I have a macOS app with auto-renewable subscription. I'm reading the docs and cannot fully understand the concept. According to the docs I have to add and observer to the payment queue. I have to provide a restore function to restore a purchase if the app was reinstalled. My observer is listening to the queue and it gets restored transactions once I call SKPaymentQueue.default().restoreCompletedTransactions() method. However, I cannot see if the subscription expired or not just using the observer. Transaction objects which I reecive in the payment queue have only some abstract transaction ID.
The docs recommend to validate a receipt. I'm sending base64 encoded receipt to my server which in turns sends it to verifyReceipt endpoint. Even if I send an old receipt, Apple responds with JSON containing latest_receipt_info where I can see the current status of subscription and it's expiration date. I can assume that subscription is not active if expiration date is earlier than the current date.
The question is why I have to call SKPaymentQueue.default().restoreCompletedTransactions() method to restore a purchase if I can refresh the receipt (if it's missing) and send it to my server and get the recent info? It seems to me that it is redundant. So my usage is:
Did I clearly understood the concept or am I missing something here because I don't see the benefit of calling SKPaymentQueue.default().restoreCompletedTransactions() method?
Your understanding is correct. The restoreCompletedTransactions()
method will save you from having to perform receipt validation on every launch of the application, which may end up getting expensive, and only do it if a user explicitly triggers it. There are also cases during a receipt refresh where a user may be prompted to enter their Apple login, which could be a confusing experience if this is triggered programatically.
Ideally you save the entire receipt file on your server and perform the receipt validation every 12-24 hours server-side as you mentioned. This lets you keep the subscription status up-to-date regardless of whether the user is opening the app or not. Then on every application launch you can make a lightweight call to your backend to check the subscription status instead of a complete receipt validation request on every launch.