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

Getting 21002 from Apple when verifying transactionReceipt #2436

Open
AaronCCWong opened this issue May 14, 2023 · 15 comments
Open

Getting 21002 from Apple when verifying transactionReceipt #2436

AaronCCWong opened this issue May 14, 2023 · 15 comments

Comments

@AaronCCWong
Copy link

Please use the Discussion board if you want to get some help. Please use issues to report bugs.

Description

Getting { 'status': 21002 } responses when calling /verifyReceipt with transactionReceipt.

Expected Behavior

/verifyReceipt should work.

Environment:

  • react-native-iap: 12.10.5
  • react-native: 0.71.7
  • Platforms (iOS, Android, emulator, simulator, device): iOS

To Reproduce
Steps to reproduce the behavior:

The sequence flow I use is as follows:

  1. requestSubscription on button click
  2. purchaseUpdatedListener gets triggered with a purchase object
  3. I call validateReceipt which is a method that sends the following to my web server:
{
        receipt: purchase.transactionReceipt,
        platform: Platform.OS,
        subscriptionId: purchase.productId,
        token: purchase.purchaseToken
}
  1. My web server makes a call to /verifyReceipt with the following request body:
{
    "receipt-data": transactionReceipt,
      "password": SECRET
      "exclude-old-transactions": true,
}
  1. Apple responds with { "status": 21002 }.

This worked until recently when I upgraded expo, react native and react-native-iap.

@midhunevolvier
Copy link

same problem here @andresesfm

@andresesfm
Copy link
Collaborator

Check the receipt is properly encoder in base 64

@AaronCCWong
Copy link
Author

This is a value that is returned through this library. That is, we get it from the purchase parameter of purchaseUpdateListener. If that returns a string that isn't properly base64 encoded, is there anything we can do on our end to make sure that it is?

@nightmre789
Copy link

nightmre789 commented May 22, 2023

@andresesfm Experiencing this same issue. The value in currentPurchase.transactionReceipt is malformed. We are receiving this value from the library itself, so it should be in proper Base64 format.

I am currently using requestSubscription and then using currentPurchase to send a validation request to my apple sandbox /verifyRequest using transactionReceipt. My subscription plans are loaded from Storekit config.

@andresesfm
Copy link
Collaborator

Look at ios/RNIapIos.swift:322. It is bein encoded there using base64EncodedString. Maybe play around with removing/changing the options argument

@numsu
Copy link

numsu commented May 27, 2023

Having the same issue. Value returned by this library and passed on to Apple as-is in the backend.

@midhunevolvier
Copy link

Does anyone have the solution? I am stuck.

@numsu
Copy link

numsu commented May 29, 2023

I decided to change my implementation because of this. Now I am sending the appAccountToken which contains an uuid of the purchase to Apple and verifying that the purchase is successful by verifying that in the S2S payload. Not handling receipts at all.

@ToyboxZach
Copy link

This is also happening to me, has anyone gotten a solution? @numsu do you have any details on how you were able to get that information?

@numsu
Copy link

numsu commented Aug 17, 2023

This is also happening to me, has anyone gotten a solution? @numsu do you have any details on how you were able to get that information?

  1. Generate an unique identifier on the client or your backend server once the user presses the "Buy" button and store it to your DB
  2. Set the generated identifier to the appAuthToken field with this library
  3. If the user completed the purchase, you will receive a S2S notification from Apple, if you have set it up. The payload will include your appAuthToken. Set the status of the purchase based on this notification

@MTPL0005-AbhishekDubey
Copy link

I was also facing the issue earlier but it was solved by making some changes to the way I was passing the parameter to the validateReceiptIos. before I was passing it as "RNIap.validateReceiptIos(receiptBody, true)". but now I have made the changes and called it like this "RNIap.validateReceiptIos({receiptBody: receiptBody, isTest: true})" and It started working properly .

@Fairbrook
Copy link

This is also happening to me, has anyone gotten a solution? @numsu do you have any details on how you were able to get that information?

1. Generate an unique identifier on the client or your backend server once the user presses the "Buy" button and store it to your DB

2. Set the generated identifier to the appAuthToken field with this library

3. If the user completed the purchase, you will receive a S2S notification from Apple, if you have set it up. The payload will include your appAuthToken. Set the status of the purchase based on this notification

Sorry to bother @numsu but I cannot seem to get Apple Store Server Notifications. The server url never gets called, the setup is alright as i used the test endpoint and the notification arrived properly
Do you have any idea what I'm doing wrong?

@tonytony2020
Copy link

confirm the same issue "react-native-iap": "^12.12.2",

@hotaryuzaki
Copy link

confirm the same issue "react-native-iap": "^12.13.0",

@hotaryuzaki
Copy link

i think one of the reasons this issue is rising is because the docs are not giving the right suggestions.
i solved with this useEffect

  useEffect(() => {
    const subscription = purchaseUpdatedListener((purchase) => {
      // console.log('>>> APP JS useEffect purchaseUpdatedListener', purchase.transactionReceipt);

      const verify = async purchase => {
        const verifyPurchase = await validateReceiptIos({
          receiptBody: { 'receipt-data': purchase.transactionReceipt },
          isTest: true
        });
      }

      verify(purchase);
    });

    return () => {
      subscription.remove();
    };
  }, []);

and another issue is that the name of the functions in the docs is wrong, it took me hours to realize this.
validateReceiptIos => in the docs is validateReceiptIOS

and another issue requestPurchaseWithQuantityIOS is undefined which i reported here

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

10 participants