latest_receipt and latest_receipt_info fields - deprecated or not?

You used to be able to check the current status of an autorenewable subscription by sending any old coded receipt from the app to the Apple servers and they would respond with the decoded receipt and two new fields - latest_receipt and latest_receipt_info. But the documents


https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW1


say this is returned "only for iOS6 style transaction receipts" which are deprecated. Rumor (i.e. your recent post) suggests that the fields will be returned for post iOS6 style receipts (i.e. the receipt in [[NSBundle mainBundle] appStoreReceiptURL]). If so, GREAT!!!!! But is this true? Can we rely on it? When will it be documented?

PBK, man, I think you are getting a little too worked over the semantics of this whole thing. The documents are just wrong or somebody thinks that wording is correct, which is even worse.

I have worked at companies the size of Apple and often the actual engineers writing code are not the ones writing the docs and may not even have any idea what the docs say. It sounds like Rich has reached out to someone connected with the docs so maybe they will get changed. If we all file bug reports regarding the wording of the docs that could help as well.

At this point I'm just going to assume the docs are either wrong or poorly worded and assume that these fields will always be there for auto-renewal subscription purchases. If I find another case of them missing I'm going to save the receipt so I can analyze it better. If the subscription is in the in_app array but these fields are not there I'm going to report it as a bug to apple. If it's not in the in_app array then I'm going to report it to apple as fraud.

Thanks for starting this thread, it has been helpful.

I recommend that you not rely on the persistence of this feature until it is documented correctly. You are welcome to ignore the documents in favor of Rich's interpretation (actually it is not an interpretation - it is an assertion that they are wrong) and I hope, for the sake of your users, that you and Rich are correct. However, the documents are very clear - this feature is documented as gone in iOS7 style receipts. That it persists for a few iOS versions is what always happens when a feature is removed. Good luck!

Hi Rich,

I appreciate the bravery of even posting here with the "Apple Staff" avatar and we all appreciate the help you've given us on this thread. In the same way that the map isn't the territory, the documentation isn't the intended contract.

My question is regarding the nature of the (intended contract for) receipt validation responses using the iOS7 receipt (applicationReceipt) for an auto-renewing subscription.

We've encountered some receipts whose application receipts return empty "latest_receipt_info" and "latest_receipt" fields. If the application receipt is not nil, we do not refresh the applicationReceipt after they make a purchase and only upload the receipt to our server (to verify with Apple) when the transaction has entered the purchased state. I have a few receipts handy that simply don't have the "latest_receipt" and "latest_receipt_info" fields when we get the validation response back. Does this mean that those users have, with 100% certainty, *not* purchased an auto-renewing subscription? Does that mean that the transaction entered the purchased state and, for one reason or another, the purchase didn't go through? Or, does that mean that we would need to explicitly refresh the application receipt on the client and re-upload that to our server to double check?

Essentially my question is this: "If a user has successfully purchased an auto-renewing subscription does that imply that the "latest_receipt" and "latest_receipt_info" fields will always be populated in the receipt validation response?"

I'm wondering if the absense of those fields suggests we need to force the client to perform an application receipt refresh request and then re-upload the receipt.

Best,

Stephen

A better approach is to follow the documentation. If you:


>only upload the receipt to our server (to verify with Apple) when the transaction has entered the purchased state.


then you can ignore the undocumented latest_receipt_info and latest_receipt fields and look at the well documented in_app field (an array of receipts) for a receipt with an expires_date in the future. The problem is that you can't reuse that same receipt each month to check to see if the auto-renewable subscription renewed. You must get a new receipt from the device, again: "when the transaction has enetered the purchased state."

You indicated that you've encountered the situation where the JSPN results of a validated applicationReceipt show an empty "latest_receipt" and "latest_receipt_info" fields. In this case, what was in the in_app array. I suspect that the in_app array was empty OR did not include an auto-renewing subscription item. Before an applicationReceipt is processed, there are no “latest_receipt” or “latest_receipt_info” fields. They are added by the iTunes Store verifyReceipt server, when it detects that there is an auto-renewing subscription item in the in_app array.

You asked - “. I have a few receipts handy that simply don't have the "latest_receipt" and "latest_receipt_info" fields when we get the validation response back. Does this mean that those users have, with 100% certainty, *not* purchased an auto-renewing subscription? Does that mean that the transaction entered the purchased state and, for one reason or another, the purchase didn't go through? Or, does that mean that we would need to explicitly refresh the application receipt on the client and re-upload that to our server to double check”

An empty in_app array indicates that you are working with a receipt where the iTunes Store has not recorded a purchase. The recommendation as per Tech Note 2413 “iAP FAQ”

<https:/

Indicate to the user that the receipt appears to need refreshing. If the user agrees, then the app issues the SKReceiptRefreshRequest and processes the refreshed receipt.

You also asked “Essentially my question is this: "If a user has successfully purchased an auto-renewing subscription does that imply that the "latest_receipt" and "latest_receipt_info" fields will always be populated in the receipt validation response?"

