Our backend does server side receipt verification. In order to check the last expiration date for a renewable subscription, we look at the information in latest_receipt_info. This approach works most of the times.
However, we have some cases of users that, even with active subscriptions, latest_receipt_info only contains the initial subscription, which has already expired. I wonder if someone has already experienced this issue of having missing transactions. It looks extremely weird to me, because Apple is not returning the right information. These users were charged properly, but the Apple response does not reflect that. Am I missing something? Documentation is far from being great... Thanks!
Related
I'm building a react native app that has a 1 month subscription component. I have integrated into the apple API to get the receipts but I have one question I can't seem to figure out in test mode. Probably a newbie question but here we go...
When a user has an auto-renewing subscription and I call the Apple API there is the latest_receipt_info.
Will I get a new one every month? if so when does it come through?
So will all I have to do is call the Apple API, grab the latest transaction from latest_receipt_info and look at the "expires_date" field. If we are still before this date then I assume the subscription is still active? Can it be this simple to see if a subscription is active or not?
I've seen talks online about a "cancellation_date_ms" field but I can't seem to find it in sandbox mode, but why would this be needed if I just use the logic I stated above?
You can get an updated receipt any time by calling Apple with receipt data from the application, even if you send older data Apple always sends you the latest receipt.
You can check for the expiration date within, however it is the case if a user gets a refund the expiration date may still be in the future - in that case you'd be sent the cancellation_date_ms as well, so you should look out for that.
To get a better understanding of what all can be in latest_receipt_info, read through the entries in here, search for responseBody.latest_receipt_info:
https://www.namiml.com/blog/app-store-verify-receipt-definitive-guide
I offer a subscription in my application, and after purchase I validate that transaction against the receipt to get its expiration date. I do this by loading the receipt from disk, sending it to Apple for validation/ decryption (I know this is bad practice), and then iterating over the latest_receipt_info in the JSON response looking for a transaction matching the transactionIdentifier of the SKPaymentTransction object.
This works for most subscriptions, but not those offered with a free trial/ introductory offer. Please take a look at my example below:
I purchase a subscription that is returned to my application with a transactionIdentifier of 1000000506350685 and originalTransaction.transactionIdentifier of null.
I get the latest JSON receipt from Apple whose latest entry is one matching my product identifier and timestamp, but the transaction_id is 1000000506350686 and so is original_transaction_id.
Therefore I am unable to validate the purchase.
There are no problems when purchasing a subscription without a free trial/ introductory offer. There are no other objects in the returned receipt that matches the transaction id returned to my application.
This is in the sandbox environment, I am not sure about the behavior in production.
Has anyone had any similar experiences? What can I do to fix this?
I think this is probably due to the fact that you've already purchased that product before in Sandbox, and there's no device receipt in sandbox until you make a purchase (unlike production).
Either way, what you should be looking at is the latest product_id and expiration_date from the receipt to validate if the subscription is active. Transaction IDs can be keys for your transactions if you're saving them in a database, but shouldn't be used to validate a purchase.
Here is a really good blog post that goes over what your in-app purchase server should be doing to validate and keep subscription status up-to-date: iOS Subscriptions are Hard
I do this by loading the receipt from disk, sending it to Apple for
validation/ decryption (I know this is bad practice).
This is actually the recommended approach by Apple.
Goodmorning everyone ! I have a little question that I would like to ask you without going to waste an incident with Apple ...
In practice I am validating the receipt of payment for an in-app purchase, specifically a one-month subscription that unlocks some features of my app.
I parse the json correctly and apparently it seems to work fine but this does not always happen! In fact it often happens that the expiration date that I go to read from the json is not correct as if the subscription was not included in the receipt and I fished only those of the day before or in any case the previous ones.
This happens in sandbox and having checked the code and reviewed well, the parse of the document I could not find a solution because often the validation of the subscription is successful. I also searched online to see if it was a common problem but I did not find a solution or a discussion. My subscription does not include trial periods.
In the specific case this morning the first test was successful, but the validation was not valid. Checking the date shown was that of the previous day and then a previous subscription made yesterday. Once the subscription to the second test expired, the subscription was successful and also validated.
According to the documentation in the below link, Apple subscriptions status server will send this field expiration_intent when users renew their subscription.
Apple's
This is the same as the Subscription Expiration Intent in the receipt.
Posted only if notification_type is RENEWAL or INTERACTIVE_RENEWAL.
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html
I'm getting all the notifications on my production server and have checked all the logs for RENEWAL or INTERACTIVE_RENEWAL types but never been able to get the value for this field.
Any idea why this is happening? though I'm getting the rest of the fields with their values.
This appears to be a bug, or a mistake in the documentation (one of many). I have only encountered this field when validating a receipt, where it will appear in the pending_renewal_info info (and only if auto_renew_status is 0).
Here is an OpenRadar I recommend duplicating: http://www.openradar.me/33937017
I have an app with an auto-renwable item in the inApp-Purchase.
Let's say, with an period of 7 days.
If a test-User buys the item...
How can I check the expiration-date?
I can observe it with restoreCompletedTransaction, but there will be an Dialog to the user. Which is not so nice. Is there any other way without a server?
How can I handle the test-phase?
I don't see a way to shorten the 7 days... does it mean I have to wait 7 days, to see that I'm handling it right if the user doesn't subscribe again?
thank you
xnz
You can send the receipt to a server of yours and have it check and re check the receipt. When the subscription is prolonged your server receives an additional receipt indicating that.
I am not sure if this is possible within the app. You need a certificate and a shared-secret to verify auto renewables. It might be a bad idea to have the certificate and the shared-secret within your app.
You can find Apples documentation here:
http://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/RenewableSubscriptions/RenewableSubscriptions.html
There is some info by Apple that recommends to verify the receipt on your own server for security reasons:
http://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/index.html
They also say, to know the status of your IAP (in the article, Consumable, but I guess it would work for subscriptions too) you can save the receipt, recall it when needed and verify it again, receiving an updated receipt.