A client application successfully performs an in-app-purchase and receives a receipt from iTunes. The client then sends this receipt to the server, which verifies it with Apple and, if successful, unlocks some content for the client.
Is it possible to insert extra data in the IAP purchase request such that the receipt or the receipt validation contains this value?
I'm trying to prevent a man-in-the-middle/packet-sniffing type hack i.e. If someone was to discover another person's receipt and validate it against my server, how is the server to know that this receipt wasn't generated by this, the validating person?
From Apple's IAP documentation there are a number of values returns in the validation response. Is it possible that I could use version_external_identifier value? What is it's use or value?
Thanks
version_external_identifier
An arbitrary number that uniquely identifies a revision of your application. This key is missing in receipts created by the sandbox.
That really answers your question; its a way to determine what revision of your application made the purchase. You can have the same version number, but multiple revisions, and this allows for that and IAP.
Is it possible to insert extra data in the IAP purchase request such that the receipt or the receipt validation contains this value?
Ultimately, no. Apple have control of the receipt, and its contents. If you follow the guidelines in the documentation (see this for more info along with the link you posted), you will be ok against a man in the middle attack (Apple would have considered this). Make sure connections to your server and to Apple are HTTPS.
A man in the middle to make a purchase on someones behalf is slightly moot anyway; the purchase request is tied to an Apple ID, meaning the man-in-the-middle would need to know their credentials.
Related
We have got a problem with auto renewable subscription.
First, I would like to tell you my case from the beginning to understand my problem totally.
So, I have an app that contains auto renewable subscription. I managed to buy a product from my app, but I would like to validate the receipt from my server. If I understand it well, then I should send the receipt data to my server that will send the receipt data to Apple and verify that receipt.
First question is that, do I know it right that verification means that we send a request to https://sandbox.itunes.apple.com/verifyReceipt ?
Secondly, what happens if I cannot send the receipt data for the server? I mean, in this case should I save the receipt data locally and try to send it again in a different time (my app can be used after registration so I have to send the user id with receipt data to my server)?
Furthermore, there is a subscription status URL for auto renewable subscription in iTunes connect. We set up an URL for this but we do not get any notification from Apple's server. We configured the server as explained in Apple's documentation (protocols, etc.) but we still don't get any notification. Do you have any suggestion why is it?
Do I know it well, that the notifications should be sent automatically if any status update change happens? If not then what should I do in my app or on my server? (e.g. how to detect if user cancels a subscription?)
Do I have to implement both logic for the best user experience?
To validate the receipt you can send it on apple servers, "can" because you can validate the receipt also in app. In this case is not fully safe, because someone can attack you app and tamper your validation code.
Apple has 2 different kind of servers test and production, when you are debugging you send receipt to the test servers, that also means that auto renewable subscription have shorter time, if I remember well a month in test is 5 minutes.
This is documented very well in apple documentation.
A receipt is always present in your app even if it's free. It's up to you how to manage those kind of situation, in my opinion a receipt should aways be valid from the beginning until the server responds in a different way.
The third question is not clear. There is a system to refresh a subscription but this should be done with user permission as far as I know, the subscription itself seems to be already updated automatically from time to time by the purchase mechanism.
You must implement all the logic to manage a subscription, cancellation, revocation etc.
We have a successful app on the iOS app store with in-app purchases. Every time a purchase is completed we send the receipt to our server, our server than checks the receipt with Apple's servers and logs apple's response(including whether the purchase was valid and that they come from our app in that same time and date).
We have quite a few users who use iap cracks that send us receipts that apple says are invalid. However we started now to see cheaters that have receipts that apple replies that are VALID. What is strange in these cheats, that when such a cheater user purchases in our app, he usually purchases all of the purchases with the exact same receipt.
Have you heard of such a way to 'fool' apple receipt validation?(to generate receipts that apple will say they are from our app in the time of the 'purchase')
Is there something we can do to find those cheaters in their 1st purchase (for the next purchases we can simply check times of the next receipts or make sure that our receipts are unique)
Thanks!
Is there something we can do to find those cheaters in their 1st purchase
Actually, if this is the same hack I've seen discussed as a proof of concept recently, the first purchase is legitimate. The "innovation" is in decoding that legitimate receipt and rejigging its IAP ID with a different one while the receipt overall still appears valid. So simply avoiding the duplicates is enough. Didn't think that one was anywhere near production-ready though, so this might be something different.
We also faced similar issue while developing a game of iOS app store where business model was based on In App Purchase only.
Initially we used to check with Apple Servers for the receipts directly from the device. But some hacker has created a hack for the users where they can install the DNS server certificate on their device which spoofs the response from Apple.
The way to do this is let web server check for the receipts from Apple directly with some kind of hashing or md5 check to make sure the response if from Apple.
here is a link which have a detailed information on this https://www.objc.io/issues/17-security/receipt-validation/
Hope this helps.
Apple has a unique identifier called the Identifier For Vendor (IDFV) discussed in this developers guide.
http://possiblemobile.com/2013/04/unique-identifiers/
I was thinking to would be possible to use with a Restful API so only requests that have a valid IDFV are accepted. But here is the problem I don't know any way to verify the IDFV. I could make it so when the app is installed it registers with my service. But ideally there would be a way I can verify this identifier.
I just had a brain storm on this: It's not all that simple, but what if you have an In-App Purchase for the app where that IAP is on a free tier. Have to investigate this more, but I think you can have a Non-Consumable purchase type that is free. The client can then send the purchase receipt (which is encrypted, as of iOS7) to the server side and the server side can then validate this receipt-- Apple does provide a RESTful means of doing this. Thoughts? Of course, you can also make the IAP have some > 0 price. This would give the app developer the means to add a payment mechanism.
I am not sure what your problem is. The app grabs the identifierForVendor and sends it to your server. What else can happen? You could certainly code the transmission so it also sent a hash of the identifierForVendor and some secret string (like "my secret 25671566") to test that the transmission was coming from your app.
You should also know that 1) the identifierForVendor will change if the app is deleted and reinstalled. 2) the keychain might solve the problem of #1 3) The app has a receipt, all apps do whether or not they have purchased an IAP. The receipt is encoded using the identifierForVendor. You could send the receipt from the device along with the purported identifierForVendor and see if it can be decoded. But see paragraph 1 above.
I am looking to build a ios application that will use an auto-renewable subscription on a yearly biases.My question is, how can we be notified when a user cancels a subscription in IOS, so that we can cancel the users features
sorry if I'm duplicating the reply:
if the receipt status is 21006 and there is a key named cancellation_date, then it's a cancellation, you can find the new expiration date in that key but it's a formatted date, if you need a better value to parse check for receipt['latest_expired_receipt_info']['cancellation_date_ms'] same as expires_date
do someone known how to be notified by apple without sending verify requests? it would be reasonable to check only when the product is expiring instead to querying each times for all products because of possible cancellation
First things first. If you're app is not a periodical like a magazine, then you should steer away from ARS (auto-renewable subscriptions). Apple may reject it and insist you use NRS (non-renewing subscriptions).
It's more code than I can practically paste in here, but please follow this guide from Apple on Verifying In-App Purchase Receipts.
Basically you'll be putting the receipt and your secret in a JSON object and sending it to Apple. It's preferable to do this from your server and not from the app.
Here is a good guide on Verifying Store Receipts Using PHP and cURL
The JSON object will look something like this:
{
"receipt-data" : "(receipt bytes here)",
"password" : "(shared secret bytes here)"
}
Apple will respond with another JSON object that has info such as expiration date.
First of all, I am not talking about calling https://buy.itunes.apple.com/verifyReceipt/, instead, what I am asking is how to verify an iTuneStore receipt from one of our users.
We have in-app purchase in our app, and we verify in-game receipts on our server before we grant the product. However, this particular user claimed that he got charged by iTunes store but did not get the purchased products, and sent us his receipt as a proof.
So I am wondering if there is anyway we can verify such a receipt. There is "receipt no" and "order number" in the iTunes Store receipt, however, with in-game receipt verification we get transaction_id, and these numbers are quite different. Any idea?
Thanks in advance.
You should contact Apple's developer support. I doubt there is a way to verify it by yourself if you can't find a respective transaction in your own systems.
There is no manual way to do this, unless you can somehow get the receipt data from his device, in which case you can use Apple's API that you mentioned to verify his claims. If what he says is true then suggest him to claim a refund and then re-purchase. He should be able to do this here.
Now, the Lookup Order ID of App Store Server API could get a customer’s in-app purchases from a receipt using the order ID.
GET https://api.storekit.itunes.apple.com/inApps/v1/lookup/{orderId}
You could find the corresponding transactionId from this API response JWSTransactionDecodedPayload
For how to do the Lookup Order ID request, please refer to https://github.com/richzw/appstore#look-up-order-id
There is source code at https://github.com/roddi/ValidateStoreReceipt/blob/master/validatereceipt.m which will validate a receipt, and let you parse it and dump out all the transactions.
If the IAP transaction is there you would see it.
You'd have to write a special-purpose iOS app which uses that code and feed it the receipt. It seems like a lot of work.
I am not talking about calling https://buy.itunes.apple.com/verifyReceipt/
Actually u have online receipt verification tool, accessible by link above.
There is no better way to verify Your receipt. Offline verification is possible, but if even it succeeded, nobody can give 100% warranty that Your receipt is valid(maybe just same signature, but still fake one).
Apple processing every purchase on its servers and if it successful, receipt saved to database. If u want to check receipt u must access to that database and request for Your receipt. So You have a tool, but don't want to use it? No reliable way then.