Yes - unless there is a problem with the verifyReceipt server.

I’ve had developer reports of the in_app array remaining empty after this refresh procedure. Assuming that this resulted after a valid purchase of an auto-renewing subscription in-app purchase, this becomes a bug report issue to be submitted to the iTunes Production Support team for investigation.

Also, if the in_app array does contain an auto-renewing subscription item, but there are neither “latest_receipt” nor “latest_receipt_info” fields, this is again a bug report issue. However, in this case, the iTunes Store server does indicate processing the in-app purchases referenced in the in-app array.

In the cases where the application is called to process a successful transaction, but is unable to validate that the purchase was actually made, the app should not call finishTransaction. This will leave the transaction as incomplete - to be processed another time when the transactionObserver detects it. In this case, when the user contacts Apple Care, AC can verify that the purchase is incomplete which lends credence to the fact that the user was charged but did not receive the contents.

To file a bug report - go the the Apple Developer Bug Report - <http:/

Make sure to include the application ID, as well as the base64 encoded applicationReceipt and the shared secret - so that the receipt can be manually validated.

Also add the statement “please check with Rich Kubota for bug report routing” - without this statement your bug report could be incorrectly assigned.


rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

A lot going on in this thread. The documentation is dated and a bit confusing. The question originally raised by PBK is currently being satisfied by NetFlix. My Netflix subscription is through iTunes Auto-Renewal. I am able to access NetFlix from any device, Apple and non-Apple, and browsers. This would suggest that server-side validation to iTunes of a receipt should be capable of informing the server of renewed, expired, and cancelled receipts without an Apple device being required to renew a receipt. From Rich's last post, I'm reading that the following would be proper validation of an auto renewing receipt:


1. Customer purchases an auto-renewing subscription

2. Apple device receives confirmation and receipt

3. App sends receipt to App's server backend for storage and continuing validation

4. App server sends receipt for validation to iTunes

5. iTunes confirms validity of the receipt, return JSON response

6. JSON response contains in_app array with purchased products. Empty array indicates no purchased products.

7. If purchased product is an auto-renewing subscription, then check the "latest_receipt" and "latest_receipt_info" fields for valid renewal


Questions:


A. Will the iTunes validation response update the in_app "expires_date" for auto-renew subscriptions? Or, do we need to verify renewal as in step #7?


B. Will the iTune validation response update the cancellation_date? If not, then how does NetFlix ensure valid subscriptions when a user may have not accessed NetFlix services from the Apple product but from a browser or other non-Apple device?

A. The receipt you send is old and the information returned for that receipt will never change - except for the latest_receipt_info and latest_receipt fields. You need to do #7.


B. #7 I believe. Note that when a user stops a subscription that does not generate a cancellation_date. A cancellation_date is generated only when the user demands money back from their subscription. Stopping a subscription stops new entroies with new expires_date(s).

Thank you PBK! I see here and amongst many other threads you've been very active in this topic. The threads have been informative. Appreciate it!


A. Perfect. My further testing validates this as well. In the case where there is a difference in items between "in_app" and "last_receipt_info", it seems that server-side should update the archived receipt with the "last_receipt". Furthermore, it also would appear the items in either section are always chronological where the last item with an "expires_date" in "last_receipt_info" would be the active (or final) subscription.


B. When a user demands money back, my understanding is that the "last_receipt" would contain "cancellation_date" instead of a receipt. Is this your understanding too? Is there anyway to test this?


As I'm testing, I'm getting expected results from /verifyReceipt for the first 6 auto-subscriptions in the sandbox and old receipt produces "last_receipt_info" with renewed subscriptions. However, after 6 subscriptions, the sandbox acts like each purchase is a consumable and no longer automatically renews.


Italso seems that downgrades and upgrades are not entirely working in the sandbox. In my UI, I provide subscription options for customers to buy, upgrade, and downgrade.


For upgrades, it's successful. The upgrade is taking immediate effect although the prior subscription being overriden's expiration date is unaltered.


For downgrades, it fails in the SKPaymentTransactionObserver with the localized error "Cannot connect to iTunes Store" everytime.


I added this information to an old thread in Sept 2016 on this topic that had no response (https://forums.developer.apple.com/message/177893)

Btw, not sure if you noticed the radar (http://openradar.appspot.com/28864177) attached to the topic on this thread: https://forums.developer.apple.com/message/142334#142334 . Apparently, Olaf indicates that Apple had contacted him... the "latest_receipt" is valid for /verifyReceipt and documentation is wrong.

Apple, let's get the documentation fixed asap...this is wasting a lot of developer's time on such a simple little edit. As it deals with money, we are naturally concerned that what our designs are bonified so we and you get paid for services rendered. Thank you!

1) "the items in either section are always chronological" - this is not my experience. I do not recommend relying on the order being preserved.

2) the limit of 6 renewals for an autorenewable is well documented.

With regards to the ordering of the items in the in_app array, I would make no assumption that the items are in chronological order. I would say the same holds true for the contents of the latest_receipt_info section. A developer made this assumption, and early last year encountered the situation that the second to the last item in the in_app array was the most current auto-renewing subscription item.


