React-native-iap: purchaseUpdatedListener est appelé à plusieurs reprises

Créé le 3 févr. 2020  ·  6Commentaires  ·  Source: dooboolab/react-native-iap

Version de react-native-iap

4.3.0

Version de react-native

0,60,5

Plateformes sur lesquelles vous avez rencontré l'erreur (IOS ou Android ou les deux?)

Tous les deux

Comportement attendu

En suivant l'exemple, je souhaite appeler une méthode personnalisée après l'achat de mon abonnement. Je crois comprendre qu'après confirmation de l'achat, l'auditeur doit être supprimé? J'ai essayé d'appeler explicitement remove mais je n'ai pas réussi.

Exemple

 const purchaseListener = purchaseUpdatedListener(purchase => {
      const receipt = purchase.transactionReceipt;
      if (receipt) {
        callCustomEndpoint().then(result => {
          if(result){
            // Subscription is valid
            finishTransaction(purchase);
          }
        }) 
      };
      finishTransaction(purchase);
    });

Comportement réel

La méthode callCustomEndpoint () est appelée plusieurs fois. Comment puis-je empêcher cela? Comme je n'ai besoin d'atteindre ce point de terminaison qu'une seule fois.

J'utilise un composant fonctionnel au lieu d'un composant de classe si c'est important.

Environnement testé (émulateur? Real Device?)

Appareil réel

Étapes pour reproduire le comportement

🙏 help wanted

Commentaire le plus utile

Je vais déposer ma solution pour les crochets pour ceux qui en auront besoin plus tard.

en dehors de votre composant d'état (bien que fonctionne probablement aussi à l'intérieur):

var purchaseUpdateSubscription;
var purchaseErrorSubscription;
const loadIAPListeners = () => {
  initConnection(); // important, or else it won't trigger before a random state change
  purchaseUpdateSubscription = purchaseUpdatedListener(
    async (
      purchase: InAppPurchase | SubscriptionPurchase | ProductPurchase,
    ) => {
      console.log('purchaseUpdatedListener', purchase);
      let receipt = purchase.transactionReceipt;
      if (receipt) {
        apis.checkreceipt({data: purchase, platform: Platform.OS}); // I personally don't care about callback
        if (Platform.OS === 'ios') {
          await RNIap.finishTransactionIOS(purchase.transactionId);
        } else if (Platform.OS === 'android') {
          await RNIap.acknowledgePurchaseAndroid(purchase.purchaseToken);
        }
        await RNIap.finishTransaction(purchase, true);
        await RNIap.finishTransaction(purchase, false);
      } else {
        // Retry / conclude the purchase is fraudulent, etc...
      }
    },
  );
  purchaseErrorSubscription = purchaseErrorListener((error: PurchaseError) => {
    console.log('purchaseErrorListener', error);
  });
};

à l'intérieur de votre composant d'état:

useEffect(() => {
    loadIAPListeners();
    return () => {
      purchaseUpdateSubscription.remove();
      purchaseErrorSubscription.remove();
    };
  }, []);

Tous les 6 commentaires

Je soupçonne que vous avez enregistré purchaseListener plusieurs fois lors de la réédition des composants.

Merci, j'ai depuis réécrit cela en utilisant des crochets afin qu'il ne soit pas appelé à chaque rendu. Mon erreur a été d'essayer de prendre l'exemple fourni dans la documentation d'un composant de classe et de le porter sur un composant fonctionnel. Excellent travail sur la bibliothèque!

@cgathergood J'ai aussi ce problème. Cela vous dérange-t-il de publier le code de votre gestionnaire d'événements à l'aide de hooks de réaction?

@cgathergood je voudrais également voir un exemple de code. je suis un peu aux prises avec des crochets.

@ wootwoot1234 @osmantuna Pouvez-vous fournir les codes du gestionnaire d'événements si vous avez réussi à résoudre le problème?

Je vais déposer ma solution pour les crochets pour ceux qui en auront besoin plus tard.

en dehors de votre composant d'état (bien que fonctionne probablement aussi à l'intérieur):

var purchaseUpdateSubscription;
var purchaseErrorSubscription;
const loadIAPListeners = () => {
  initConnection(); // important, or else it won't trigger before a random state change
  purchaseUpdateSubscription = purchaseUpdatedListener(
    async (
      purchase: InAppPurchase | SubscriptionPurchase | ProductPurchase,
    ) => {
      console.log('purchaseUpdatedListener', purchase);
      let receipt = purchase.transactionReceipt;
      if (receipt) {
        apis.checkreceipt({data: purchase, platform: Platform.OS}); // I personally don't care about callback
        if (Platform.OS === 'ios') {
          await RNIap.finishTransactionIOS(purchase.transactionId);
        } else if (Platform.OS === 'android') {
          await RNIap.acknowledgePurchaseAndroid(purchase.purchaseToken);
        }
        await RNIap.finishTransaction(purchase, true);
        await RNIap.finishTransaction(purchase, false);
      } else {
        // Retry / conclude the purchase is fraudulent, etc...
      }
    },
  );
  purchaseErrorSubscription = purchaseErrorListener((error: PurchaseError) => {
    console.log('purchaseErrorListener', error);
  });
};

à l'intérieur de votre composant d'état:

useEffect(() => {
    loadIAPListeners();
    return () => {
      purchaseUpdateSubscription.remove();
      purchaseErrorSubscription.remove();
    };
  }, []);
Cette page vous a été utile?
0 / 5 - 0 notes