voltrue2 / in-app-purchase

A Node.js module for in-App-Purchase for iOS, Android, Amazon and Windows.
http://iap.gracenode.org
Other
1.05k stars 289 forks source link

Apple: Consider handling app store app receipts - "The receipt is valid, but purchased nothing." #231

Open kaansoral opened 5 years ago

kaansoral commented 5 years ago

So Mac App Store purchases have receipts too, as I learned, which is great, as it allows easily verifying the purchase - However the library processes them as errors:

"{\"error\":{},\"status\":2,\"message\":\"The receipt is valid, but purchased nothing.\"}"

screen shot 2018-12-18 at 01 04 09

So it would be great if there was a better way to handle these reliably (I can process this data atm. but there are no guarantees that the error format won't change in the future)

Bonus Noob Question: Is there a way to determine a "Persistent User ID" from the receipt? - After some research, I believe the original Mac App Store app purchase "transaction_id" can be used as a persistent ID for the user, but since the library only produces an error, I wasn't able to reach it during my tests

voltrue2 commented 5 years ago

Hello,

The library does not suppose Mac App Store receipt at the moment, but I could try to add that in.

Regarding the persistent ID for the user, as you mentioned, original_transaction_id is the one to use.

Cheers

On Dec 18, 2018 at 07:04, <Kaan Soral (mailto:notifications@github.com)> wrote:

So Mac App Store purchases have receipts too, as I learned, which is great, as it allows easily verifying the purchase - However the library processes them as errors:

"{\"error\":{},\"status\":2,\"message\":\"The receipt is valid, but purchased nothing.\"}" (https://user-images.githubusercontent.com/170243/50118480-d7abfe80-0260-11e9-93c4-6986f2558011.png)

So it would be great if there was a better way to handle these reliably (I can process this data atm. but there are no guarantees that the error format won't change in the future)

Bonus Noob Question: Is there a way to determine a "Persistent User ID" from the receipt? - After some research, I believe the original Mac App Store app purchase "transaction_id" can be used as a persistent ID for the user, but since the library only produces an error, I wasn't able to reach it during my tests

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub (https://github.com/voltrue2/in-app-purchase/issues/231), or mute the thread (https://github.com/notifications/unsubscribe-auth/ACKY4UCkkXZcafV2qgDl9pf7mxj--J0tks5u6BTygaJpZM4ZXNoD).

kaansoral commented 5 years ago

Thanks,

For the purpose of only using the library for app purchase receipt verification, I modified this line: https://github.com/voltrue2/in-app-purchase/blob/develop/lib/apple.js#L377 - and reached the data without manually doing the call myself, would be nice to have a way to do just this, without having to modify the library

Edit: By the way, unless there's data in the receipt itself, there is no transaction_id in the response, only a download_id that is not guaranteed to be unique or non-mutable, as far as I see

voltrue2 commented 5 years ago

Hello

If you could show me what you changed and the results, I would be more then happy to update the library with it or you can send me a pull request with the change too!

Cheers

On Dec 18, 2018 at 10:02, <Kaan Soral (mailto:notifications@github.com)> wrote:

Thanks,

For the purpose of only using the library for app purchase receipt verification, I modified this line: https://github.com/voltrue2/in-app-purchase/blob/develop/lib/apple.js#L377 - and reached the data without manually doing the call myself, would be nice to have a way to do just this, without having to modify the library

— You are receiving this because you commented. Reply to this email directly, view it on GitHub (https://github.com/voltrue2/in-app-purchase/issues/231#issuecomment-448057224), or mute the thread (https://github.com/notifications/unsubscribe-auth/ACKY4aiFBMJFilaqF-gDf9D5Ree_aoZwks5u6D7BgaJpZM4ZXNoD).

kaansoral commented 5 years ago
screen shot 2018-12-18 at 04 23 48

&& 0 was the quick modification I made to see the data

screen shot 2018-12-18 at 04 24 02

^ Here's the data - receipt is an object (in case the indentation isn't clear), in_app is an empty array

voltrue2 commented 5 years ago

Thank you. I will have a look and see.

Cheers

voltrue2 commented 5 years ago

Hello,

My apologies for late response on this. The reason, you see this error is because the library is expecting in_app array in the response from Apple after validation. This is to prevent iOS purchase hacks. As you mentioned, in_app array is empty in this case... Now I am wondering if this is the intended Apple App Store's behavior or there's something missing... If you have some insights in this, it would be really great.

Cheers

bhallionOhbibi commented 5 years ago

Hello there !

I came accross the same issue today while inspecting some transactions made by our users. One of our user have tried to validate 2 purchases in a row.

The first response we got:

verification of purchase 330000464941702:

{ "error": {}, "response": { "receipt": { "receipt_type": "Production", "adam_id": 1314391359, "app_item_id": 1314391359, "bundle_id": "com.ohbibi.fps", "application_version": "2877", "download_id": 73043652729257, "version_external_identifier": 831021161, "receipt_creation_date": "2019-04-18 21:13:43 Etc/GMT", "receipt_creation_date_ms": "1555622023000", "receipt_creation_date_pst": "2019-04-18 14:13:43 America/Los_Angeles", "request_date": "2019-04-25 15:25:07 Etc/GMT", "request_date_ms": "1556205907158", "request_date_pst": "2019-04-25 08:25:07 America/Los_Angeles", "original_purchase_date": "2019-03-09 23:08:36 Etc/GMT", "original_purchase_date_ms": "1552172916000", "original_purchase_date_pst": "2019-03-09 15:08:36 America/Los_Angeles", "original_application_version": "2662", "in_app": [] }, "status": 2, "environment": "Production", "sandbox": false, "service": "apple", "message": "The receipt is valid, but purchased nothing." } }

The second:

verification of purchase 330000464941881:

{ "error": "Transaction not found", "response": { "receipt": { "receipt_type": "Production", "adam_id": 1314391359, "app_item_id": 1314391359, "bundle_id": "com.ohbibi.fps", "application_version": "2877", "download_id": 73042285285082, "version_external_identifier": 831021161, "receipt_creation_date": "2019-04-22 17:59:42 Etc/GMT", "receipt_creation_date_ms": "1555955982000", "receipt_creation_date_pst": "2019-04-22 10:59:42 America/Los_Angeles", "request_date": "2019-04-25 15:32:06 Etc/GMT", "request_date_ms": "1556206326548", "request_date_pst": "2019-04-25 08:32:06 America/Los_Angeles", "original_purchase_date": "2019-03-09 23:08:36 Etc/GMT", "original_purchase_date_ms": "1552172916000", "original_purchase_date_pst": "2019-03-09 15:08:36 America/Los_Angeles", "original_application_version": "2662", "in_app": [{ "quantity": "1", "product_id": "com.ohbibi.fps.speoffer4", "transaction_id": "330000464941702", "original_transaction_id": "330000464941702", "purchase_date": "2019-04-22 17:59:41 Etc/GMT", "purchase_date_ms": "1555955981000", "purchase_date_pst": "2019-04-22 10:59:41 America/Los_Angeles", "original_purchase_date": "2019-04-22 17:59:41 Etc/GMT", "original_purchase_date_ms": "1555955981000", "original_purchase_date_pst": "2019-04-22 10:59:41 America/Los_Angeles", "is_trial_period": "false" } ] }, "status": 0, "environment": "Production", "sandbox": false, "service": "apple" } }

Note that in the second you can see transaction ID of the first request...

I retried the requests and they always return the same response. A also checked here https://www.revenuecat.com/apple-receipt-checker just in case, same result.

I dont know how to handle thoses, perhaps its cheating ? perhaps it bug from apple-side ? I dont know how many users have encountered this either.

voltrue2 commented 5 years ago

Hello

The first purchase has an empty in_app array which is an indication of possible cheating or bug(s) in the purchase flow (usually client side) because you cannot get a receipt when you purchase nothing. The library successfully detected that and sending the application status 2, which is an error. The second receipt came back with an error claiming there is no such transaction, which means the client has not completed a purchase transaction.

I hope this helps!

Cheers

triplef commented 5 years ago

because you cannot get a receipt when you purchase nothing.

I don’t think that’s quite true: afaik downloading a free app also yields a receipt.

voltrue2 commented 5 years ago

Hello, what I meant by it is you cannot get a valid Apple receipt with empty in_app field unless you are hacking the app.

lincolnthree commented 3 years ago

@voltrue2 I am not sure that's the case. As @triplef said, downloading a free app also produces a receipt with no entitlements/in_app elements. So far we are checking for this error code and returning a "success" status instead if the customer is not in a purchase process.

In order to do this we have to JSON.parse(err) the error which is returned from in-app-purchase as a string', then check err.status === 2

triplef commented 3 years ago

Yes I can confirm that’s definitely the case that a free app downloaded from the App Store has a receipt without any In-App Purchases. Unfortunately I don’t think there’s a way to reproduce this without a live app on the store, but at least for macOS apps one can quite easily confirm this by downloading any free app from the Mac App Store and looking in the app bundle, which will contain a receipt file at Contents/_MASReceipt/receipt.