* Add methods to finish transactions * Add a method to get the product descriptions from the App Store * Improve the documentation of a transaction structure * Add a tutorial for In App Purchase * Fix typo in In-App Purchase tutorial * Fix style of In-App Purchase files * Fix In-App-Purchase product structure conversion in amr64 * Fix code style in In-App Purchase tutorial documentation * Fix typos in In-App Purchase documentation * Fix typo in In-App Purchase spec * Slight style fixes
		
			
				
	
	
		
			125 lines
		
	
	
		
			No EOL
		
	
	
		
			4.1 KiB
			
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			No EOL
		
	
	
		
			4.1 KiB
			
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# In-App Purchase (macOS)
 | 
						||
 | 
						||
## Preparing
 | 
						||
 | 
						||
### Paid Applications Agreement
 | 
						||
If you haven't already, you’ll need to sign the Paid Applications Agreement and set up your banking and tax information in iTunes Connect. 
 | 
						||
 | 
						||
[iTunes Connect Developer Help: Agreements, tax, and banking overview](https://help.apple.com/itunes-connect/developer/#/devb6df5ee51)
 | 
						||
 | 
						||
### Create Your In-App Purchases
 | 
						||
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.
 | 
						||
 | 
						||
[iTunes Connect Developer Help: Create an in-app purchase](https://help.apple.com/itunes-connect/developer/#/devae49fb316)
 | 
						||
 | 
						||
 | 
						||
### Change the CFBundleIdentifier
 | 
						||
 | 
						||
To test In-App Purchase in development with Electron you'll have to change the `CFBundleIdentifier` in `node_modules/electron/dist/Electron.app/Contents/Info.plist`. You have to replace `com.github.electron` by the bundle identifier of the application you created with iTunes Connect.
 | 
						||
 | 
						||
```xml
 | 
						||
<key>CFBundleIdentifier</key>
 | 
						||
<string>com.example.app</string>
 | 
						||
```
 | 
						||
 | 
						||
 | 
						||
## Code example
 | 
						||
 | 
						||
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 `com.example.app.product1` is `product1`). Note that you have to listen to the `transactions-updated` event as soon as possible in your app.
 | 
						||
 | 
						||
 | 
						||
```javascript
 | 
						||
const { inAppPurchase } = require('electron').remote
 | 
						||
const PRODUCT_IDS = ['id1', 'id2']
 | 
						||
 | 
						||
// Listen for transactions as soon as possible.
 | 
						||
inAppPurchase.on('transactions-updated', (event, transactions) => {
 | 
						||
  if (!Array.isArray(transactions)) {
 | 
						||
    return
 | 
						||
  }
 | 
						||
 | 
						||
  // Check each transaction.
 | 
						||
  transactions.forEach(function (transaction) {
 | 
						||
    var payment = transaction.payment
 | 
						||
 | 
						||
    switch (transaction.transactionState) {
 | 
						||
      case 'purchasing':
 | 
						||
        console.log(`Purchasing ${payment.productIdentifier}...`)
 | 
						||
        break
 | 
						||
      case 'purchased':
 | 
						||
 | 
						||
        console.log(`${payment.productIdentifier} purchased.`)
 | 
						||
 | 
						||
        // Get the receipt url.
 | 
						||
        let receiptURL = inAppPurchase.getReceiptURL()
 | 
						||
 | 
						||
        console.log(`Receipt URL: ${receiptURL}`)
 | 
						||
 | 
						||
        // Submit the receipt file to the server and check if it is valid.
 | 
						||
        // @see https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
 | 
						||
        // ...
 | 
						||
        // If the receipt is valid, the product is purchased
 | 
						||
        // ...
 | 
						||
 | 
						||
        // Finish the transaction.
 | 
						||
        inAppPurchase.finishTransactionByDate(transaction.transactionDate)
 | 
						||
 | 
						||
        break
 | 
						||
      case 'failed':
 | 
						||
 | 
						||
        console.log(`Failed to purchase ${payment.productIdentifier}.`)
 | 
						||
 | 
						||
        // Finish the transaction.
 | 
						||
        inAppPurchase.finishTransactionByDate(transaction.transactionDate)
 | 
						||
 | 
						||
        break
 | 
						||
      case 'restored':
 | 
						||
 | 
						||
        console.log(`The purchase of ${payment.productIdentifier} has been restored.`)
 | 
						||
 | 
						||
        break
 | 
						||
      case 'deferred':
 | 
						||
 | 
						||
        console.log(`The purchase of ${payment.productIdentifier} has been deferred.`)
 | 
						||
 | 
						||
        break
 | 
						||
      default:
 | 
						||
        break
 | 
						||
    }
 | 
						||
  })
 | 
						||
})
 | 
						||
 | 
						||
// Check if the user is allowed to make in-app purchase.
 | 
						||
if (!inAppPurchase.canMakePayments()) {
 | 
						||
  console.log('The user is not allowed to make in-app purchase.')
 | 
						||
}
 | 
						||
 | 
						||
// Retrieve and display the product descriptions.
 | 
						||
inAppPurchase.getProducts(PRODUCT_IDS, (products) => {
 | 
						||
  // Check the parameters.
 | 
						||
  if (!Array.isArray(products) || products.length <= 0) {
 | 
						||
    console.log('Unable to retrieve the product informations.')
 | 
						||
    return
 | 
						||
  }
 | 
						||
 | 
						||
  // Display the name and price of each product.
 | 
						||
  products.forEach((product) => {
 | 
						||
    console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)
 | 
						||
  })
 | 
						||
 | 
						||
  // Ask the user which product he/she wants to purchase.
 | 
						||
  // ...
 | 
						||
  let selectedProduct = products[0]
 | 
						||
  let selectedQuantity = 1
 | 
						||
 | 
						||
  // Purchase the selected product.
 | 
						||
  inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity, (isProductValid) => {
 | 
						||
    if (!isProductValid) {
 | 
						||
      console.log('The product is not valid.')
 | 
						||
      return
 | 
						||
    }
 | 
						||
 | 
						||
    console.log('The payment has been added to the payment queue.')
 | 
						||
  })
 | 
						||
})
 | 
						||
``` |