Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue on v13 with validator event returning outdated receipt on iOS #1466

Closed
tomerdev opened this issue Sep 12, 2023 · 12 comments
Closed

Issue on v13 with validator event returning outdated receipt on iOS #1466

tomerdev opened this issue Sep 12, 2023 · 12 comments

Comments

@tomerdev
Copy link

When a purchase is made on iOS using the v13 plugin, the validator event is returning an outdated receipt. Which makes the server side validation of the transaction impossible since the receipt doesn't contain the new transaction.

I was able to find the issue, it is here, the loadAppStoreReceipt is returning the cached receipt instead of loading the new one.

An easy fix would be to simply check that the forceReceiptReload property isn't true (before we return the cached receipt in the loadAppStoreReceipt method). And make sure we switch the forceReceiptReload property to false right after calling loadAppStoreReceipt here.

Would it be possible to ship the fix in a future version @j3k0? Thanks

@j3k0
Copy link
Owner

j3k0 commented Sep 12, 2023 via email

@tomerdev
Copy link
Author

For subscriptions but not for consumables.

@lilmnm-kamikaze-
Copy link

lilmnm-kamikaze- commented Sep 13, 2023

I am having the same issue. I am able to validate one purchase then each purchase after with a different in app item it returns the previous appStoreReceipt that then gets sent to apple to validate but it is the first purchase that was already validated.
Using V13.8.0 plugin

@oduverne
Copy link

Hello, same problem here. My solution is to restart the app after doing a restore or a purchase but it is not a good solution

@heffthedev
Copy link

heffthedev commented Sep 13, 2023

This could explain why all our purchases (non_consumable) after an initial one do not get properly handled.

@heffthedev
Copy link

heffthedev commented Sep 19, 2023

The changes @tomerdev suggested do not seem to fix the issue for us in ios for non_consumables. So far the only way I could find to make a purchase of 2 products (shopping cart style) get correctly validated with our own validator is by calling restorePurchases() after the 2 purchases are completed. Then the most up to date receipt gets then sent to the validator and it all works.

I have not managed to get the plugin to send the latest receipt (of a 2+ product purchase) without calling restorePurchase(). Only the first purchase is contained inside the receipts transactions, any further ones are not (until restorePurchase()).

@lilmnm-kamikaze-
Copy link

The same for me. Is there any insight on this issue? Even with the 13.8.1 update i am still getting this issue.

@cmaas
Copy link

cmaas commented Sep 21, 2023

I can confirm this issue, but in my case, loadAppStoreReceipt is called once only and never reaches the cached-check branch that @tomerdev mentioned.

The flow is as follows as far as I can tell:
App starts → loads existing receipts via initializeAppReceipt() and caches the result. This happens every time the app starts, because on iOS, you have at least one transaction, which is the download of the app itself.

If you then buy an item (a consumable in my case), initializeAppReceipt() is called again, but this._receipt already exists and hence, the function exits here already: https://github.com/j3k0/cordova-plugin-purchase/blob/22ea0d6e8bffeed5f7219aa5af6fc88b39fdd3cf/src/ts/platforms/apple-appstore/appstore-adapter.ts#L382C30-L382C30

One thing though: This has nothing to do with the validator event. It happens during the entire flow of the transaction. The receipt is simply never updated.

@oduverne
Copy link

I did it this way by replacing the deprecated verifyReceipt by App Store Server API and it works great. Thank you!

It doesn't make validation impossible: Apple's API will return the history of all transactions (including newer ones).

On Sep 12, 2023 at 17:44:23, Tomer @.> wrote: When a purchase is made on iOS using the v13 plugin, the validator event is returning an outdated receipt. Which makes the server side validation of the transaction impossible since the receipt doesn't contain the new transaction. I was able to find the issue, it is here

if (this.bridge.appStoreReceipt?.appStoreReceipt) {
, the loadAppStoreReceipt is returning the cached receipt instead of loading the new one. An easy fix would be to simply check that the forceReceiptReload property isn't true (before we return the cached receipt in the loadAppStoreReceipt method). And make sure we switch the forceReceiptReload property to false right after calling loadAppStoreReceipt here . Would it be possible to ship the fix in a future version @j3k0 https://github.com/j3k0? Thanks — Reply to this email directly, view it on GitHub <#1466>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABO3CPVKXAITQSYOSGGR63X2BYMPANCNFSM6AAAAAA4U7BI3I . You are receiving this because you were mentioned.Message ID: @.>

@lilmnm-kamikaze-
Copy link

I did it this way by replacing the deprecated verifyReceipt by App Store Server API and it works great. Thank you!

It doesn't make validation impossible: Apple's API will return the history of all transactions (including newer ones).

On Sep 12, 2023 at 17:44:23, Tomer @.> wrote: When a purchase is made on iOS using the v13 plugin, the validator event is returning an outdated receipt. Which makes the server side validation of the transaction impossible since the receipt doesn't contain the new transaction. I was able to find the issue, it is here

if (this.bridge.appStoreReceipt?.appStoreReceipt) {
, the loadAppStoreReceipt is returning the cached receipt instead of loading the new one. An easy fix would be to simply check that the forceReceiptReload property isn't true (before we return the cached receipt in the loadAppStoreReceipt method). And make sure we switch the forceReceiptReload property to false right after calling loadAppStoreReceipt here . Would it be possible to ship the fix in a future version @j3k0 https://github.com/j3k0? Thanks — Reply to this email directly, view it on GitHub <#1466>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABO3CPVKXAITQSYOSGGR63X2BYMPANCNFSM6AAAAAA4U7BI3I . You are receiving this because you were mentioned.Message ID: @.>

@oduverne would you be able to make a pull request for the fix to help others?

@j3k0
Copy link
Owner

j3k0 commented Oct 5, 2023

The fix is server side, note that verifyReceipt will also return the list of newer transactions in the receipt. (check the difference between the in_app and latest_receipt fields)... Maybe you are using a (very) outdated library to handle this server side? In doubt, you can test validation with https://www.iaptic.com, AFAIK you should get the correct result.

@ersingencturk
Copy link

i was able to get the refreshed appstorereceipt with this way:

store.when().approved(verifyPurchase);  

verifyPurchase function:

switch (platform) {
      case "iOS":
        postData.type="ios-appstore";
        store.getAdapter("ios-appstore").refreshReceipt().then(function (s) {
          postData.appStoreReceipt=product.parentReceipt.nativeData.appStoreReceipt;
          serverValidateTransaction(product,postData);
        });

for me 13.10.1 version of this plugin is broken for ios , custom server validation.

i was using store.validator function to validate in app purchase but that seems to never receive in app purcahses only app itself with product.type="application"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants