Search code examples
iosswiftstorekit

Restoring unprocessed SKPaymentTransaction for non-renewing subscription


In my app I want to implement non-renewing subscriptions. I have set up (I believe correctly) my logic. I place the observer in the app delegate and then in the class that implements SKPaymentTransactionObserver I implement the following function:

func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { }

Within this method I loop through all the updatedTransactions and I check every transactionState, and accordingly I implement my logic.

What troubles me is this: when the transaction is successful I have to contact our servers to update the user's profile and add more days to his/her subscription. This means that I have to call SKPaymentQueue.default().finishTransaction(transaction) after I have received a successful response from our servers. However there is a chance that something goes wrong from the moment that Apple's servers send that the transaction has been completed, until our servers respond.

A shortcut would be to mark the transaction as finished as soon as Apple responds, but by reading the documentation, it doesn't seem correct. How can I restore an unprocessed transaction? (in the case our servers do not respond and the SKPaymentQueue.default().finishTransaction(transaction) is not called).

Thank you in advance.


Solution

  • You should mark the transaction as finished only after your server acknowledges it.

    If something does go wrong (let's say a crash occurs) between the time the transaction succeeds but your server hasn't seen it, the transaction will stay incomplete, and will be accessible in SKPaymentQueue.default.transactions right after you add the observer to the queue.

    You can then grab those transactions or the receipt and send it to your server for another attempt at increasing the duration of their subscription.

    Additionally, from Apple's docs:

    For example, consider the case of a user buying something in your app right before going into a tunnel. Your app isn’t able to deliver the purchased content because there’s no network connection. The next time your app is launched, StoreKit calls your transaction queue observer again and delivers the purchased content at that time. Similarly, if your app fails to mark a transaction as finished, StoreKit calls the observer every time your app is launched until the transaction is properly finished.