dooboolab-community / react-native-iap

In App Purchase module for React Native!
https://react-native-iap.dooboolab.com
MIT License
2.78k stars 634 forks source link

ios - calling requestSubscription doesn't do nothing #2077

Closed kobishaked1 closed 1 year ago

kobishaked1 commented 1 year ago

Description

Using the requestSubscription method in android works just fine and opens the popup to make the purchase. however, in ios, nothing happens. it doesn't return any value or error and also doesn't trigger the purchaseErrorListener

Expected Behavior

open apple subscription popup

Screenshots:

image

Environment:

To Reproduce

Steps to reproduce the behavior:

  1. on ios device version 16 make a call to: await requestSubscription({sku: PRODUCT_ID});
  2. you will notice that nothing happen
andresesfm commented 1 year ago

It's not my experience, It's working fine on the IapExample app

kobishaked1 commented 1 year ago

it was fixed by adding the line: setup({storekitMode:'STOREKIT_HYBRID_MODE'}) right before the initConection method now the popup is coming up but I have another issue. the purchaseUpdateListener is not triggered after I get a popup that approves the payment. here is whole code of the listeners and the requestSubscription method:

useEffect(() => {
    if (!PRODUCT_ID) {
      return;
    }

    let purchaseUpdateSubscription: EmitterSubscription | undefined;
    let purchaseErrorSubscription: EmitterSubscription | undefined;

    getSubscriptions({skus: [PRODUCT_ID]})
      .then(prods => {
        if (!prods || prods.length === 0) {
          return;
        }

        if (Platform.OS === 'android') {
          offerTokenRef.current =
            prods[0].subscriptionOfferDetails[0]?.offerToken;
        }

        setGotProduct(true);

        purchaseUpdateSubscription = purchaseUpdatedListener(async purchase => {
          console.log(
            `the purchase we get from purchaseUpdatedListener: ${purchase}`,
          );
          await sendPayment({
            purchase,
            onSuccess: () => {
              setUser(userObj => ({
                ...userObj!,
                isFree: false,
                plan: 'Premium',
              }));
              navigation.dispatch(CommonActions.goBack());
            },
          });

          try {
            finishTransaction({purchase});
          } catch (error) {
            console.error(error);
          }
        });
        purchaseErrorSubscription = purchaseErrorListener(error => {
          console.error('purchaseErrorListener', error);
        });
      })
      .catch(e => console.error(e));

    return () => {
      purchaseUpdateSubscription?.remove();
      purchaseErrorSubscription?.remove();
    };
  }, [setUser, navigation]);

  const purchaseSubscription = async () => {
    if (!PRODUCT_ID || isPaymentOpen) {
      return;
    }
    setIsPaymentOpen(true);

    try {
      if (Platform.OS === 'ios') {
        await IapIos.clearTransactionIOS();
        await requestSubscription({sku: PRODUCT_ID});
      } else {
        await requestSubscription({
          subscriptionOffers: [
            {sku: PRODUCT_ID, offerToken: offerTokenRef.current},
          ],
        });
      }
    } catch (error) {
      console.error('from purchaseSubscription:', error);
    }

    setIsPaymentOpen(false);
  };

I really appreciate your help!

amkiran commented 1 year ago

Using setup({storekitMode:'STOREKIT_HYBRID_MODE'}) did work on iOS 15 and iOS 16 devices.

But requestSubscription doesn't work on iOS 14 with version react-native-iap: 12.1.0 on iOS 14 devices, calling requestSubscription does nothing.

Any idea if I'm missing something here?

andresesfm commented 1 year ago

Do you get an error or anything on the logs? Do you get anything returned?

amkiran commented 1 year ago

Do you get an error or anything on the logs? Do you get anything returned?

@andresesfm No errors are recorded in logs and the promise of requestSubscription never resolves.

I noticed the same issue on iOS 15 & 16 devices as well, but it's gone after upgrading to react-native-iap: 12.1.0. So the issue now happens only on iOS 14.

kobishaked1 commented 1 year ago

for me im using ios 16 and react-native-iap 12.1.1 and in some of the case the purchaseUpdatedListener fired and in other cases it doesn't.

ElicaInc commented 1 year ago

@andresesfm: Thank you for sharing your great libraries!

@andresesfm No errors are recorded in logs and the promise of requestSubscription never resolves.

I occasionally had the same issue (iOS15, react-native-iap 12.0.1) in TestFlight, but adding the line await clearTransactionIOS(); just before await requestSubscription({sku: productId}) works fine in my setting.

andresesfm commented 1 year ago

What storeKitMode are you using?

ElicaInc commented 1 year ago

What storeKitMode are you using?

STOREKIT2_MODE

herbertvuijk commented 1 year ago

Have this problem too. The problem is that there for some reason calling requestSubscription will first fire purchaseUpdatedListener if there are unfinished transactions. So let's say you have 5 unfinished purchases, trying to requestSubscription will not open the apple subscription popup, but instead cause an event trigger to purchaseUpdatedListener. This happens 4 more times, till everything is finished, only then it works.

My work around is this to call clearTransactionIOS before requestSubsription. Doesn't feel right to me though.

if (Platform.OS === 'ios') {
  await clearTransactionIOS();
}
await requestSubscription(obj);

Are there better solutions? I'm looking into using getPendingPurchasesIOS and finish all of them before attempting requestSubscription.

Note: I'm upgrading from RNIAP 8 to 12 at the moment, in the hope it would be more stable by now, it looks like it's not :(, having a wide array of issues. Might want to implement everything myself I guess

Update: I tried using getPendingPurchasesIOS to finish them before calling requestSubscription. Unfortunately that function doesn't seem to be implemented. [TypeError: (0, _internal.getIosModule)().getPendingTransactions is not a function. (In '(0, _internal.getIosModule)().getPendingTransactions()', '(0, _internal.getIosModule)().getPendingTransactions' is undefined)]

andresesfm commented 1 year ago

getPendingTransactions issue has been fixed