We recently launched the app which has only consumable in-app purchases. We noticed lot of fake purchases - purchases with invalid receipts and also 'valid' receipts but the "in_app" array in the validation response from apple is empty array. I need to know how users are forming such a 'valid' receipts ? Is it the receipt of the app download and not of in-app purchase or what ? I am now putting the following check for validation. Extract "in_app" field in json response from Apple and if it is non-empty, then check the product_id matches or not. I need to know if this check is enough or their is a better fool proof check.
2 Answers
All apps have a receipt. Those apps that have purchased an IAP have an in_app field in their receipt. Your users are pushing a fake call into their updatedTransaction method and you are grabbing their receipt (sans IAP cause they made no purchase)and sending it to your server. Other users might swap some receipt from somewhere (e.g. one of 30 thieves makes a purchase and extracts that valid receipt and sends it to their 29 co-thieves). If they stick that receipt into their device and then push a call to updatedTransactions then your server will get their now-valid-but-duplicate receipt. Your server needs to check *** the date of the receipt and discover it is older than recent or, even better, older than the paymentRequest which you would need to co-send to your server. (it is better to decode on the device - much more secure)
*** you used to be able to check transaction_id for a duplicate transaction_id. Unfortunately you can no longer do that since a restoreCompletedTransaction returns the same transaction_id as the original purchase. I have told Apple about that and they ignored me.

- 16,385
- 1
- 16
- 20
-
1I just realized that for a consumable you can check for a duplicate transaction_id and reject it. – Peter B. Kramer May 05 '16 at 01:33
-
Thank you. I found that "original_transaction_id" is the bet. – Deepak Sharma May 05 '16 at 10:02
-
@PeterB.Kramer how can you tell which transaction is the one associated with the current purchase if the grand unified receipt has the users entire purchase history!? – Learn2Code Nov 18 '17 at 04:51
-
The overall receipt has a creation_date field and the IAP specific portion has a purchase_date. If they are similar then that IAP was purchased in conjunction with refreshing that receipt. Your app has a method called updatedTransactions that delivers a transaction.payment.productIdentifier that identifies the product that was just purchased or restored. – Peter B. Kramer Nov 22 '17 at 20:26
Refer to this In-App Purchase FAQ My app validates its receipt with the App Store via paymentQueue:updatedTransactions: after a successful purchase. However, the returned receipt contains an empty in_app array rather than the expected products.
An empty in_app array indicates that the App Store has not recorded any transactions for the user yet. It may be that the application receipt has not yet been updated. When this happens, your app can inform the user that the receipt does not appear current and ask whether to refresh it.
Information about consumable products is added to the receipt when they are 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. Thus resulting into an empty in_app array if your app only sells consumable products.

- 27,015
- 29
- 156
- 295