Apple In-App Purchases - Server-side Validation

I have a problem checking the receipt of a mailbox on the server side. I tried to find a solution on the Internet, but failed.

So, the description: First of all, the application is made for iOS7. Secondly, I have several elements (type = Non-Renewing Subscription). Thus, the user can buy one or more items, and then he must manually update them (buy again).

Applications send a receipt to the server, I make a request to Apple and get the result with a lot of in_app receipts. Something like:

"in_app":[ { "quantity":"1", "product_id":"...", "transaction_id":"...", "original_transaction_id":"...", "purchase_date":"...", "purchase_date_ms":"...", "purchase_date_pst":"...", "original_purchase_date":"...", "original_purchase_date_ms":"...", "original_purchase_date_pst":"...", "is_trial_period":"..."}, { "quantity":"1", "product_id":"...", "transaction_id":"...","original_transaction_id":"...", "purchase_date":"...", "purchase_date_ms":"...", "purchase_date_pst":"...", "original_purchase_date":"...", "original_purchase_date_ms":"...", "original_purchase_date_pst":"...", "is_trial_period":"..."} ] 

So, each "receipt" in "in_app" has transaction_id. But how can I determine the transactionId of the current purchase? I would also like to test it and make sure that it is unique.

It bothers me: if someone receives one valid receipt, he will be able to crack our server-side API and make an unlimited number of purchases in the application with the same valid receipt.

Do I have to somehow decrypt and verify the "original" receipt for transaction_id, which I send to Apple for verification?

Any help / suggestions would be greatly appreciated. Thank you in advance.

Regards, Maxim

+7
ios in-app-purchase
source share
2 answers

@ Doug Smith

https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html

If you are viewing different fields on this page, you will find

Original Transaction ID: For a transaction that restores a previous transaction, the transaction ID of the original transaction. Otherwise, identical to the transaction identifier. This value corresponds to the original property of the transaction. All receipts in the renewal chain for automatic renewable subscriptions have the same value for this field.

So, for your non-car renewable subscriptions, you need to track two things on your server side:

  • The ID of the original receipt transaction that you are checking on the itunes server, link it to the user ID in your database.
  • Whether the request received from the client side will be a purchase or purchase of recovery.

Once you have these two things, you can write your logic on these two parameters, as shown below:

:: If the request is of the type “Purchase” and you already have the original transaction ID of this receipt associated with some other user ID, you can block this purchase.

:: If the request is of the type "Restore the purchase", and the request comes from the same user ID with which the identifier of the original transaction is associated with your database, and not block its recovery.

In addition, you can get your own logic based on these things, according to your needs.

Let me know if you have any further doubts.

0
source share

For each new transaction, apple sends a new receipt, which is unique, encodes it, so no one can fake data.

Get the transaction receipt from the completed transaction, encode it and send it to the server, and decode it on the server side and match it with sending one apple to the server.

 - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { _transactionArray = transactions; for (SKPaymentTransaction * transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: { NSData *receipt = transaction.transactionReceipt; [self sendReceiptToServer]; } break; case SKPaymentTransactionStateFailed: { // finish this transaction } break; case SKPaymentTransactionStateRestored: NSData *receipt = transaction.transactionReceipt; [self sendReceiptToServer:receipt]; } break; default: break; } }; } -(void)sendReceiptToServer:(NSData *)receipt { // encode receipt // send receipt to server // add success and error callback } -(void) receiptSuccess { // finish transaction here } -(void) receiptError { // try again sending receipt to server } 
0
source share

All Articles