React-native-iap: purchaseUpdatedListener chamado apenas uma vez no início do aplicativo e nunca chama após a chamada de requestSubscription

Criado em 21 abr. 2020  ·  22Comentários  ·  Fonte: dooboolab/react-native-iap

Versão do react-native-iap

4.4.6

Versão do react-native

0.61.5

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

ios

Comportamento esperado

purchaseUpdatedListener chamada, após requestSubscription chamada

Comportamento real

purchaseUpdatedListener chamado apenas uma vez no início do aplicativo e nunca chama após a chamada de requestSubscription

Ambiente testado (emulador? Dispositivo real?)

Dispositivo real

Passos para reproduzir o comportamento

Basta seguir o readme e tentar solicitar a assinatura

📱 iOS 🕵️‍♂️ need more investigation 🙏 help wanted

Comentários muito úteis

Tive o mesmo problema porque não adicionei a chamada initConnection() .
O README parece ter sido atualizado apenas com a parte em negrito aqui:

initConnection() No iOS, ele simplesmente chamará o método canMakePayments e retornará o valor __que é necessário para que os ouvintes funcionem corretamente .__

Eu acho que esta parte "No iOS, ele simplesmente chamará canMakePayments" deve ser removida, também initConnection() deve ser adicionada ao exemplo básico

Eu estava realmente convencido de que era opcional porque não estava no exemplo

Adicionar initConnection() antes de registrar o ouvinte de compra corrigiu isso para mim, então provavelmente está relacionado a # 1002 e # 756

Todos 22 comentários

Alguém mais está tendo o mesmo problema? @Strate você chamou finishTransaction ?

@hyochan sim, mas na verdade essa chamada acontece após a reinicialização do aplicativo

@hyochan Eu tentei um pacote de compra expo-in-app e não há nenhum problema como este - tudo parece estar bem

@Strate Quero ver seu código. Não consigo encontrar nenhum erro :(

este problema é absolutamente irritante. Existe uma versão anterior em que este não seja o caso?

Alguém mais está tendo o mesmo problema? @Strate você chamou finishTransaction ?

Como isso seria possível, já que a compra é um argumento em finishTransaction? Portanto, você precisa do ouvinte de evento para obter o argumento a ser transmitido para finishTransaction.

Espera-se que @Sophrinix purchaseUpdatedListener

@hyochan desculpe, mas parece que não tenho um código real agora, mudei para o módulo expo-in-app-purchase . Parece que @Sophrinix está tendo o mesmo problema.

A propósito, não havia nada de especial no meu código: registre o ouvinte assim que o aplicativo iniciar e apenas siga o readme.

Acontece que esta é uma regressão.

Se você usar as seguintes versões, tudo funcionará:

"react": "16.8.1",
"react-native": "^0.59.10",
"react-native-iap": "4.3.0",

O problema surge quando você tenta usar react-native-iap 4.4.4 e uma versão de react-native antes de 0.60

@Sophrinix Acabei de experimentar requestPurchase do meu lado e tudo parece estar funcionando. Você poderia compartilhar um pouco do seu código?

Além disso, verifique novamente se você chamou initConnection . Esta é uma mudança crítica em uma atualização recente que agora é necessário ser chamada em iOS como em android .

Eu confirmo que reverter para 4.3.0 funciona. Eu estava enlouquecendo com a versão mais recente, estive depurando por mais de 1h tentando encontrar o problema.

Se eu puder adicionar, 4.3.4 por meio de 4.4.3 funcionam bem, o problema começa em 4.4.4

Se eu puder adicionar, 4.3.4 por meio de 4.4.3 funcionam bem, o problema começa em 4.4.4

Mesmo aqui, rebaixado de 4.4.8 para 4.4.3 e agora está funcionando!

Alguém mais está tendo o mesmo problema? @Strate você chamou finishTransaction ?

Estou tendo o mesmo problema em 4.4.0 - nenhum ouvinte de evento está sendo chamado, incluindo purchaseErrorSubscription .

Acabei de ler sobre o downgrade, estou prestes a tentar isso ...

Edit: Este é um problema sério porque:

  • evita que compras sejam enviadas para processamento do servidor
  • impede a reversão de estado quando alguém cancela a compra.

Também posso confirmar que 4.3.0 está funcionando.

Tive o mesmo problema por alguns dias com RN 0.62.2 e react-native-iap 4.4.8
De alguma forma, perdi initConnection() provavelmente porque está faltando no exemplo do README

Tive o mesmo problema no iOS ao atualizar para 4.4.8, o que fez com que algumas assinaturas não fossem concluídas. O downgrade para 4.4.3 resolveu o problema, por enquanto. InitConnection () é obrigatório? O doc faz parecer que não é

Tive o mesmo problema porque não adicionei a chamada initConnection() .
O README parece ter sido atualizado apenas com a parte em negrito aqui:

initConnection() No iOS, ele simplesmente chamará o método canMakePayments e retornará o valor __que é necessário para que os ouvintes funcionem corretamente .__

Eu acho que esta parte "No iOS, ele simplesmente chamará canMakePayments" deve ser removida, também initConnection() deve ser adicionada ao exemplo básico

Eu estava realmente convencido de que era opcional porque não estava no exemplo

Adicionar initConnection() antes de registrar o ouvinte de compra corrigiu isso para mim, então provavelmente está relacionado a # 1002 e # 756

Estou no 4.4.9 e o problema descrito por este tíquete também está acontecendo comigo.
O listener só é chamado quando iniciado, mas se eu configurá-lo e, em seguida, realizar a compra, ele não é chamado.
Eu resolvi isso inscrevendo-me diretamente no evento nativo, depois de olhar para react-native-iap/index.ts e descobrir que é o que acontece internamente.
Isso pode ser feito a qualquer momento e persistirá. (Certifique-se de que seja feito apenas uma vez)

import { NativeModules, NativeEventEmitter } from 'react-native';
import { Observable } from 'rxjs/Observable';

const purchaseEvent = Observable.fromEvent(
  new NativeEventEmitter(NativeModules.RNIapIos),
  'purchase-updated'
);
const purchaseSubscription = purchaseEvent.subscribe((transactionData) => {
  // Trigger server receipt validation here...
});
const errorEvent = Observable.fromEvent(
  new NativeEventEmitter(NativeModules.RNIapIos),
  'purchase-error'
);
const errorSubscription = errorEvent.subscribe((errorData) => {
  // Handle errors here...
});

Muitas pessoas estão cometendo erros porque initConnection() não está no código de exemplo do README. Eu adicionei aqui: # 1088, mas se alguém pudesse verificar meu código, ficaria grato. (Ainda não tenho meu código funcionando totalmente, então não estou muito confiante sobre isso ...)

Eu também estava encontrando esse problema na v5.1.1. initConnection não resolveu. Os retornos de chamada do ouvinte nunca são acionados em purchaseUpdate. Funciona bem no Android. Minha solução alternativa foi usar Observáveis ​​como o fez @mrozanski .

import React, { useContext, useEffect, useState } from 'react';
import { Alert, EmitterSubscription, Platform, NativeEventEmitter,
    NativeModules } from 'react-native';
import { connect } from 'react-redux';
import RNIap, {
    InAppPurchase,
    PurchaseError,
    SubscriptionPurchase,
    purchaseErrorListener,
    purchaseUpdatedListener,
} from 'react-native-iap';
import { Observable, Subscription } from 'rxjs';

const RNIAPEvent = new NativeEventEmitter(NativeModules.RNIapIos);
const purchaseObservable = new Observable((subscriber) => {
    RNIAPEvent.addListener('purchase-updated', (event) => {
        subscriber.next(event);
    })
})

const RNIAPErrorEvent = new NativeEventEmitter(NativeModules.RNIapIos);
const purchaseErrorObservable = new Observable((subscriber) => {
    RNIAPErrorEvent.addListener('purchase-error', (event) => {
        subscriber.next(event);
    })
})


const Wrapper = ({ ...props }) => {

    let purchaseUpdateSubscription: EmitterSubscription | Subscription | null = null;
    let purchaseErrorSubscription: EmitterSubscription | Subscription | null = null;

    const validateTransaction = async (purchase: SubscriptionPurchase) => {    
        return new Promise(async (resolve) => {
              //resolve(validationResponseFromYourBackend)
        }
    }

    const handleSubEvent = async (purchase: InAppPurchase | SubscriptionPurchase) => {
        const receipt = purchase.transactionReceipt;
        const purchaseToken = purchase.purchaseToken
        if (receipt) {
            try {
                const result = await validateTransaction(purchase);
                if (result.status === 200) {
                    RNIap.acknowledgePurchaseAndroid(purchaseToken).then(() => {
                        RNIap.finishTransaction(purchase, false)
                        .then(() => giveYourUserValue())
                        .catch((e) => {
                            //
                        })
                    })
                }
            } catch (err) {
                //
            }
        }
    }


    useEffect(() => {
        RNIap.initConnection()
            .then(() => {
                RNIap.flushFailedPurchasesCachedAsPendingAndroid().catch(() => {
                    // exception
                    })
                .then(() => {
                    if (Platform.OS === 'ios') {
                        //Documented implementation has issues purchaseUpdatedListener callback
                        purchaseUpdateSubscription = purchaseObservable.subscribe((purchase) => {
                            console.log('purchase observable', purchase)
                            handleSubEvent(purchase);
                        });

                        purchaseErrorSubscription = purchaseErrorObservable.subscribe((error) => {
                            console.log('purchaseErrorListener', error);
                        })

                    } else {
                        //for android use the documented method. Callbacks work.
                        purchaseUpdateSubscription = purchaseUpdatedListener(
                            (purchase: InAppPurchase | SubscriptionPurchase) => {
                                handleSubEvent(purchase);
                            }

                        );
                        purchaseErrorSubscription = purchaseErrorListener(
                            (error: PurchaseError) => {
                               console.log('purchaseErrorListener', error);
                            },
                        );
                    }

                })
            })
        return () => {
              // clear your listeners
             //eg if Subscription purchaseErrorSubscription.unsubscribe() 
            //eg if EmitterSubscription purchaseErrorSubscription.remove() 
        }
    }, []);

    return (
        <InAppSubContext.Provider
            value={{
                someValueYouWantPassedDown: 'theValue'
            }}
        >
            {props.children}
        </InAppSubContext.Provider>
    )
}

const mapState = (state) => ({ someProps: 'yeah' });

const InAppSubscriptionManager = connect(mapState)(Wrapper);

export default InAppSubscriptionManager;

Agora você pode usar isso para envolver seu aplicativo em seu App.tsx :


import InAppSubscriptionManager from './path/to/inAppSubscriptionManager';
const App = () => {

    return (
        <Provider store={store}>
                <InAppSubscriptionManager>

                    <AppNavigator />

                </InAppSubscriptionManager>
        </Provider>
    );
}

export default App;

Ainda bem que ajudou. Temos isso em produção desde junho.
Ele mudou de Observável para este em algum ponto (não estamos usando texto datilografado)

      const purchaseEvent = new NativeEventEmitter(NativeModules.RNIapIos);
      const subscription = purchaseEvent.addListener(
        'purchase-updated',
        transactionData => {
          console.log('IAP-LOG purchase-updated');
          dispatch(validateRecepit(transactionData));
        }
      );
      const errorSubscription = purchaseEvent.addListener(
        'purchase-error',
        data => {
          crashlytics().log(`Purchase error ${JSON.stringify(data)}`);
          console.log('IAP-LOG purchase-error', data);
        }
      );
    };
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

fergalindez picture fergalindez  ·  5Comentários

makarsky picture makarsky  ·  3Comentários

jvandenaardweg picture jvandenaardweg  ·  4Comentários

sanilcgs picture sanilcgs  ·  3Comentários

Symyon picture Symyon  ·  5Comentários