应用内购买 (macOS)

准备工作

付费应用协议

如果你还没有,你需要在 iTunes Connect 签署付费应用协议, 并设置您的银行和税务信息。

iTunes Connect 开发人员帮助: 协议、税务和银行概述

创建您的应用内购买

然后,您需要在iTunes Connect中配置您的应用内购买,并包含名称,定价和说明等详细信息,以突出显示您的应用内购买的功能。

iTunes Connect开发人员帮助:创建应用程序内购买

变更 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.

  1. <key>CFBundleIdentifier</key>
  2. <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.

  1. const { inAppPurchase } = require('electron').remote
  2. const PRODUCT_IDS = ['id1', 'id2']
  3. // Listen for transactions as soon as possible.
  4. inAppPurchase.on('transactions-updated', (event, transactions) => {
  5. if (!Array.isArray(transactions)) {
  6. return
  7. }
  8. // Check each transaction.
  9. transactions.forEach(function (transaction) {
  10. var payment = transaction.payment
  11. switch (transaction.transactionState) {
  12. case 'purchasing':
  13. console.log(`Purchasing ${payment.productIdentifier}...`)
  14. break
  15. case 'purchased':
  16. console.log(`${payment.productIdentifier} purchased.`)
  17. // Get the receipt url.
  18. let receiptURL = inAppPurchase.getReceiptURL()
  19. console.log(`Receipt URL: ${receiptURL}`)
  20. // Submit the receipt file to the server and check if it is valid.
  21. // @see https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
  22. // ...
  23. // If the receipt is valid, the product is purchased
  24. // ...
  25. // Finish the transaction.
  26. inAppPurchase.finishTransactionByDate(transaction.transactionDate)
  27. break
  28. case 'failed':
  29. console.log(`Failed to purchase ${payment.productIdentifier}.`)
  30. // Finish the transaction.
  31. inAppPurchase.finishTransactionByDate(transaction.transactionDate)
  32. break
  33. case 'restored':
  34. console.log(`The purchase of ${payment.productIdentifier} has been restored.`)
  35. break
  36. case 'deferred':
  37. console.log(`The purchase of ${payment.productIdentifier} has been deferred.`)
  38. break
  39. default:
  40. break
  41. }
  42. })
  43. })
  44. // Check if the user is allowed to make in-app purchase.
  45. if (!inAppPurchase.canMakePayments()) {
  46. console.log('The user is not allowed to make in-app purchase.')
  47. }
  48. // Retrieve and display the product descriptions.
  49. inAppPurchase.getProducts(PRODUCT_IDS, (products) => {
  50. // Check the parameters.
  51. if (!Array.isArray(products) || products.length <= 0) {
  52. console.log('Unable to retrieve the product informations.')
  53. return
  54. }
  55. // Display the name and price of each product.
  56. products.forEach((product) => {
  57. console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)
  58. })
  59. // Ask the user which product he/she wants to purchase.
  60. // ...
  61. let selectedProduct = products[0]
  62. let selectedQuantity = 1
  63. // Purchase the selected product.
  64. inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity, (isProductValid) => {
  65. if (!isProductValid) {
  66. console.log('The product is not valid.')
  67. return
  68. }
  69. console.log('The payment has been added to the payment queue.')
  70. })
  71. })