21
votes

Once I get a receipt from client and validate it by apple server, then I got a transaction id of the new purchase (it's an auto-subscription purchase) in this receipt. After a few days , I get a new receipt from the same client and validate it , strange things happen : the transaction id of that old purchase changes.

I compare the data of this purchase in the old receipt with the data in the new receipt , the only thing changes is the transaction_id field ,the original_transaction_id, purchase_date, expires_date, web_order_line_item_id and other fields are exactly same.

Than I check the database, I found about 1% transaction records have the same situation. And there is a trait, Most of their transaction id were increased or decreased by 1-2 .

I used to think the transaction id is the identifier of a purchase. Does anyone meet the same problem or know the reason?

2
I am facing the same issue now and am interested in knowing how did you address the problem?Sriram
Since I can't rely on transaction_id or web_order_line_item_id just now, I consider a purchase with new transaction_id and new web_order_line_item_id as a new purchase.PE Xie

2 Answers

18
votes

Yes we see this happen as well. We see this triggered by 'Restore Purchase' button clicks.

If your 'Restore Purchase' button uses the restoreCompletedTransactions API then this will cause your transaction ID's to change. We have confirmed that this with Apple developer support.

Apparently you can call SKReceiptRefreshRequest instead which will just grab the latest receipt instead of replaying all of the transactions. It is my understanding that this will not cause the transaction ids to change.

We have, anecdotally, witnessed that the web_order_line_item_id values do not change across calls to restoreCompletedTransactions. However we only received an ambiguous, at best, response from Apple developer support when we asked for confirmation:

In regards to the web_order_line_item_id field, the value will change on every subsequent renewal.

You can use this, as long as you continue to store the new value as the renewal subscription events come in.

We take this to mean that the web_order_line_item_id is unique per renewal-purchase. Which neither confirms nor denies that it remains constant across calls to restoreCompletedTransactions

Additionally, I found this conference recording on Apple/Google/Amazon recurring billing very helpful (though, not for this particular case):

Rosa Gutierrez - The recurring nightmare. Implementing cross platform in-app subscription purchases

7
votes

Based on latest Apple developer documentation,

web_order_line_item_id - A unique identifier for purchase events across devices, including subscription-renewal events. This value is the primary key for identifying subscription purchases.

transaction_id - You can use this value to:

  1. Manage subscribers in your account database. Store the transaction_id, original_transaction_id, and product_id for each transaction, as a best practice to store transaction records for each customer. App Store generates a new value for transaction_id every time the subscription automatically renews or is restored on a new device.
  2. Differentiate a purchase transaction from a restore or a renewal transaction. In a purchase transaction, the transaction_id always matches the original_transaction_id. For subscriptions, it indicates the first subscription purchase. For a restore or renewal, the transaction_id does not match the original_transaction_id. If a user restores or renews the same purchase multiple times, each restore or renewal has a different transaction_id.