iOS: can receipts be reused to check for purchases? - ios

is it possible to send an iOS receipt to the server and the server checks periodically with that same receipt if (new) purchases are made? Or are only in app purchases returned up to the point the receipt has been sent to the server?
For my use case I need to check "future" purchases with the same receipt as well, but while testing with sandbox it seems as if only purchases until the time of the receipt are returned from the App Store.

According to the documentation this varies based on the type of you in-app purchases. If your receipt containing auto-renewable subscriptions the response you will receive from apple will contain two additional fields "latest_receipt" and "latest_receipt_info", you can use these fields to determine whether the subscriptions are currently active or not. If your receipt doesn't containing auto-renewable subscriptions than you will only receive the "receipt" field which will be a JSON representation of the receipt that was sent for verification.

Related

Correct workflow to online validate non-consumable in-app purchase receipts on iOS?

What is the correct workflow to online validate the in-app purchase of non-consumable IAPs on iOS?
While I found a lot of information about in-app purchases in general I found no details on how to actually perform online validation.
Is the following workflow correct and complete or am I missing something?
General setup:
iOS app starts purchase by adding an SKPaymentQueue to the payment queue
iOS calls paymentQueue:updatedTransactions: with transaction.transactionState == SKPaymentTransactionStatePurchased when purchase is complete
At this time the app receipt has already been updated and the purchase of the non-consumable item was added.
The receipt data and transaction.transactionIdentifier are send via HTTP POST to my own web service
The web service POSTs the data to Apples /verifyReceipt endpoint
Apples server response with an error if the receipt is invalid or with detailed JSON data if receipt is valid
The JSON Data received from Apple includes information about all prior non-consumable and subscription purchases AND the current consumable purchase.
The information about the consumable purchase can be identified by the product_id field or by using the transaction.transactionIdentifier
The web service adds the purchase to the current user account and/or sends back an valid/invalid response to the iOS app.
If necessary (when the purchase is not stored/handled online) the iOS app can handle the purchase (add coins, or whatever)
The transaction is closed using [queue finishTransaction:transaction]
Additional Observations:
The receipt includes information about all prior non-consumable and subscription purchases AND the current/last consumable purchase.
The information about the current consumable purchase is available until the next purchase (no matter if consumable, non-consumable or subscription).
Restarting the app does not destroy the information about the current consumable purchase
When the app is deleted and re-installed the receipt is empty / does not exist. After restoring previous purchases the receipt only includes information about non-consumable and subscription purchases. No information about non-consumable purchases is restored (no surprise)
Conclusion:
If (for some reason) the receipt cannot send be to the web service (server down, no connection, etc.), this can be retry later. The purchase data will be available within the receipt until the next purchase.
To be able to access the receipt data even after the next purchase one has to implement a custom storage method (e.g. save receipt data to file).
This way the user can be informed about outstanding validations and a retry option can be offered.
Is this a complete and valid workflow to validate consumable in-app purchases online or am I missing some special cases?

How to validate an iOS consumable in-app purchase?

When a user purchases a consumable, my SKPaymentTransactionObserver receives an array of SKPaymentTransaction. The app can then check the transaction.TransactionState and transaction.Payment.ProductIdentifier to verify that the iap has actually been purchased.
But my app uses that in order to allow the user to download content from my web service. So the question is how can the web service validate that the app has actually purchased the iap, and not that it's a fake app just saying it did? I need some way to validate the SKPaymentTransaction on the server. Either by a signature, or by an app-store verification-service.
Windows has a way to do this on UWP . Is there a way to do this on iOS?
I've checked SKPaymentTransaction , SKPayment , etc. but all either don't show a way for validation, or they're about non-consumables (which are kept in the app's receipt).
There are two ways to validate an iOS consumable in-app purchase.
Firstly, You can validate the receipt locally in the app(see Validating Receipts Locally) . However, it is still susceptible to cracking.
The safest way is to perform server-side validation by sending the receipt to your server then sending it on to Apple (see Validating Receipts With the App Store).

Notify server with IOS in-app purchase events (renewed,cancelled..etc)

I'm using auto recurring subscriptions in my app in my app,I need to change the subscription status if recurring fails from iOS.
I am following this documentation, but there are a few things that are still not clear to me:
What if my server missed the post data from iOS
How do I know if the subscription got renewed
How do I link my app user memberId (unique id) to the transaction
What is the difference between latest_receipt form iOS post data(server to server notification) and bundle receipt url after purchase.
Here are the steps I take the user to subscribe:
Ask the user to sign in. If they don't sign in they can't subscribe.
Send the app receipt to my server and store it there. If this fails they can't subscribe. This need this to validate get the latest_receipt info from the server at any time.
The user subscribes through iTunes.
Validate their receipt with the app store and check the latest_receipt to make sure they are subscribed. (This is done server side)
Repeat step 4 periodically to make sure they are still subscribed
So to answer your questions:
What if my server missed the post data from iOS?
Since I get the app receipt from the user before they subscribe I can check the with itunes directly from my sever any time and get the status of their subscription.
How do I know if the subscription got renewed?
Since you have the user receipt on your server, you can use it to get the latest receipt from apple and check the current status of the subscription. Here is how you do it Validating Receipts With the App Store
How do I link my app user memberId (unique id) to the transaction?
You could use the "Original Transaction Identifier" from the receipt as a unique id. This value is the same for all receipts that have been generated for a specific subscription
What is the difference between latest_receipt form iOS post
data(server to server notification) and bundle receipt url after
purchase?
When you send a receipt to the app store to be validated, it will return a JSON representation of the receipt that was send, this can be found in the "receipt" field. If your receipt contains subscriptions you will get "latest_receipt" and "latest_receipt_info" fields. These fields are useful when checking whether an auto-renewable subscription is currently active. If the bundle receipt is up to date then the "receipt" and "latest_receipt" will be the same.

Match iOS in-app purchase receipt with user's purchase history

We're using in-app purchases in our app and validating receipts on server side.
As a result of validation we get Receipt object described here. We store the transaction_id in our records as a unique identifier of the purchase.
Then, some time after the purchase a user who made a purchase in our app looks at Purchase History in the iTunes app and see this identifiers:
Question:
How can we match this identifiers with the validated receipt?
For example, it's useful in the case when users contact us via support channels and want to restore their accounts.

IAP Receipt Validation for Consumable Products

I have implemented the IAP for Consumable Products in my app. I have couple of queries regarding validating the receipt. I am going to use my own server which will communicate with apple server.
1.) Does the below url will contain the most recent receipt or all the receipts (even the old ones)?
NSBundle.mainBundle().appStoreReceiptURL
2.) If the above url stores all the receipts then do i need to verify all the receipts whenever user purchase a new product?
3.) Does the user will have access to these receipts if he chooses to reinstall the application?
Refer: In-App Purchase Programming Guide
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/DeliverProduct.html#//apple_ref/doc/uid/TP40008267-CH5-SW16
Information about consumable products and non-renewing subscriptions
is added to the receipt when they’re paid for and remains in the
receipt until you finish the transaction. After you finish the
transaction, this information is removed the next time the receipt is
updated—for example, the next time the user makes a purchase.
Information about all other kinds of purchases is added to the receipt
when they’re paid for and remains in the receipt indefinitely.

Resources