如果在开发iOS内购的时候,你一定会遇到购买Consumable
类物品的需求,比如购买游戏币就是一个很经典的使用场景。最近在测试购买这种消耗品的时候,发现遇到了一个非常奇怪的问题,当你重复购买游戏币的时候,系统提示
This In-App Purchase has already been bought. It will be restored for free.
该物品已经购买过了,直接恢复即可。
当你在完成一笔交易的时候,调用StoreKit.SKPaymentQueue
的finishTransaction
就可以将这个交易标记为已购买,之后应该会没有障碍的继续购买Consumable
类的商品。
那么现在这是什么情况的?让人非常费解。
幸好发现了这个和我遇到一样问题的开发者,This In-App Purchase Has Aready Been Bought
他也提到,
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
一直没有被调用,并且显示已经购买
的对话框。
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的问题)。
SKPaymentTransactionObserver
没有被调用,其实是因为已经有一个了Observer
存在了。
解决方案也比较简单,就是在初始化第三方软件之前,来添加我们的Queue。
因为我在工程里引用了第三方的支付库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
}
}
然后就大功告成了。