若是在開發iOS內購的時候,你必定會遇到購買Consumable
類物品的需求,好比購買遊戲幣就是一個很經典的使用場景。最近在測試購買這種消耗品的時候,發現遇到了一個很是奇怪的問題,當你重複購買遊戲幣的時候,系統提示html
This In-App Purchase has already been bought. It will be restored for free.
該物品已經購買過了,直接恢復便可。git
當你在完成一筆交易的時候,調用StoreKit.SKPaymentQueue
的finishTransaction
就能夠將這個交易標記爲已購買,以後應該會沒有障礙的繼續購買Consumable
類的商品。github
那麼如今這是什麼狀況的?讓人很是費解。
幸虧發現了這個和我遇到同樣問題的開發者,This In-App Purchase Has Aready Been Boughtswift
他也提到,app
Apple has designed the payment queue in such a way as to enable apps to fulfill a purchase before completing - with finishTransaction being the indication that fulfillment is complete. In the case that a failure occurs during fulfillment, the app can recover when SKPaymentQueue calls the app’s observer again.This is all good and fine - except many developers have encountered a situation where this process breaks down. Their SKPaymentTransactionObserver is never called again, and the user is presented with the dreaded 「already bought」 dialog and no apparent way to fix the problem.測試
SKPaymentTransactionObserver
一直沒有被調用,而且顯示已經購買
的對話框。this
A library (in my case Firebase analytics) is adding its own SKPaymentTransactionObserver before your app adds its own observer. As a result, SKPaymentQueue is calling that observer first, and by the time your observer is added, as far as the payment queue is concerned it has already delivered the notification and there’s nothing left to do.
他幫我找到了緣由——第三方軟件(和我同樣就是Firebase的問題)。rest
SKPaymentTransactionObserver
沒有被調用,實際上是由於已經有一個了Observer
存在了。code
解決方案也比較簡單,就是在初始化第三方軟件以前,來添加咱們的Queue。server
由於我在工程裏引用了第三方的支付庫jinSasaki/InAppPurchase因此下面就用這個爲例,簡單的寫一下解決方案。
class AppDelegate: UIResponder, UIApplicationDelegate { // 初始化InAppPurchase let iap = InAppPurchase.default func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // 首先在這邊加入Transaction Observer iap.addTransactionObserver() // 而後再開啓Firebase的設置 FirebaseApp.configure() return true } }
而後就大功告成了。