IAP - Restore purchase in a auto-renewable with S2S integration scenario

We have a pretty simple setup:

  • iOS 14 as min target
  • only auto-renewable subscriptions
  • Apple S2S integration

Here is, in short, our flow:

APP: We register a PaymentQueue observer early in the application lifecycle and whenever a newly purchased transaction is received, we send the receipt to the backend for validation. This happens regardless of whether the purchase was user-initiated (i.e. for an actual purchase) or not (i.e. autorenewal).

BACKEND: The backend receives the receipt, validates it against verifyReceipt Apple's endpoint, and stores relevant information into the database. This information gets sent back to the app over time in order to let it figure out whether the user is subscribed, and block relevant content if he is not.

Also, we continue poll Apple's endpoint over time as suggested in the well-known WWDC 2018 session.

S2S SERVICE: whenever we receive a notification from Apple, we take the latest receipt base64 data, validate it against verifyReceipt endpoint, and then we use the response to figure out the latest user status and update relevant fields in our backend, including locking/unlocking paid content. This is done differently depending on the notification type, but I don't think it's relevant here.

All that said, I can't figure out the use case for the in-app Restore Purchases process. Do we really need it?

Thanks.

Accepted Reply

To the note on Restore Purchases, this is a App Review requirement and does allow customers a consistent and safe way to force an app to check their current status and purchases. Please see https://developer.apple.com/app-store/review/guidelines/#in-app-purchase

  • Well... that's what I guessed. Indeed, we have it implemented. I was simply wondering whether there's any use case for it in our scenario. Thank you again.

Add a Comment

Replies

That is great to hear you are initializing the TransactionObserver on launch, sounds like you are all set to not miss any transactions that can be initiated or completed outside of your application - such as code redemptions, interrupted transactions, approved Ask To buy requests, etc.

In regards to polling verifyReceipt, we suggest these not be hard scheduled and instead be more data and event driven to reduce requests and maximize value. A couple of examples would be to poll on subscribers expires date timestamp or optionally on app launches IF status hasn't already been checked in last 8-days. But with the coming release of Server Notifications v2 you will soon be able to remove the need to poll entirely as you'll receive notifications for all user events that impact the subscribers status in anyway. Events will not always result in turning service on or off but some may be about future plan changes, redeemed offers, soft cancelling, etc.

When receiving Server Notifications there is no need to take that receipt and send that to verifyReceipt - that is an extra and redundant action. The notification itself contains the transactions in the unified_receipt object and the notification type itself gives you a hint as to the action to take. For example: DID_RENEW notes there was a successful renewal so you should see a new transaction period/service to apply to the existing subscriber. Or for CANCEL/REFUND/REVOKE types you will see a cancellation_Date/revocation_date populated for a past transaction. So no need to use verifyReceipt.

But it should be said that with v2 notifications the type + subtype will significantly increase the coverage of user events and simplify the logic to know what to do for each notification type + subtype received. The notification type + optional subtype will indicate the exact user event, for example if a former subscriber reactivates service from the sam subscription group, you'll receive a notification of SUBSCRIBED.RESUBSCRIBE [type.subtype]. Or if a Subscriber soft cancels you'll receive a notification of DID_CHANGE_RENEWAL_STATUS.AUTO_RENEW_DISABLED or once a subscription expires as they had soft cancelled, then you'll receive EXPIRED.VOLUNTARY.

Note: I put the notification type and subtype together above to simplify but please see the WWDC for info on the expected payload of v2 server notifications and documentation will be coming soon. https://developer.apple.com/videos/play/wwdc2021/10174?time=909

  • First and foremost: thank you for the reply.

    Regarding polling: of course, we have proper logic that follows suggestions of WWDC 2018 session. Anyway, if we'll be able to get rid of it in the near future it'll be even better.

    Regarding double verification in S2S, that's simply an extra-security measure: if someone gets access to the shared secret, we are still able to verify we are receiving valid and safe data. But OK, we'll consider getting rid of it as well.

Add a Comment

To the note on Restore Purchases, this is a App Review requirement and does allow customers a consistent and safe way to force an app to check their current status and purchases. Please see https://developer.apple.com/app-store/review/guidelines/#in-app-purchase

  • Well... that's what I guessed. Indeed, we have it implemented. I was simply wondering whether there's any use case for it in our scenario. Thank you again.

Add a Comment