Kinda worried about [SKPaymentTransaction transactionReceipt]

Hey guys, hope you're well,


Apple announcements about changes on auto-renewable subscriptions got me a bit worried.


My app still relies on the "old" way for validating purchases against Apple servers, ie. by fetching the transactionReceipt of the SKPaymentTransaction object that gets passed with the completeTransaction: method, and my app passes this receipt to my server that validates the receipt with Apple.


I know that this has been deprecated for some time now and that we're supposed to use [NSBundle appStoreReceiptURL], and I'm wrong to still rely on the transactionReceipt.


I was planning to migrate my app to the "appStoreReceiptURL" way during this summer and get it ready for iOS 10, in case Apple shuts down the older method for validating transaction receipts when it comes out this fall.

I was under the impression we still got some time to make the appropriate changes, since the "Validating Receipts with the App Store" documentation still states the following : "If the

appStoreReceiptURL
method is not available, you can fall back to the value of a transaction's
transactionReceipt
property for backward compatibility."


But this week's announcements of changes about in-app purchases got me worried, especially since some of these changes will take place next Monday. I'm afraid that all my transactions verifications could start failing any minute now.


I don't know how many apps still use the old way of validating receipts, but do you think Apple would "kill" the transactionReceipts without giving us a heads-up ? Ideally, could someone at Apple tell us if this is planned ?


Thanks for reading !

Yes, things that have been deprecated for years and years can start to fail. But can you point us to anything specific that makes you concerned? Here, for any other readers, is my understanding of the new changes:


https://developer.apple.com/app-store/subscriptions/whats-new/

I'd sit on any worry until WWDC is over and we have a chance to see what else is added to the conversation.

Thanks for your replies,


Actually, I'm worried because we know for a fact that there are some undergoing changes regarding in-app purchases and subscriptions in the days to come, and the previous threads mention some changes about older ways of validating receipts that have recently been invalidated by Apple. We know appStoreReceiptURL has been around for a while, and I fear that Apple could shut down the older way of validating receipts any moment now.

My app is also still using the old transactionReceipt method.

I have the code ready in the application to fall-back to the applicationReceipt. Server side, the code is expecting transactionReceipt, but can be switched to use AppReceipt only when needed.

In fact we use a mix of the two method to enforce authentification and consolidation of purchases. That's why, the old method is still useful to our setup.

Does anyone have seen any hints about transactionReceipt in iOS 10 ? I have not tried the beta yet.

As a hint to fellows, I just checked my server logs and found numerous transactions validations from users devices running 10.0 beta. They did not generate errors so, at least on beta release, the transactionReceipt is still there and populated.

Rezard,



The content of the transactionReceipt is controlled by iTunes. To date, the only public interface as to operational status is via the System Status web page <https://www.apple.com/support/systemstatus/>.



