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

purchaseUpdateListener is getting called multiple times in IOS #801

Closed
anuragdwivedi29 opened this issue Oct 19, 2019 · 19 comments
Closed
Labels
🙏 help wanted Extra attention is needed 📱 iOS Related to iOS 🚶🏻 stale Stale

Comments

@anuragdwivedi29
Copy link

Version of react-native-iap

4.0.4

Version of react-native

0.60.5

Platforms you faced the error (IOS or Android or both?)

IOS

Expected behavior

should be called when requestSubscription(subscriptionID) is called

Actual behavior

is getting called when the app loads for the very first time.Also when a subscription is bought it is getting called multiple times

Tested environment (Emulator? Real Device?)

Real Device (sandbox environment)

Steps to reproduce the behavior

@anuragdwivedi29
Copy link
Author

are there any pointers for the above mentioned issue?

@bang9
Copy link
Contributor

bang9 commented Oct 21, 2019

maybe clearTransactionIOS() would help you , but i'm not sure :p
reference

@anuragdwivedi29
Copy link
Author

ok i will try that but i am testing the in app purchase in sandbox environment .So when i am launching the app and before making any purchase it is calling the clearTransactionIOS() and is making the purchase which should not be the behaviour. Ideally only when the user makes the purchase the it should ask for the payment and make the purchase.So therefore i am not able to understand as to what i am doing wrong here.
Any pointers would be highly appreciated.Thanks

@franj0
Copy link

franj0 commented Oct 22, 2019

@anuragdwivedi29 if you did not finish transaction on app relaunch update listener will try automatically execute code inside.

Also do not forgot this.yourListener.remove() on unmount...

Maybe something of this you need. gl

@hyochan hyochan added 🙏 help wanted Extra attention is needed 📱 iOS Related to iOS labels Oct 22, 2019
@mingxin-yang
Copy link

+1

@nicolaswilliman
Copy link

This is happeening to me too. The difference is that I'm using the 3.2.3 version of RNIap.
I'm also removing the listener when unmounting, but the purchaseUpdateListener is getting called multiple times with differents transaction ids. Just happens in iOS.

Any ideas?

@bang9
Copy link
Contributor

bang9 commented Nov 18, 2019

