Receipts not being updated for auto-renewing subscriptions

I am developing a Mac app that will support In-App Auto-Renewable Subscriptions. The problem I am having is that the receipt is never updated after a renewal period goes by. For example, if I launch the app and purchase the subscription (with a sandbox user), I get the transaction in updatedTransactions. I then check the renewal date and all is well. I am testing monthly purchases and that means after 5 minutes, the auto-renewal process should take place.

I then re-launch the app and get another call to updatedTransactions and a SKPaymentTransactionStateRestored transaction. This seems correct.


The problem is that when I check the receipt, it hasn't been updated. Not only does the IAP transaction still reflect the original renewal date (which is now expired) but if I check the actual date of the receipt file, it hasn't been touched. I've tried creating multiple new sandbox users and it just doesn't work.


I am assuming (documentation doesn't actually state this) but that when updateTransactions is called for the restore, that the system would be delivering a new receipt. Is this not the case or do I need to request it in some way.


If I let more time go by, I will continue to get the SKPaymentTransactionStateRestored states but the receipt file is never changed.


I've searched and searched on how IAP needs to work and have watched every video on the subject multiple times and can't figure this out.


This was working last week but now isn't. It's as if the sandbox store is having an issue all of a sudden.


What am I missing?? Thanks in advance!

Replies

An autorenewable in the sandbox will renew 5 times and then quit. No more auto renewals. You can create a new test user and go for 5 auto renewals again.


Perhaps your calls to updatedTransactions are the last renewal and you haven't called finishTransaction.


Try a new purchase and see if you get a new receipt (only one if the user has gotten their 5)

Thanks for your response. I am trying newly created sandbox users. The issue is that the receipt is just never updated. As mentioned, if I do a monthly subscription (with brand new user) and then run the app again after 6 mins, I get a posted notification that the restore happened. However, the receipt itself is never updated. I'm definitely calling finishTransaction after each renewal (restore).


I just discovered that it's working fine on El Cap. On Sierra, however, the receipt is just never updated.

I am experiencing the same problem under Sierra (10.12.1). Have you in the meantime found any way to get this to work under Sierra?

I would suggest that you download the StoreKitSuite sample code.

<https://developer.apple.com/library/content/samplecode/sc1991/Introduction/Intro.html>


Use the iOSInAppPurchase sample code project. Set the application bundle ID and version for the sample to match your app, and define the in app purchase identifiers in the productID.plist file. You will have to implement code to validate the applicationReceipt, but it would be interesting to see if you see the same non-renewing issue. One more thing to try. After, you validate the applicationReceipt the first time, and the status of the validation is 0, log the JSON contents. If you isolate that "latest_receipt" section of the receipt, you can try manually validating this item every 5 minutes to see if the iTunes Store Server is renewing the subscription. The latest_receipt section is only available when there is an auto-renewing subscription item in the in_app array of the applicationReceipt. It's also base64 encoded - ready for the next validation attempt.


You can manually validate the latest_receipt item using the following command


curl -d '{ "password":"yyyy" "receipt-data": "xxxx"}' https://sandbox.itunes.apple.com/verifyReceipt


where yyyy is the shared-secret for your developer account and xxxx is the contents of the latest_receipt field. If the auto-renewing subscription item is renewing, you will see a new item in the JSON result when the subscription renews.


If things still aren't working, I can assist you if you submit for a DTS incident.


rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

Rich,


You worte:

> If you isolate that "latest_receipt" section of the receipt,


Are you saying that new receipts will generate this field when decoded by Apple servers? This is documented only for iOS6 style receipts (i.e. the deprecated transaction.transactionReceipt). Does this field always exist for post-iOS6 style receipts? Do you know whether this is a permanent change?


Peter

Turns out the transaction.transactionReceipt field in the SKPaymentTransaction.h interface file is what is deprecated - not the style of the receipt. The contents of the latest_receipt and the latest_receipt_field are not deprecated. This was not clear to me until I did some further digging with the iTunes Store Server engineers. However, note that the processing of the latest_receipt field is not exactly the same as provided for the transaction.transactionReceipt field. I've submitted a request to the iTunes Store Server engineers to document the validation results of the latest_receipt field.


Rather than discuss my findings so far in this posting, if your would initiate a new post - like "how can I make use of the latest_receipt field in a validated applicationReceipt for processing auto-renewing subscription renewals", I will take some time to respond. I'd rather respond to a posting with a title which more users will likely peruse.


rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

Same problem here under High Sierra in the sandbox environment.

And:

- Restoring does NOT update the receipt

- Receipt will be updated if to Purchase a new product or to Refresh Receipt

- If keeping the app running "updatedTransactions" will NOT be called. Restart the app (and let more time go by), "updatedTransactions" will be called

- The receipt is not updated when renewal happened, AND the receipt is not updated if did a purchase on another Mac (same testing account in sandbox environment)

- Strangely if to validate the receipts with the app store, the result is correct (all the new purchase or renewal receipt item be fetched), but the local receipt data is still old (the new purchase or renewal receipt will not be fetched from the receipt data). After calling "Refresh Receipt", the local data will be updated.



To reproduce it:

- Prepare to MACs and open the same Xcode project to test in sandbox environment

- Log in to a sandbox account on one MAC, and purchase a renewal product

- Log in another MAC with same sandbox account, now all the receipt are correct

- .... After expired

- Purchase a product on Mac A

- One Mac B, wait the "updatedTransactions" be called and make sure "finishTransaction" be called (by restart the app, waiting a long time, or ...). We will find the receipt will not be updated.

- One Mac B, then call restore, the receipt is still same (not be updated)

- One Mac B, Then to call refresh receipt or to buy a product, then the receipt will be updated


Very tough case. I saw you started this thread one year ago, would you please help to suggest the solution if you got it fixed?

As you have said that auto renewal will work 5 times during sandbox testing, Can you please let us know that what happen when it will go live. Can we trust on reciept validation that it will work absolutely fine in production if subscription is for 1 month.It will give us updated reciept and dates everytime??.Please reply

I cant refresh the receipt while auto renewel occurs, Also the transaction observer is not being called when a renewal occurs. How i get the renewed receipt for validation?

> I cant refresh the receipt while auto renewel occurs, Also the transaction observer is not being called when a renewal occurs. How i get the renewed receipt for validation?


You get a renewed receipt by:

        SKReceiptRefreshRequest *request=[[SKReceiptRefreshRequest alloc] init];
        [request setDelegate:self];
        [request start];


which results in a call to requestDidFinish:


You can also do a restoreCompletedTransactions and get a call to updatedTransactions.


Be sure that you have added an observer with

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];