If I receive word that the transactionReceipt, I will lobby WWDR management to allow this information to be posted. As an Ap[ple employee, I'm limited to publishing approved information only.


As to the finding that the transactionReceipt still persists in iOS 10, I suspect that there continue to be some major developers whose applications rely on this receipt for validation of in app purchase products. iOS 6 style receipts have documented support features which the applicationReceipt does not. If your application is dependent on specific functionality that the transactionReceipt provides, but is not available in the applicationReceipt, please submit an enhancement request using the Apple Developer bug report web page - <http://bugreport.apple.com>. In submitting the enhancement request, make sure to select the iTunesConnect product - NOT the iOS product.


Having said this, it's time to update your app to stop relying on the transactionReceipt. The common question is asked - how to verify that the auto-renewing subscription is current, and how to detect when the subscription is cancelled.


PBK has responded a number of times on the matter of detecting a valid auto-renewing subscription. I will again do so, but add some description as to how the process works. Initially, the user decides to purchase an auto-renewing subscription. The application has used to SKProductsRequest to validate the identifier "mycompany.myapp.autorenewsubscription1month". The user presses the buy button and the addPayment call is made to the iTunes Store to charge the current user for the purchase of "mycompany.myapp.autorenewsubscription1month". Let's assume that this is the first time the user has attempted to purchase the 1 mo auto-renewing subscription item and that there is a free trial associated with the purchase. The user's account is charged and the updatedTransactions delegate method is called with the SKPaymentTransactionStatePurchased. For now, there appears to be the transactionReceipt included with the transaction.


The app then validates the applicationReceipt, if it chooses to do so - by accessing the receipt at appStoreReceiptURL. The app encodes the receipt in base64, then forwards it to the developer server for processing. (some apps send the receipt directly to the Apple Receipt Validation server process - but this is against recommendation as it can lead to a man-in-the-middle attach). The developer server forwards the base64 encoded receipt with shared secret to the Apple Receipt Validation server process. The validated receipt is returned. The app inspects the in_app array and should find one item with the product_id field set to "mycompany.myapp.autorenewsubscription1month". The app calculates the length of the subscription by the difference of the expires_date and the purchase_date. The result should be the length of the free trial period - not the one month period plus the free trial period. The app notes that the expire_date is later than the current date so it knows that the subscription is active.


Lets assume that the user does not cancel the free trial. On the last day of the free trial, the iTunes store will bill the user for the first month of the auto-renewing subscription (I may be off as to the exact time that the user account is billed). The iTunes store will set up an incompleteTransaction on the store for the user and applicationID. At some point, the user will launch the application and assuming that the application has called addTransactionObserver in the startup process, and there is an active network connection, the application immediately detects the incomplete transaction. The updatedTransactions delegate method is called with the SKPaymentTransactionStatePurchased. The applicationReceipt is validated. Now when the app inspects the applicationReceipt, there will be a second item in the in_app array. The app cannot assume that the in_app array contents are in any order. The current purchase might be the first element in the in_app array. The app finds the iAP item where the expire_date is later than the current date and knows that the subscription is still active. This is how the app will detect that the auto-renewing subscription is current. When the validation process is complete, make sure to call finishTransaction on the transactionIdentifier so that the store will mark the incompleteTransaction as "completed"


If there is concern that the in_app array will grow without bounds, this is the current design. Please submit an ER that there be a way for an app to trigger older in app purchase items to not be included in the applicationReceipt.


So what happens when a user cancels a subscription. There are 2 cases to study here. There is the case that the user decides to let the current subscription expire. this happens when the user enters their iTunes account, to the "Manage Subscriptions" section and chooses to allow the current subscription to expire. In this case, on the next auto-renew date, iTunes will not post an incompleteTransaction to the user account. When the application validates the applicationReceipt, there will no longer be an in_app array item with the expire_date greater than the current date. If the application knows that the subscription was active, it can alert the user that the receipt does not show that the subscription is active and can ask the user whether to refresh the receipt using the SKReceiptRefreshRequest. If the user agrees, then the app makes the call, validates the updated receipt and scans for a current subscription item in the in_app array. So long as there is no in_app array item where the expire_date is greater than the current date, the subscription is expired.


The other cancellation case is where the user contacts Apple Care and requests a refund for the in_app purchase. When this happens, the date of the refund is noted. When the applicationReceipt is validated, the cancellation_date field for the corresponding in_app array item will be set. Note that as per TN 2413, iAP FAQ <https://developer.apple.com/library/ios/technotes/tn2413/_index.html#//apple_ref/doc/uid/DTS40016228-CH1-RECEIPT-HOW_DO_I_USE_THE_CANCELLATION_DATE_FIELD_>

the cancellation_date field is only added for non-consumable and auto-renewing subscription purchase types. Note that the cancellation_date applies to the specific in_app array item, and not to all of the in_app array items.


Note that the applicationReceipt is only updated when the receipt is refreshed, when the updatedTransactions delegate method is called for a successful or restored transaction or when the application is installed from the iTunes store (in the case that another copy of the app is to a second device).


rich kubota - rkubota@apple.com

developer technical support CoreOS/Hardware/MFI

Kinda worried about [SKPaymentTransaction transactionReceipt]
 
 
Q