Unexpectedly receiving iOS6 styled receipts in sandbox

Hello. I am working on an application which uses auto-renewable in-app purchases. We are using sandbox with testflight to get test base64 iOS receipts.

We are making these calls server-side using the base64 receipt passed up from the app.

When we try to validate against the sandbox endpoint: https://sandbox.itunes.apple.com/verifyReceipt

when the receipt is Expired, the server throws the error status code: 21006 representing that the receipt is expired. This suggests that this receipt is iOS6 style according to Table 2-1: https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html


However, we are testing on iOS 11 devices. The same error does not seem to get thrown in builds which are directly on the device from XCode.


We are wondering what behavior we are to expect from the production verification endpoint https://buy.itunes.apple.com/verifyReceiptt. Namely, whether to expect iOS6 or iOS7 or if we should support a combination of both. The app will not run on devices below iOS9 so we would like to avoid supporting iOS6 style receipts if possible.





: https://buy.itunes.apple.com/verifyReceipt

Replies

>We are making these calls server-side using the base64 receipt passed up from the app.


Are you using transaction.transactionReceipt (iOS6 style receipt) or are you using the receipt from [[NSBundle mainBundle] appStoreReceiptURL] (iOS 7 and later style receipt)?

We are using appStoreReceiptURL, the iOS 7 style.

To clarify, we are unsure of which behavior to expect in production since we have had the (seemingly deprecated) iOS6 style behavior in some cases, and iOS7 style behavior in others, with the exact same device/product/Sandbox user/code. The only difference seems to be the build environment. When making a Sandbox purchase on a build from TestFlight, StoreKit returns a purchase token that, when validated with Apple API from our server, seems to return iOS6 style data (i.e., “latest_expired_receipt_info” is present and attempting to validate an expired receipt returns an error with code 21006). However, builds running locally from XCode seem to be iOS7 style (everything is in “latest_receipt_info” vs “latest_expired_receipt_info”, we get “pending_renewal_info” and validating does not throw 21006 but instead the most recent information on the subscription, even if it has expired).

1) you wrote "StoreKit returns a purchase token that, when validated with Apple API from our server". I assume you mean you "retrieve the data from appStoreReceiptURL and send it to the Apple servers to process it". If not, what do you mean?


2) the content of the field "latest_expired_receipt_info" is an iOS6 receipt so you should not be surprised that it returns a 21006. You would expect to have such a receipt if the app purchased an IAP back in the days when it was running iOS6. Is that possible?


3) you wrote " seems to return iOS6 style data (i.e., 'latest_expired_receipt_info' is present...)" . That leaves open the possibility that there were other components in the receipt like a field "latest_receipt_info" which would contain either one (iOS6) or all (iOS7) autorenewable renewals. Was that field there and did it contain multiple renewals?

I dont have anything useful to say, we just started receiving a random collection of ios6 style receipts in our live environment. Nicely mixed up with 'new' style ones as well. They are coming from the same app version and all from ios 11 devices, that only use 'appStoreReceiptURL' - no idea what is going on, but quickly deploying some changes to handle both receipts...