I'm implementing a monthly and yearly auto-renewing subscription alongside several non-consumable IAPs. After quite a lot of documentation and SO reading, I've landed on the following conclusions:
The app receipt at
Bundle.main.appStoreReceiptURL
only needs to be refreshed if missing or invalid. It does not need to be refreshed if there is a file present atBundle.main.appStoreReceiptURL
. (Source: "Use [SKReceiptRefreshRequest
] to request a new receipt if the receipt is invalid or missing")The initial purchase of a non-consumable or auto-renewing subscription product can be detected using
paymentQueue(updatedTransactions:)
only. No need to verify (i.e., decode) the receipt at this time, as I'm not worried about significant fraud.Receipt verification on each launch of the app is sufficient to detect expired or auto-renewed subscriptions via the
latest_receipt_info->expires_date_ms
andreceipt->request_date_ms
fields. (This information is used to a) revoke the user's subscription privileges if their subscription has expired, and b) to update the "Subscription renews on [date]" text in the app.)Receipt verification on each launch of the app is sufficient to detect cancelled subscriptions. This will be detected via the
pending_renewal_info->auto_renew_status
fields. (This information is used to display "Subscription expires on [date]" text in app).Restore purchases (
SKPaymentQueue.default().restoreCompletedTransactions()
) can be used to restore non-consumable purchases, but isn't sufficient to restore subscriptions (no expiry date information). Receipt verification on launch is enough to ensure subscriptions are restored. (That said, though redundant, a "restore purchases" button press by the user can also trigger a receipt verification pass.)The "active subscription" is found via
pending_renewal_info->auto_renew_product_id
, and represents their most recent subscription selection. This is used to display the price/duration of the next subscription period to the user.
The implicit assumption in 3 and 4 is that the call to verifyReceipt
will retrieve any new information about the subscription. In other words, if a) a monthly subscription starts today, and b) no receipt refresh is manually performed at any point afterwards, then c) verifying the receipt in just over a month will still give me an updated latest_receipt_info->expires_date_ms
value.
Are there any conceptual or practical oversights here?