Transaction is lost from the local receipt after the app restart.

I am testing a non-consumable In-App purchase and I found a strange issue. Here is my scenario:

1. User buys the In-App.

2. The app sends the receipt(Bundle.main.appStoreReceiptURL) for validation to my server which sends it to the app store /verifyReceipt

3. Receipt verification is successful, the app unlocks required features.

4. User closes the app.

5. User opens the app.

6. The app gets the user receipt (Bundle.main.appStoreReceiptURL) and sends it for verification.

7. The transaction for the In App not found.

If however I refresh the receipt by using SKReceiptRefreshRequest and then send it for verification, the transaction is back again. And it is there until the user restarts the app. If he does, the transaction is lost again until I call SKReceiptRefreshRequest.


I am having this issue with local builds and builds downloaded using TestFlight.


I also noticed, that when the required transaction are not present in the receipt, there are other transactions which I did not make using the current user. Those other transaction are for an auto-renewable subscription which I also have in my app.


Also the issue is currently reproducing only on one of my device(iPhone 5s). On my other iPhone all seems to work fine.


It looks for me like the local receipt on my 5s iPhone has got corrupted or something and it does not persist the changes after the SKReceiptRefreshRequest.


Is there a way to completely remove the receipt for the sandbox environment so I could start from scratch?

Answered by PBK in 399451022

Absolutely not.


You need to have a restore function for those few users who share a device with other users. Usually a device has only one user and the receipt will be the appropriate receipt. If the receipt is not the appropriate receipt then the user knows exactly why they must restore the IAP - and usually that is because they didn't buy the IAP from you but their friend did.

Are you sure this isn't a case of properly keeping track of which receipts belong to which users along the way? That iPhone 5 is using an older iOS, where you may need to edge case it if you want it to perform similar to current iOS calls, etc.


Seen this from the the docs ?:

Send a copy of the receipt to your server along with some kind of credentials or identifier so you can keep track of which receipts belong to a particular user. For example, let users identify themselves to your server with an email or user name, plus a password.

It is possible that the app was 'purchased' from the App Store under the Apple ID of user 1 (in the sandbox that would be determined at the time of installation through TestFlight or Xcode) and when you restore the receipt you choose to restore it under the Apple ID of user 2. Therefore, when the app is closed and reopened you might get the receipt in the account of user 1. So the question is - do you know who might have made the purchases that show up in the original receipt - could that be the TestFlight user?


>Is there a way to completely remove the receipt for the sandbox environment so I could start from scratch?


Sure - delete the app and reinstall it.

The user thas has made the original purchases is one of my sandbox accounts I used some time ago when testing the auto-renewable subscription. What I can not understad is why after I refresh the receipt when the new user is logged in into the sandbox environment and then reopen the app without switching the user or logging out the newest recept is lost again.


Should not the latest version of the receipt that was acquired by sending the SKReceiptRefreshRequest be persisted?

For the purity of the experiment I just repeated all my test scenario:


- I created new clear sandbox user in AppStore connect.

- I removed the app

- Logged out from my real account and from sandbox account.

- Reinstalled the app from XCode.

- The app sent the local receipt for verification. The receipt returned from the app store contains old transactions created by some previous user.

- Then I tap on the restore button. The app tries to send SKReceiptRefreshRequest. User is asked to enter his AppleID credentials. After SKReceiptRefreshRequest is completed the receipt is sent again to verification server.

Now the parsed and verified receipt returned from the App Store /verifyReceipt, is clear, there are not any transaction(which is an expected behavior).

- I close the app. I go to settings> iTunes & App Store to check if the new sandbox account is logged in. It is.

- Open app. The app sends local receipt for verification. Verified receipt contains old, not related to the current user transactions.

> Should not the latest version of the receipt that was acquired by sending the SKReceiptRefreshRequest be persisted?


No. The system needs to limit the possibility that user A will purchase an IAP and then go from device to device to device restoring that purchase for all of their friends.

So it means I need to send SKReceiptRefreshRequest every time the app is relaunched?

Accepted Answer

Absolutely not.


You need to have a restore function for those few users who share a device with other users. Usually a device has only one user and the receipt will be the appropriate receipt. If the receipt is not the appropriate receipt then the user knows exactly why they must restore the IAP - and usually that is because they didn't buy the IAP from you but their friend did.

This makes sense. Thanks a lot for the help.

Transaction is lost from the local receipt after the app restart.
 
 
Q