Client transaction ID does not match transaction ID from receipt

Environment: Production

Product type: Subscription

Client

- completed a subscription purchase

- sent to the server:

- transaction ID: 520000448162796

- receipt: MIIUFAYJKoZ...vn3Zdfsb8=


Server

- sends this receipt to the Apple's verification server (buy.itunes.apple.com/verifyReceipt)

- gets receipt/in_app/purchase:

{

"quantity":"1",

"product_id":"ru.rt.itv.dlyasvoih",

"transaction_id":"520000448157321",

"original_transaction_id":"520000448157321",

"purchase_date":"2019-06-09 02:14:41 Etc\/GMT",

"purchase_date_ms":"1560046481000",

"purchase_date_pst":"2019-06-08 19:14:41 America\/Los_Angeles",

"original_purchase_date":"2019-06-09 02:14:43 Etc\/GMT",

"original_purchase_date_ms":"1560046483000",

"original_purchase_date_pst":"2019-06-08 19:14:43 America\/Los_Angeles",

"expires_date":"2019-07-09 02:14:41 Etc\/GMT",

"expires_date_ms":"1562638481000",

"expires_date_pst":"2019-07-08 19:14:41 America\/Los_Angeles",

"web_order_line_item_id":"520000139001845",

"is_trial_period":"false",

"is_in_intro_offer_period":"false"

}


The question is,

- why does the identifier of the completed transaction on the client do not match the identifier of the transaction from the receipt?

520000448162796 vs 520000448157321

- How to correctly validate a purchase on the server if the transaction ID changes?

Additional information:

- Is the first purchase on the client and this is not a renewal of the old subscription (the transaction identifier is equal to the original transaction identifier)

- There are a lot of such cases: from 10 cases every day 😔 (I can provide more receipts and transaction identifiers not found)
See also:
https://forums.developer.apple.com/thread/84812
https://forums.developer.apple.com/thread/68944

Thanks, Roman

Replies

You don’t show the complete receipt........ The transactionIdentifier property in updatedTransactions can differ from the transaction_id for the subscription purchase. It is certainly different for restoreCompletedTransactions which are new transactions and therefore new transactionIdentifiers but the same transaction_id for the IAP. ........Regarding your question of how to correctly validate a receipt - what is your concern? If you wish to assure the transaction is not a duplicate the only way to do that is to check that the receipt is signed with the device’s identifierForVender using OpenSSL code. Unfortunately Apple screwed up this security feature years ago. ......If you are trying to tie together devices using the same subscription you can do that with original_transaction_id or web_order_line_item_id.

>How to correctly validate a purchase on the server if the transaction ID changes?


Note that "

paymentQueue(_:updatedTransactions:)
gets called when one or more transaction states change. This method evaluates the state of each transaction in an array of updated transactions and calls the relevant helper method:
complete(transaction:)
,
restore(transaction:)
or
fail(transaction:)
."


>There are a lot of such cases: from 10 cases every day


Good info, thanks, but what's the context? What percentage is that of a day's total?

Does your app tell your server when it is doing a restoreComplrtedTransactions? I believe these are receipts received by a user’s second device after they purchase on the first and do a restore on the second. Is that possible. If so, what are you trying to verify?

The transaction identifier and receipt are all that I receive from the client after the purchase.

I wanted by the identifier of the transaction that the client receives to find the transaction in the receipt and open access to the content.

As I understand it, if a user restores a purchase through the ___ method, then for each transaction a new one is created with a new transaction identifier? If so, then everything becomes clear.

If a user buys a subscription for the first time, can he get an invalid transaction ID that does not match the transaction ID from the receipt?

>if a user restores a purchase through the __(restoreCompletedTransaction) _ method, then for each transaction a new one is created with a new transaction identifier? If so, then everything becomes clear.


Yes, a new transaction is generated and it has a new transaction.transactionIdentifier in updatedTransactions. But in the receipt nothing is changed - and therefore this new transactionIdentifier is not in the receipt. In the 'old' days of iOS6 style receipts the value for original_transaction_id and transaction_id were different and the transaction_id reflected this transaction.transactionIdentifier.



>If a user buys a subscription for the first time, can he get an invalid transaction ID that does not match the transaction ID from the receipt?


I believe 'no'; the transaction.transactionIdentifier in updatedTransactions will be the same as the value in original_transaction_id and transaction_id.