1"use strict";(self.webpackChunkelectronjs=self.webpackChunkelectronjs||[]).push([["26278"],{57034(e,n,t){t.r(n),t.d(n,{metadata:()=>a,default:()=>l,frontMatter:()=>s,contentTitle:()=>o,toc:()=>p,assets:()=>c});var a=JSON.parse('{"id":"latest/tutorial/in-app-purchases","title":"In-App Purchases","description":"Add in-app purchases to your Mac App Store (MAS) application","source":"@site/docs/latest/tutorial/in-app-purchases.md","sourceDirName":"latest/tutorial","slug":"/latest/tutorial/in-app-purchases","permalink":"/docs/latest/tutorial/in-app-purchases","draft":false,"unlisted":false,"editUrl":"https://github.com/electron/electron/edit/main/docs/tutorial/in-app-purchases.md","tags":[],"version":"current","frontMatter":{"title":"In-App Purchases","description":"Add in-app purchases to your Mac App Store (MAS) application","slug":"in-app-purchases","hide_title":true},"sidebar":"docs","previous":{"title":"Device Access","permalink":"/docs/latest/tutorial/devices"},"next":{"title":"Keyboard Shortcuts","permalink":"/docs/latest/tutorial/keyboard-shortcuts"}}'),r=t(74848),i=t(28453);let s={title:"In-App Purchases",description:"Add in-app purchases to your Mac App Store (MAS) application",slug:"in-app-purchases",hide_title:!0},o="In-App Purchases",c={},p=[{value:"Preparing",id:"preparing",level:2},{value:"Paid Applications Agreement",id:"paid-applications-agreement",level:3},{value:"Create Your In-App Purchases",id:"create-your-in-app-purchases",level:3},{value:"Change the CFBundleIdentifier",id:"change-the-cfbundleidentifier",level:3},{value:"Code example",id:"code-example",level:2}];function d(e){let n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"in-app-purchases",children:"In-App Purchases"})}),"\n",(0,r.jsx)(n.h2,{id:"preparing",children:"Preparing"}),"\n",(0,r.jsx)(n.h3,{id:"paid-applications-agreement",children:"Paid Applications Agreement"}),"\n",(0,r.jsx)(n.p,{children:"If you haven't already, you\u2019ll need to sign the Paid Applications Agreement and set up your banking and tax information in iTunes Connect."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://help.apple.com/itunes-connect/developer/#/devb6df5ee51",children:"iTunes Connect Developer Help: Agreements, tax, and banking overview"})}),"\n",(0,r.jsx)(n.h3,{id:"create-your-in-app-purchases",children:"Create Your In-App Purchases"}),"\n",(0,r.jsx)(n.p,{children:"Then, you'll need to configure your in-app purchases in iTunes Connect, and include details such as name, pricing, and description that highlights the features and functionality of your in-app purchase."}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.a,{href:"https://help.apple.com/itunes-connect/developer/#/devae49fb316",children:"iTunes Connect Developer Help: Create an in-app purchase"})}),"\n",(0,r.jsx)(n.h3,{id:"change-the-cfbundleidentifier",children:"Change the CFBundleIdentifier"}),"\n",(0,r.jsxs)(n.p,{children:["To test In-App Purchase in development with Electron you'll have to change the ",(0,r.jsx)(n.code,{children:"CFBundleIdentifier"})," in ",(0,r.jsx)(n.code,{children:"node_modules/electron/dist/Electron.app/Contents/Info.plist"}),". You have to replace ",(0,r.jsx)(n.code,{children:"com.github.electron"})," by the bundle identifier of the application you created with iTunes Connect."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-xml",children:"<key>CFBundleIdentifier</key>\n<string>com.example.app</string>\n"})}),"\n",(0,r.jsx)(n.h2,{id:"code-example",children:"Code example"}),"\n",(0,r.jsxs)(n.p,{children:["Here is an example that shows how to use In-App Purchases in Electron. You'll have to replace the product ids by the identifiers of the products created with iTunes Connect (the identifier of ",(0,r.jsx)(n.code,{children:"com.example.app.product1"})," is ",(0,r.jsx)(n.code,{children:"product1"}),"). Note that you have to listen to the ",(0,r.jsx)(n.code,{children:"transactions-updated"})," event as soon as possible in your app."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-js",children:"// Main process\nconst { inAppPurchase } = require('electron')\n\nconst PRODUCT_IDS = ['id1', 'id2']\n\n// Listen for transactions as soon as possible.\ninAppPurchase.on('transactions-updated',
1(event, transactions) => {\n if (!Array.isArray(transactions)) {\n return\n }\n\n // Check each transaction.\n for (const transaction of transactions) {\n const payment = transaction.payment\n\n switch (transaction.transactionState) {\n case 'purchasing':\n console.log(`Purchasing ${payment.productIdentifier}...`)\n break\n\n case 'purchased': {\n console.log(`${payment.productIdentifier} purchased.`)\n\n // Get the receipt url.\n const receiptURL = inAppPurchase.getReceiptURL()\n\n console.log(`Receipt URL: ${receiptURL}`)\n\n // Submit the receipt file to the server and check if it is valid.\n // @see https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html\n // ...\n // If the receipt is valid, the product is purchased\n // ...\n\n // Finish the transaction.\n inAppPurchase.finishTransactionByDate(transaction.transactionDate)\n\n break\n }\n\n case 'failed':\n console.log(`Failed to purchase ${payment.productIdentifier}.`)\n\n // Finish the transaction.\n inAppPurchase.finishTransactionByDate(transaction.transactionDate)\n\n break\n case 'restored':\n console.log(`The purchase of ${payment.productIdentifier} has been restored.`)\n\n break\n case 'deferred':\n console.log(`The purchase of ${payment.productIdentifier} has been deferred.`)\n\n break\n default:\n break\n }\n }\n})\n\n// Check if the user is allowed to make in-app purchase.\nif (!inAppPurchase.canMakePayments()) {\n console.log('The user is not allowed to make in-app purchase.')\n}\n\n// Retrieve and display the product descriptions.\ninAppPurchase.getProducts(PRODUCT_IDS).then((products) => {\n // Check the parameters.\n if (!Array.isArray(products) || products.length <= 0) {\n console.log('Unable to retrieve the product information.')\n return\n }\n\n // Display the name and price of each product.\n for (const product of products) {\n console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)\n }\n\n // Ask the user which product they want to purchase.\n const selectedProduct = products[0]\n const selectedQuantity = 1\n\n // Purchase the selected product.\n inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity).then((isProductValid) => {\n if (!isProductValid) {\n console.log('The product is not valid.')\n return\n }\n\n console.log('The payment has been added to the payment queue.')\n })\n})\n"})})]})}function l(e={}){let{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},28453(e,n,t){t.d(n,{R:()=>s,x:()=>o});var a=t(96540);let r={},i=a.createContext(r);function s(e){let n=a.useContext(i);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.