In addition, if the user contacts Apple Care, requests a refund, and the request is approved, the cancellation_date field appears in the corresponding in-app purchase item which was refunded. This will normally be for a non-consumable item or for the auto-renewing subscription item for the period which was refunded. This will appear in both the in_app array item, and in the latest_receipt_info item.


rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

Thank you Rich! Based on these clarifications, I've planned to:


a) separate in_app and latest_receipt_info by subscription versus others (like non-consumable/consumable)

b) sort the in_app and latest_receipt_info by descending purchase date order

c) look for cancellation_date in in_app and latest_receipt_info for current/active subscription

d) look for subscription upgrades and downgrades to adjust expiration dates of n-1 subscription life


Is there any way to test cancellation and subscription downgrades? It makes me nervous to push into the App Store without confirming the logic. When does a downgrade show in the receipt? After the current subscription ends?


Oh, and any timeline for the documentation to be revised ;-)?


Thanks!

(in response to H2OSkier)

Is there any way to test cancellation and subscription downgrades?

For cancellations, there is no good means to do so. The cancellation_date field is only set when Apple Care refunds a non-consumable or auto-renewing subscriptiuon purchase. There's no simulation for this in the sandbox environment. Id submit an enhancement request for iTunesConnect to have the iTunes Store server in the sandbox have a means to simulate this in the applicationREceipt


For subscription change, run two copies of the app. In one, make the purchase to different items in the subscription group. after the change, if the change becomes active, then launch the app on a second device and have it refresh the applicationReceipt and validate the receipt. The subscription change should be present.


The use of the second app will detect renewals made in the iTunes user subscription area as well. However one cannot use this method in the sandbox - another enhancement request.


When does a downgrade show in the receipt?

It was my experience that all changes occurred immediatelty. If your app offers all grouped auto-renewing subscriptions, try purchasing each one before the subscription expires. As I recall, there is an alert to indicate that the change is effective immediatelty.


One other thing, if the applicationReceipt contains an auto-renewing subscription item in the in_app array, then you can manually validate that one applicationReceipt after the purchase of a different subscription in the group - and the JSON results should show the change. This receipt update process only applies to auto-renewing subacriptions. If the first app is later used to make a non-consumable purchase, validating the original application_receipt will not show the non-consumable purchase.


>Oh, and any timeline for the documentation to be revised ;-)?

This would be for a Developer Publications writer to respond to. I work in DTS. I guess I could write a Tech Note - hmm.


rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

>When does a downgrade show in the receipt?

It was my experience that all changes occurred immediatelty. ....As I recall, there is an alert to indicate that the change is effective immediatelty.


I recall that a downgrade occurs at the next renewal cycle and that the user is not refunded anything for their current (not downgraded) subscription period. If this is true, a downgrade, unlike an upgrade, is handled in the normal course of subscription renewals.

PBK, Do you know if this means that the receipt (in_app and latest_receipt_info) through /verifyReceipt will not show the downgraded purchase until the next renewal cycle occurs? Is there any indication that the customer intends to downgrade in the receipt?

Rich,


A TechNote from an Apple representative with a modern date/time would be very helpful.


As for downgrades in the TestFlight environment, my App fails in the SKPaymentTransactionObserver with the localized error "Cannot connect to iTunes Store" everytime I try to downgrade a subscription. So, I'm not able to test what the receipt would contain and when for the downgraded subscription.


Would the receipt show anything in the result from /verifyReceipt before the current subscription ends? If so, what would the JSON look like for the current subscription and upcoming change?


Or, does the downgraded subscription arrive in the receipt after the current subscription period expires? If so, how do we identify that the customer intends to downgrade so we can forecast our revenue?


Thanks,

Scott

Using just logic, not experience, to answer:

When a user choses to downgrade they are only signaling an intent to the App Store. They may cancel before the renewal, they may change their mind and go back to the original level. So nothing has happened. And therefore nothing should be reflected in the receipt. Same thing as when a user cancels the autorenewing function - it's only an intention.

Your logic makes perfect sense 🙂. It could be nice to know a customer's intent to (a) forecast revenue or (b) understand why they want to downgrade.


It would be nice to have modern documentation and a fully functional TestFlight environment to cover all the scenarios clearly since there's been many changes in this area recently...sigh.

Scott,


I would test with a new test user account - as for the downgrade in a group, I just did a quick test with a sample I have, I could go from one subscription item in the group to another and the app receipt was updated with the new info. If the application is where the user makes the change, then the application will know when it gets the successful transaction indication. However, if the user makes the change in the iTunes subscription area, this will result in the creation of an incompleteTransaction when the charge occurs by the iTunes Store. Tkhe app will know when the transactionObserver is called and detects the incompleteTransaction. Things get considerably more complicated if the app is not required to run.


You issue may be better discussed via a DTS incident.

rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

Accepted Answer
latest_receipt and latest_receipt_info fields - deprecated or not?
 
 
Q