As discussed in this question and everywhere else, Apple now requires apps to include a means for the user to restore completed transactions for In App Purchases.
I'm all for this. The first version of my app somehow made it past review without it (I wasn't aware of this rule at the time, and/or it wasn't being enforced yet), but then I started receiving lots of e-mails from users asking about missing content (there is the Data Storage Guidelines too, and the heavy, downloadable contents aren't backed up).
So let's say I include a 'restore' button somewhere in my UI, that when tapped calls:
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
So far, so good. The user is prompted his AppleID and/or password, and the restoring process begins.
The problem I have is: If there is no transactions to restore, after the AppleID prompt essentially nothing happens in my app, and that may be confusing to the user or make the app look unresponsive or broken.
I would like to be able to display an alert view along the lines of "All purchases are up to date" or something.
Is there anything I can do in my Transaction Observer code to detect this case?
Does anybody think it would be a bad design, UX-wise?
Restoring purchases prevents you from losing all the things that have been purchased on the old devices.
Answer: A: Answer: A: It means that if you made an in-app purchase in that game but on another device you can restore those purchases with your apple ID log in credentials without having to pay again.
If you have multiple devices signed in to the same Apple ID, Restore Purchase will allow you to transfer your in-app purchases to your other devices without having to pay again. For example, if you make an in-app purchase inside an app on your iPhone, you may be able to restore that in-app purchase on your iPad.
This is still an issue in the latest SDK / xCode 8.0, Swift 3 - if a user who hasn't made any purchases attempts to 'restore', the following method:
SKPaymentQueue.default().restoreCompletedTransactions()
does not trigger the usual delegate method that handles purchases / restoring:
paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {...}
Interestingly, the method that probably should catch the error is also NOT called:
func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error){...}
And instead, the optional method is triggered, as if the restore worked fine:
func paymentQueueRestoreCompletedTransactionsFinished()
This can cause the app to look like it is hanging / not doing anything.
As discussed in the other answers, the cause of this is that the SKPaymentQueue doesn't contain any transactions.
in Swift, this problem can be overcome by using the following:
//Optional Method.
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue)
{
let transactionCount = queue.transactions.count
if transactionCount == 0
{
print("No previous transactions found")
//You can add some method to update your UI, indicating this is the problem e.g. use notification centre:
NotificationCenter.default.post(name: "restoreFailedNoPrevIAP", object: nil)
}
}
Importantly, if a user has made previous purchases, the transaction queue will not be empty, hence updateTransaction delegate method will be called, and will process the restore request normally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With