Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restore the correct transaction when using Auto-Renewable In-App Purchases?

This question is regarding Auto-Renewable IAPs and how they should be restored. These links: this and this have not helped me unfortunately.

In my app I have users subscribing to Auto-Renewable In-App Purchases. They can subscribe either 1, 6 or 12 months.

When they subscribe, the transaction receipt is sent to my server for later validation. I do not validate the receipt immediately since it would slow down the user experience (a receipt validation query to apples servers takes about 1 - 2 seconds for me). Instead, I use the naive approach and provide the content that the users subscribed to, without any direct receipt verification. I schedule a cron job to validate every user's receipt once a day and revokes privileges upon outdated receipts.

Now since apples guidelines clearly state that a restore functionality is required for applications with auto-renewable subscriptions, I have chosen to implement that.

When I try to restore the purchases in sandbox mode, using:

[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];

I obtain not only current subscriptions, but all previous subscriptions(including outdated ones) in the callback to:

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

Currently I have tried my IAPs about 30 times, which means that the above method is sent 30 different transactions(outdated and active). For each of these transactions I upload the transactions receipt to my web service for later verification.

Now. Should it happen that the last transaction has an outdated receipt(but the second to last transaction was actually valid), it would overwrite the current(valid) receipt for the current user and thereby revoke the privileges for the user falsely.

Basically my problem is that when calling restoreCompletedTransactions I obtain a list of both outdated and active transactions. And on the server-side they might invalidate each other. Optimally, I would like to only retrieve one transaction(The most relevant) and have that receipt sent to my server for later validation.

All in all I guess my main question is:

How can I make sure that only an active(i.e. the most current) transaction is restored?

like image 564
Eyeball Avatar asked Mar 08 '14 11:03

Eyeball


People also ask

How do I restore in-app purchases?

To restore your purchases:Open the drawer from the upper left corner of the screen and select Support. Select Purchases and Paid App from the menu. Tap on the menu option, located in the upper right-hand corner of the screen. Tap on Recover Paid App.

What does restore mean for in-app purchases?

Restoring purchases is a mechanism by which your user can restore their in-app purchases, reactivating any content that had previously been purchased from the same store account (Apple, Google, or Amazon).

How do I check in-app purchase for auto renewable?

Go to App Store Connect and add another auto-renewable subscription product. When prompted to choose the subscription group for your new product, choose the same PoohWisdomSubs group you created earlier.


1 Answers

My solution: retrieve the receipt and validate it against your productIdentifiers. Using SKPaymentQueue.defaultQueue().restoreCompletedTransactions() for auto-renewable subscriptions does not make sense because:

  1. takes too long because it causes receipt validation to be called way too many times (once for each transaction in the past)
  2. may cause a valid transaction validation to be overwritten by a subsequent failed transaction

For example, if you have three durations for your auto-renewable subscription, just validate the receipt once against the three productIdentifiers associated with the three subscription durations.

like image 180
RawMean Avatar answered Oct 29 '22 14:10

RawMean