question

joltsoft avatar image
joltsoft asked

Unique identifier for purchases?

In our app we verify purchases on our server using the Amazon receipt validation service. The flow is usually: a) user purchases a consumable, b) we send the userId and purchaseToken to our servers for verification c) if valid, we update consumable count on server side and deliver some info back to the application. In order to prevent replays of the "verification" call, other platforms provide a unique identifier (an order ID or a transaction ID). Is there something like this for Amazon IAP? I don't see anything returned from the call that we can use to lookup orders by identifier to see if we are seeing a repeat order or a new one. I was thinking we could use purchaseToken, but I'm not entirely sure if that's guaranteed to be unique and unchangeable. Ideas? Will I need to compute my own unique identifier?
iap
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

joltsoft avatar image
joltsoft answered
Furthermore, I've noticed that the purchaseToken is identical for multiple purchase of the same consumable (at least using the Sandbox SDK app for fulfillment) so it cannot be used as a unique identifier. What should we use to uniquely identify individual purchases?
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sachin@Amazon avatar image
Sachin@Amazon answered
You can track the RequestID returned by each method so you can identify a response to its initiator. The PurchaseToken is dynamically generated each time Receipt data is returned and is not a unique order identifier. They are unique values for verifying the Receipt data returned in a response object. The PurchaseToken of a Receipt returned in a PurchaseResponse will be different than the PurchaseToken of a Receipt for the same user and sku returned in a PurchaseUpdatesResponse. Hope this helps. Thank you.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

joltsoft avatar image
joltsoft answered
I'm not sure that this helps. Here's where I'm running into a problem (or confusion!). Let's say we want to verify all purchases on our server (this is what our app on other platforms does), here's what happens in detail: 1) User initiates purchase of a consumable 2) User completes purchase of a consumable 3) In our Observer, we execute a call to our server passing along the userId and purchaseToken (HTTP GET) 4) On our server, we verify the purchaseToken using the Amazon API for verification 5) If the request comes back as valid, we update their account on our server and send a success message back to the client Without a way to uniquely identify this specific transaction, what's stopping a user from replaying the call to our server and increasing their consumable count without paying? On other platforms we use the transaction ID given, and if we see the same transaction ID come through that has already been delivered we ignore it. Since there doesn't appear to be a unique identifier included, I'm not sure we can handle transactions the same way. I *could* generate a unique identifier and enforce it all on our side, but I'm trying to keep the code paths for each App Store provider similar. All other platforms provide a transaction or reference ID. We also run into issues if there are billing questions, etc, and a user needs to contact us.. how can we communicate back to Amazon without some kind of order number or transaction ID?
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Dixith@Amazon avatar image
Dixith@Amazon answered
Thank you for your post. We have understand your issue in tracking of IAP purchases. In Live Environment, Currently Amazon IAP not providing unique transaction number or order id for purchasing of IAP items. During Testing environment(SDK tester), SDK tester produces the same purchase token for subsequent purchase of the same consumable item. Since the combination of userid and purchase token is the way to know whether a payment sent to the backend server or not. The live store will generate a different purchase token for each purchase, even if you purchase the same item. As a developer, you have access to the user ID, Purchase Token and SKU for a particular purchase. You need to compute your unique identifier for tracking of purchases based on the above values. Hope this information helps you.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

joltsoft avatar image
joltsoft answered
This helps, thank you! Just to reiterate, if the purchases are on the live environment, the purchaseToken will be unique per user, per purchase. Thank you!
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Anshul@Amazon avatar image
Anshul@Amazon answered
Yes if the purchases are on the live environment, then the purchaseToken will be unique.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

roddick04 avatar image
roddick04 answered
Hello, I have a further question regarding replay attacks. The Receipt Verification Service provides a method to renew an expired token. Couldn't a hacker use this method to generate a fresh token for the same order out of the expired one, and send this to the application's server? If the server only knows about the expired token it wouldn't realize it's a replay of the old order. Thanks, Marius
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sachin@Amazon avatar image
Sachin@Amazon answered
Hi, Can you please raise a ContactUs ( https://developer.amazon.com/help/contactus.html) for this and one of our support engineer will provide you more information on this. Thank you
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Andrei avatar image
Andrei answered
Hi guys Please dont stop discussion ) I have the same problem I work with AIR framework. So this is real case: 1 User make consumable purchase - coins pack 2 I recieved from OS that purchase is successed 3 Immediatly application send request to my server to validate it 4 But user lost internet connection at this moment. Application cannot verify purchase on the my server and server cann't increase user balance 5 User close application 6 User open application after 3 days 7 Really he made purchase and he wait coins pack on his balance How I can determine that this consumable purchase didn't processed? For example iOs opens transaction for every purchase and it arrives every application start until application close it. Message was edited by: chapayamazon
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Sujoy@Amazon avatar image
Sujoy@Amazon answered
Amazon IAP does not provide unique identifier for every transaction. So I would suggest you to generate an unique id on your own in the back end for every purchase attempt happening in your client. In the table of your database, you can have fields for unique transaction id (int, unique and autoincreament)and the status (enum value could be like NOT_PURCHASED - default value, PURCHASED) of current attempt. you should insert into that table while user is going to purchase any item in the app before triggering the initiatePurchaseRequest(). Send the transaction id back to client in the response of the same request. You need to also persist the id in the client (sql lite is recomended) and maintain the status of the transaction there (like NOT_PURCHASED - default value, PURCHASED_BUT_NOT_NOTIFIED_TO_GAME_SERVER, PURCHASED_AND_NOTIFIED_TO_GAME_SERVER). If user purchases the item, change the status of the current transaction attempt to "PURCHASED_BUT_NOT_NOTIFIED_TO_GAME_SERVER". Then send request to server to validate the token and change status of transaction attempt in the db table to "PURCHASED". After receiving the response of the this request in the client you should finally change the status of transaction in client to "PURCHASED_AND_NOTIFIED_TO_GAME_SERVER". This way you are maintaining the transaction log in client and server both so that you can sync later on. In start of your app, you can check the local transaction attempt persistence and if any purchase attempt stays in PURCHASED_BUT_NOT_NOTIFIED_TO_GAME_SERVER, you could resend the validation request that time. Hope this helps.
10 |5000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.