恢复购买:非消费品

我已经完成了一个小应用程序,我有一个非消耗品购买选项。 它在App Store上。

购买产品运行正常。 这是我的恢复购买function,似乎什么都不做。

我已经为恢复购买@IBAction添加了这个代码:

 @IBAction func restorePurchases(sender: AnyObject) { SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } 

但是当我点击还原购买button时,什么也没有发生。

我想我必须添加一个函数来检查恢复是否成功。 我打算修改以下代码:

 @IBAction func restorePurchases(sender: AnyObject) { SKPaymentQueue.defaultQueue().addTransactionObserver(self) SKPaymentQueue.defaultQueue().restoreCompletedTransactions() } func paymentQueue(queue: SKPaymentQueue!, updatedTransactions transactions: [AnyObject]!) { for transaction:AnyObject in transactions { if let trans:SKPaymentTransaction = transaction as? SKPaymentTransaction{ switch trans.transactionState { case .Restored: SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction) var alert = UIAlertView(title: "Thank You", message: "Your purchase(s) were restored.", delegate: nil, cancelButtonTitle: "OK") alert.show() break; case .Failed: SKPaymentQueue.defaultQueue().finishTransaction(transaction as SKPaymentTransaction) var alert = UIAlertView(title: "Sorry", message: "Your purchase(s) could not be restored.", delegate: nil, cancelButtonTitle: "OK") alert.show() break; default: break; } } } 

这会做诡计吗?

我已经完成了与恢复购买交易有关的每一个线索,而且我的研究使我得到了上述结论。 所以我不认为这是一个问题的重复,但也许可以澄清如何成功恢复面临类似情况的其他人的采购。

你的代码大部分看起来相当不错,虽然有些部分似乎来自较老的教程。 你应该做一些改变,其中一个是你需要再次调用你的unlockProduct函数。

这是我使用的代码(Swift 3)。

 /// Updated transactions func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { for transaction in transactions { switch transaction.transactionState { case .purchasing: // Transaction is being added to the server queue. case .purchased: // Transaction is in queue, user has been charged. Client should complete the transaction. defer { queue.finishTransaction(transaction) } let productIdentifier = transaction.payment.productIdentifier unlockProduct(withIdentifier: productIdentifier) case .failed: // Transaction was cancelled or failed before being added to the server queue. defer { queue.finishTransaction(transaction) } let errorCode = (transaction.error as? SKError)?.code if errorCode == .paymentCancelled { print("Transaction failed - user cancelled payment") } else if errorCode == .paymentNotAllowed { // Will show alert automatically print("Transaction failed - payments are not allowed") } else { print("Transaction failed - other error") // Show alert with localised error description } case .restored: // Transaction was restored from user's purchase history. Client should complete the transaction. defer { queue.finishTransaction(transaction) } if let productIdentifier = transaction.original?.payment.productIdentifier { unlockProduct(withIdentifier: productIdentifier) } case .deferred: // The transaction is in the queue, but its final status is pending external action // eg family member approval (FamilySharing). // DO NOT freeze up app. Treate as if transaction has not started yet. } } } 

比使用委托方法显示还原警报

 /// Restore finished func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { guard queue.transactions.count != 0 else { // showAlert that nothing restored return } // show restore successful alert } /// Restore failed func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: NSError) { /// handle the restore error if you need to. } 

解锁产品只是一种方法,我相信你已经拥有了。

  func unlockProduct(withIdentifier productIdentifier: String) { switch productIdentifier { /// unlock product for correct ID } } 

作为一个侧面说明,你应该移动这一行

  SKPaymentQueue.default().add(self) 

退出你的恢复和购买function,并把它放在viewDidLoad。

Applebuild议您在应用程序启动后立即添加事务观察器,并且仅在closures应用程序时将其删除。 很多教程不幸的不教你这个正确的。 这样你就不能确定任何不完整的交易,例如由于networking错误,总是会恢复正常。

https://developer.apple.com/library/content/technotes/tn2387/_index.html

在我真正的项目中,我的IAP代码在Singleton类中,所以我实际上使用委托来将unlockProduct方法转发到处理gameData的类。 我也可以确保在应用程序启动时添加观察者。

希望这可以帮助