iOS 應用程式內購設置 with react-native-iap
第一次弄 iOS 的應用程式內購,紀錄一下測試的時候踩到的各種坑
測試 code 是根據 react-native IAP 套件提供的 Demo code
Empty product list
根據這篇文章建立好所有測試環境,包含:
- 在 App Store Connect > Features > In-App Purchase 建立測試用產品,要記得 localization 的部分產品名稱跟敘述都要加,sandbox user 為了測試方便是設定成 English (US),在商品的描述那裡要記得加上 English(US)的相關敘述。
- 產品的審核用圖(Metadata)大小 StackOverflow 上有人測說 1334x750 會成功。
- 在 Users and Access > Sandbox Testers 加入測試用帳號(不用是真實 email,用 sandbox@xxx.com 之類的就行了)
- 設定相關稅務資料,注意 iOS 有分 FreeApps 和 PaidApps 的稅務資料,兩個都要填,不然像我因為公司 App 本身已經在架上(所以 FreeApps 的部分有填),以為稅務那些都有設定好(但其實漏掉 PaidApps 部分),結果測試時就拿到空的產品列表。稅務設定完就會顯示 Active (Pending User info) ,這時候就能成功獲取產品列表了。
Cannot connect to iTunes Store
用 Sandbox 帳號測試的時候,按下購買在跳出輸入帳號密碼之後,就會顯示這個錯誤訊息而無法進行購買。
下面整理了幾種可能的錯誤原因
- The sandbox may be unreachable. Check the System Status for the status of the iTunes Sandbox. (有可能是 Sandbox 剛好爆掉)
- Your app does not have a bundle version (CFBundleVersion). See Setting the Version Number and Build String for more information.
- Your app is running in the Simulator, which does not support in-app purchase.
- You are attempting to purchase a product that is unavailable for sale. See Query the App Store for product information before presenting your app’s store UI for more information. (不過我自己測試 Sandbox user 就算沒有勾選發佈也能測試成功)
不過這些都對我沒用,於是我花了點時間直接回到原生 code 去印出全部的錯誤訊息是長這樣:
Error Domain=SKErrorDomain Code=0 “Operation could not be completed. (SKErrorDomain error 0.)”
藉由這個錯誤訊息多查到了:
- Make sure you have placed the correct “Product Identifier”.If that’s the case, then you’ll get error 0 shortly after calling -[SKPaymentQueue addPayment:], before you get the popup asking you to confirm payment.
- 如果是這種情形就要確認 app bundle ID 跟 itunes connect 上的 bundle ID 是一致的
- Your test user has become invalidated. This can happen if you accidentally log into the App Store with your test user. When this happens, you’ll get error 0 after entering your password to confirm your payment.
- 如果是這種只能重新創立一個沒登入過 itunes store 的 sandbox 帳號
我自己的狀況是我一開始看說明以為要真的在設定那裡登入 Sandbox 使用者帳號,後來看到這個,換了帳號之後發現 Sandbox 使用者沒有真的登出(在付款的時候會顯示舊的 sandbox 帳號的付款資訊,然後一樣出現失敗抓不到 transaction receipt)。
但是明明我 itunes & app Store 已經登出,而且 Apple ID 那裡也是登出狀態, 後來才發現 Sandbox 帳號控制的地方(iOS 12.4)在設定 > 人名(Apple ID)> 下方(要先登入過 Sandbox user 的帳號才會出現)
這裡登出後就測試 IAP 就可以成功拿到 transaction receipt 啦!
拿到 transaction receipt 之後,把結果回傳給 server (官方建議,但是要用手機本身驗證其實也行),讓 server 去驗證之後再把結果丟回給 app 就可以完成所有 IAP 的步驟了。
測試的連結:https://sandbox.itunes.apple.com/verifyReceipt
正式的連結:https://buy.itunes.apple.com/verifyReceipt
官方回傳驗證 transaction receipt status 的文件:https://developer.apple.com/documentation/appstorereceipts/status
# python3 sample code for verifying receiptimport http.client, json
receipt = "/* transaction receipt got from IAP */"body = json.dumps({"receipt-data": receipt})/* change to buy.itunes.apple.com on live server */
connect = http.client.HTTPSConnection("sandbox.itunes.apple.com")
headers = {"Content-type": "application/json"}connect.request("POST", "/verifyReceipt", body)
result = connect.getresponse()
data = result.read()
connect.close()
decoded_data = json.loads(data)print(decoded_data)
官方其實是建議先連 live server,收到 status 21007 的話再去連 sandbox server。
最後補上過程中有參考到的文件: