React-native-iap: purchaseUpdatedListener é chamado repetidamente

Criado em 3 fev. 2020  ·  6Comentários  ·  Fonte: dooboolab/react-native-iap

Versão do react-native-iap

4.3.0

Versão do react-native

0,60,5

Plataformas em que você enfrentou o erro (IOS ou Android ou ambos?)

Ambos

Comportamento esperado

Seguindo o exemplo, desejo chamar um método personalizado após a compra da minha assinatura. É meu entendimento que, após reconhecer a compra, o ouvinte deve ser removido? Tentei chamar explicitamente remove mas não tive sucesso.

Exemplo

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

Comportamento real

O método callCustomEndpoint () está sendo chamado várias vezes. Como posso impedir que isso aconteça? Como só preciso atingir esse ponto final uma vez.

Estou usando um componente funcional em vez de um componente de classe, se for importante.

Ambiente testado (emulador? Dispositivo real?)

Dispositivo real

Passos para reproduzir o comportamento

🙏 help wanted

Comentários muito úteis

Vou colocar minha solução de ganchos para quem vai precisar mais tarde.

fora do seu componente de estado (embora provavelmente funcione também dentro):

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);
  });
};

dentro do seu componente de estado:

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

Todos 6 comentários

Estou suspeitando que você registrou o purchaseListener várias vezes quando o componente foi processado novamente.

Obrigado, reescrevi isso usando ganchos para que não seja chamado em cada renderização. Meu erro foi tentar pegar o exemplo fornecido na documentação de um componente de classe e portá-lo para um componente funcional. Excelente trabalho na biblioteca!

@cgathergood Também estou tendo esse problema. Você se importa em postar seu código de manipulador de eventos usando os hooks react?

@cgathergood eu gostaria de ver um exemplo de código também. estou um pouco lutando com ganchos.

@ wootwoot1234 @osmantuna Você pode fornecer os códigos do manipulador de eventos se conseguiu corrigi-los?

Vou colocar minha solução de ganchos para quem vai precisar mais tarde.

fora do seu componente de estado (embora provavelmente funcione também dentro):

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);
  });
};

dentro do seu componente de estado:

useEffect(() => {
    loadIAPListeners();
    return () => {
      purchaseUpdateSubscription.remove();
      purchaseErrorSubscription.remove();
    };
  }, []);
Esta página foi útil?
0 / 5 - 0 avaliações