- Home /
Prime31 StoreKit TransactionId Mismatch
I am using the recommended method of confirming IAP receipts. The client tries to purchase, sends the receipt data to our game server (along with the StoreKitTransaction.productIdentifier and transactionIdentifier), our server verifies the receipt with Apple's server and then our server verifies several things:
Purchase hasn't been used before (isn't in our db)
Purchase is for THIS app (by verifying both the bid and product_id)
transactionIdentifier client sends up from StoreKitTransaction is compared to transaction_id found in Apples receipt
About 95% of our purchases succeed. However, I've had two users whose transactions fail test 3. The StoreKitTransaction.transactionIdentifier the client sends to our game server is different from the transaction_id Apple's receipt contains.
Example of GOOD transaction:
Client sends to our server: transId:14021391238918, prodId:"500 coins"
Our server gets from Apple's server: transId:14021391238918, prodId:"500 coins"
Example of BAD transaction:
Client sends to our server: transId:CD9B55238-3C81-42B7-8TTW-62391FBDLQO6B, prodId:"500 coins"
Our server gets from Apple's server: transId:128391278321, prodId:"500 coins"
ALL of our successful transactionIds are 16 integers like in the good example above. ALL of the failed transactionIds are those big number/letter combos.
Any ideas? Thanks!
Possible interesting sidenote: The format for the failed transactionIds matches up exactly with the "unique_vendor_identifier" field of Apple's receipts.
TLDR: We sometimes experience: transactionId from client doesn't match tansactionId from Apple's receipt when validating from a server.
Answer by blindgoat · Apr 26, 2013 at 05:43 PM
I added more logging on our server. Turns out these really are users using bad data trying to fake purchases.
Apple response from endpoint=ssl://buy.itunes.apple.com: stdClass::__set_state(array( 'original_purchase_date_pst' => '2012-07-12 05:54:35 America/Los_Angeles',
'purchase_date_ms' => '1342097675882',
'original_transaction_id' => '170000029449420',
'original_purchase_date_ms' => '1342097675882',
'app_item_id' => '450542233',
'transaction_id' => '170000029449420',
'quantity' => '1',
'bvrs' => '1.4',
'version_external_identifier' => '9051236',
'bid' => 'com.zeptolab.ctrexperiments',
'product_id' => 'com.zeptolab.ctrbonus.superpower1',
'purchase_date' => '2012-07-12 12:54:35 Etc/GMT',
'purchase_date_pst' => '2012-07-12 05:54:35 America/Los_Angeles',
'original_purchase_date' => '2012-07-12 12:54:35 Etc/GMT',
'item_id' => '534185042', ))
So basically they are using an old purchase from Cut the Rope (NOT our app). A little research shows that this is a pretty common thing and there must be a jailbroken app out there that lets you try to buy stuff from other apps. See this
yeah, it's super-common .. indeed it's universal.
it's actually really, really hard to do IAP and so on, really securely. What a hassle!
Note that in the real world you really have to make your server track all transactions, and only ever approve a transaction to your app ONC$$anonymous$$
it's sort of the "elephant in the room" or the "dirty little secret" of doing IAP.
Ya - it's crazy how common it is. I'm just glad the system we put in place seems to be secure. We track all the transactions like you said and make sure they only occur once.
Thanks for marking it as the answer.
"We track all the transactions and make sure they only occur once"
You nailed it. Like I say, it's totally weird that you never hear people mentioning that. Like it's an absolute basic in the app store.
Just one of those weird things in life !
Hi Blindgoat and co
I'm curious as to HOW you track the transactions? Do you save the original transaction number or the product id number? Thanks.
Hi Blindgoat et al...
I'm curious as to HOW you track the transactions? Do you save the original transaction number or the product id number? Thanks.