This is an old thread, but I find the answer incomplete, which can be misleading, and Apple docs are a bit vague on the subject. The problem is how we define a 'failed' transaction.
We can identify many states:
SKPaymentTransactionStateFailed
You get notified Apple noticed something went wrong (i.e. user cancelled, credit card declined, the kid is not authorized by its father to make the purchase, etc) and informs you of the event.
You must call finishTransaction
SKPaymentTransactionStatePurchased
We can split this one in multiples ones:
- Receipt validated and content delivered. You must call finishTransaction
- Receipt is invalid. There is no agreement here, as Apple docs are vague. It's 95.0% certain this is a hacked/jailbreak purchase. You could call finishTransaction to remove it from the queue and thus lighten the load on your servers (otherwise the queue will keep asking your client to revalidate). However the other 5% is that Apple servers were down and somehow they returned invalid (or you interpreted as invalid) when actually Apple servers just were temporarily down.
- This applies specially to consumable IAPs. Because once you call finishTransactions, the consumable IAP is gone from the receipt
- For non-consumable IAPs, you can safely always call finishTransaction because worst case scenario the user can tap the button to restore transactions (which you have to implement as per App Store Guidelines)
- Receipt is valid, but could not be verified for temporary reasons (e.g. your servers are down, Apple servers down, internet connection went down). You must not call finishTransaction. The payment will remain on the payment queue and it will eventually ask you to try again (note that the device that attempts to try again may be a different iPhone, if the user is logged on from multiple Apple devices). Hopefully this time the servers will be back up.
- This is a must for consumable IAPs. You can't call finishTransactions or else you'll get legit angry customers
- Once again, for non-consumable IAPs, you can safely always call finishTransaction and rely on Restore Transactions instead.
If you don't perform validation nor have server-side inventory, none of this really matters to you, since there are not many points of failure.
Without validation nor server-side inventory, after receiving SKPaymentTransactionStatePurchased you update your database on the phone's storage with the additional/unlocked content, and after that you just call finishTransactions.
SKPaymentTransactionStateRestored
Same flow as SKPaymentTransactionStatePurchased.
SKPaymentTransactionStatePurchasing
You must not call finishTransaction
SKPaymentTransactionStateDeferred
You must not call finishTransaction