@nicolaswilliman @anuragdwivedi29 @mingxin-yang @franj0
I found the reason, refer this link(https://help.apple.com/app-store-connect/#/dev7e89e149d)

one auto-renewable subscription makes 6 renew transactions on Sandbox Environment
If you turn the app back on 20 minutes after subscribe a 1week
6 renew transactions that occurred every 3 minutes will enter the purchaseUpdatedListener at once

(on Production Environment, if a user that subscribes month plan re-payment after a month, the renew transaction will enter the purchaseUpdatedListener.)

@alexpchin
Copy link

@bang9 Do you have a solution for this? I understand that the purchaseUpdatedListener is being called multiple times

@bang9
Copy link
Contributor

bang9 commented Nov 19, 2019

@bang9 Do you have a solution for this? I understand that the purchaseUpdatedListener is being called multiple times

If you don't want to getting six times of renew transactions after purchased auto-renewable subscription

1. purchase auto-renewable subscription
2. logout previous sandbox account
3. create a new sandbox account
4. login with new sandbox account

I don't think it is efficiently :P
six times of renew transaction is needed for testing renew properly

this is not above case

@jonnyberanek
Copy link

Perhaps a way to handle resubscribe events would be to reference originalTransactionDateIOS which is present in the given ProductPurchase? Is this field undefined on the initial purchase of a subscription?

@karltaylor
Copy link

maybe clearTransactionIOS() would help you , but i'm not sure :p
reference

clearTransactionIOS method is deprecated.

If believe it might be worth checking to see if a 'purchase button' has been pressed, and then processing with your normal purchase flow. Otherwise you will have to do some extra logic to handle these resubscribe events.

@denkeni
Copy link
Contributor

denkeni commented Dec 24, 2019

I would suggest not deprecating clearTransactionIOS.

I have experience of implementing iOS IAP subscription that, unexpected numbers of transactions coming. I understand there are condensed intervals for sandbox testing environment, just as @bang9 mentioned above, but it was not the case.

It turned out that I implemented a mechanism similar to clearTransactionIOS to ignore any retrying transactions on app launch. So the user would need to manually restore purchase if any error happened, but it's a more clear and expected behavior.

@stale
Copy link

stale bot commented Apr 8, 2020

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as "For Discussion" or "Good first issue" and I will leave it open. Thank you for your contributions.

@stale stale bot added the 🚶🏻 stale Stale label Apr 8, 2020
@stale
Copy link

stale bot commented May 9, 2020

Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please feel free to create a new issue with up-to-date information.

@Abdulmateenchitrali
Copy link

+1

@erenkulaksiz
Copy link

Having the same issue on sandbox env. I'm not going to do something for this but calling my API like 10 times in a single go is not the way. Also server validates all receipts and thinks like i received 10 subscriptions.

@rashonwill
Copy link

Same issue in sandbox, sending multiple receipts to the backend on a consumable purchase and all getting validated making multiple database entries.

@Karthik-V26
Copy link

Hey, did you find any solution for this issue?

@JuGit-pk
Copy link

JuGit-pk commented Dec 10, 2024

What's the conclusion? I need a solution as I'm still encountering this issue on iOS.

Please take a look at my implementation.

1. INIT IAP

  const initializeIAP = async () => {
    try {
      const isConnected = await initConnection();
      if (Platform.OS === 'android') {
        await flushFailedPurchasesCachedAsPendingAndroid();
      } else if (Platform.OS === 'ios') {
        console.log('CLEARTING IOS clearTransactionIOS');
        await clearTransactionIOS();
      }
    } catch (error) {
      console.error('Error initializing IAP: ', error);
    }
  };
  useEffect(() => {
    initializeIAP();

    return () => {
      endConnection();
    };

2. Method to Request Subscription

  const handleBuySubscription = async () => {
    if (selectedPackage) {
      try {
        // ios
        let subsParams: RequestSubscription = {
          sku: selectedPackage.productId,
          andDangerouslyFinishTransactionAutomaticallyIOS: false,
        };
        if (Platform.OS === 'android' && currentSubscriptionOffer) {
          const sku = currentSubscription?.productId as string;
          const offerToken = currentSubscriptionOffer.offerToken;

          subsParams = {
            sku,
            ...(offerToken && {subscriptionOffers: [{sku, offerToken}]}),
          };
        }

        requestSubscription(subsParams);
      } catch (err: any) {
        console.warn(err.code, err.message);
      }
    }
  };

3. Purchase Listener

 useEffect(() => {
    // Initialize purchase listeners
    let purchaseUpdateSubscription = purchaseUpdatedListener(async purchase => {
      const receipt = purchase.transactionReceipt;
      if (receipt) {
        try {
          const payload = {
            receipt,
            os_type: Platform.OS,
          };
          debouncedAcknowledgementReceiptAPI(payload, {
            onSuccess: async () => {
              qc.invalidateQueries({queryKey: ['billing-details']});
              if (isBillingModalVisible) {
                setIsBillingModalVisible(false);
              }
              setIsModalVisible(true);
              await finishTransaction({purchase, isConsumable: false});
              await getPurchaseHistory();
            },
          });
        } catch (error) {
          console.error('Error during purchase handling:', error);
        }
      }
    });

    let purchaseErrorSubscription = purchaseErrorListener(error => {
      console.error('Purchase error:', error);
    });

    // Cleanup listeners on unmount
    return () => {
      lastTransactionRecipe.current = null;
      purchaseUpdateSubscription.remove();
      purchaseUpdateSubscription = null as any;
      purchaseErrorSubscription.remove();
      purchaseErrorSubscription = null as any;
    };
  }, [
    debouncedAcknowledgementReceiptAPI,
    getPurchaseHistory,
    qc,
    isBillingModalVisible,
    setIsBillingModalVisible,
    profileData?.email,
  ]);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🙏 help wanted Extra attention is needed 📱 iOS Related to iOS 🚶🏻 stale Stale
Projects
None yet
Development

No branches or pull requests