React-native-iap: purchaseUpdatedListener appelé une seule fois au démarrage de l'application, et ne l'appelle jamais après la demande

Créé le 21 avr. 2020  ·  22Commentaires  ·  Source: dooboolab/react-native-iap

Version de react-native-iap

4.4.6

Version de react-native

0,61,5

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

ios

Comportement attendu

purchaseUpdatedListener appelé à chaque fois, après requestSubscription appel

Comportement réel

purchaseUpdatedListener appelé une seule fois au démarrage de l'application, et ne l'appelle jamais après la demande

Environnement testé (émulateur? Real Device?)

Appareil réel

Étapes pour reproduire le comportement

Suivez simplement le fichier Lisez-moi et essayez de demander un abonnement

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

Commentaire le plus utile

J'ai eu le même problème car je n'ai pas ajouté l'appel initConnection() .
Le README semble être juste mis à jour avec la partie en gras ici:

initConnection() Sur iOS, il appellera simplement la méthode canMakePayments et retournera la valeur __ qui est nécessaire pour que les écouteurs fonctionnent correctement .__

Je pense que cette partie "Sur iOS, il appellera simplement canMakePayments" devrait être supprimée, ainsi que initConnection() devrait être ajouté à l'exemple de base

J'étais vraiment convaincu que c'était facultatif car ce n'était pas dans l'exemple

L'ajout du initConnection() avant d'enregistrer le / les auditeur (s) d'achat a résolu ce problème pour moi, donc c'est probablement lié aux # 1002 et # 756

Tous les 22 commentaires

Quelqu'un d'autre a-t-il le même problème? @Strate avez-vous appelé finishTransaction ?

@hyochan oui, mais en fait cet appel se produit après le redémarrage de l'application

@hyochan J'ai essayé le package d'achat expo-in-app, et il n'y a pas de problème comme celui-ci - tout semble aller bien

@Strate Je veux voir votre code. Je ne trouve aucune erreur moi-même :(

cette question est absolument exaspérante. Existe-t-il une version antérieure où ce n'est pas le cas?

Quelqu'un d'autre a-t-il le même problème? @Strate avez-vous appelé finishTransaction ?

Comment cela serait-il possible car l'achat est un argument dans finishTransaction? Ainsi, vous avez besoin de l'écouteur d'événements pour obtenir l'argument à passer à finishTransaction.

@Sophrinix finishTransaction devrait être appelé dans purchaseUpdatedListener

@hyochan désolé, mais il semble que je n'ai pas de code réel pour le moment, je suis passé au module expo-in-app-purchase . On dirait que @Sophrinix rencontre le même problème.

Btw, il n'y avait rien de spécial dans mon code: enregistrez l'auditeur dès que l'application a démarré et suivez simplement le readme.

Il s'avère que c'est une régression.

Si vous utilisez les versions suivantes, tout fonctionne:

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

Le problème survient lorsque vous essayez d'utiliser react-native-iap 4.4.4 et une version de react-native antérieure à 0.60

@Sophrinix Je viens d'essayer requestPurchase de mon côté et tout semble fonctionner. Pourriez-vous s'il vous plaît partager une partie de votre code?

Veuillez également vérifier à nouveau si vous avez appelé initConnection . Il s'agit de changements critiques dans une mise à jour récente qu'il est maintenant nécessaire d'appeler dans iOS comme dans android .

Je confirme que le retour à la version 4.3.0 fonctionne. J'étais fou de la dernière version, j'ai débogué pendant plus d'une heure pour essayer de trouver le problème.

Si je peux ajouter, 4.3.4 à 4.4.3 fonctionne bien, le problème commence dans 4.4.4

Si je peux ajouter, 4.3.4 à 4.4.3 fonctionne bien, le problème commence dans 4.4.4

Idem ici, rétrogradé de 4.4.8 à 4.4.3 et cela fonctionne maintenant!

Quelqu'un d'autre a-t-il le même problème? @Strate avez-vous appelé finishTransaction ?

J'ai le même problème sur 4.4.0 - aucun des écouteurs d'événement n'est appelé, y compris purchaseErrorSubscription .

Lisez juste à propos du déclassement, je suis sur le point d'essayer ça ...

Edit: C'est un problème grave car:

  • il empêche l'envoi des achats pour le traitement du serveur
  • il empêche la restauration de l'état lorsque quelqu'un annule l'achat.

Je peux également confirmer que 4.3.0 fonctionne.

J'ai eu le même problème pendant quelques jours avec RN 0.62.2 et react-native-iap 4.4.8
J'ai en quelque sorte manqué le initConnection() probablement parce qu'il manque dans l'exemple dans le README

J'ai eu le même problème sur iOS lors de la mise à niveau vers 4.4.8, ce qui a rendu certains abonnements incomplets. Le passage à la version 4.4.3 a résolu le problème pour le moment. Est-ce que initConnection () est obligatoire? Le doc donne l'impression que ce n'est pas le cas

J'ai eu le même problème car je n'ai pas ajouté l'appel initConnection() .
Le README semble être juste mis à jour avec la partie en gras ici:

initConnection() Sur iOS, il appellera simplement la méthode canMakePayments et retournera la valeur __ qui est nécessaire pour que les écouteurs fonctionnent correctement .__

Je pense que cette partie "Sur iOS, il appellera simplement canMakePayments" devrait être supprimée, ainsi que initConnection() devrait être ajouté à l'exemple de base

J'étais vraiment convaincu que c'était facultatif car ce n'était pas dans l'exemple

L'ajout du initConnection() avant d'enregistrer le / les auditeur (s) d'achat a résolu ce problème pour moi, donc c'est probablement lié aux # 1002 et # 756

Je suis sur 4.4.9 et le problème décrit par ce ticket m'arrive également.
L'auditeur n'est appelé qu'au démarrage, mais si je le configure et que j'effectue ensuite l'achat, il n'est pas appelé.
Je l'ai résolu en m'inscrivant directement à l'événement natif, après avoir regardé react-native-iap/index.ts et compris que c'est ce qui se passe en interne.
Cela peut être fait à tout moment et persistera. (Assurez-vous simplement que ce n'est fait qu'une seule fois)

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

Beaucoup de gens se heurtent à des erreurs car initConnection() ne figure pas dans l'exemple de code du README. Je l'ai ajouté ici: # 1088, mais si quelqu'un pouvait vérifier mon code, ce serait apprécié. (Je n'ai toujours pas mon code pleinement opérationnel donc je ne suis pas trop confiant à ce sujet ...)

Je rencontrais également ce problème sur v5.1.1. initConnection ne l'a pas résolu. Les rappels d'auditeur ne sont jamais déclenchés lors de purchaseUpdate. Fonctionne bien sur Android cependant. Ma solution de contournement était d'utiliser Observables comme @mrozanski l'a fait.

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;

Vous pouvez maintenant l'utiliser pour envelopper votre application dans votre App.tsx :


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

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

                    <AppNavigator />

                </InAppSubscriptionManager>
        </Provider>
    );
}

export default App;

Heureux que cela ait aidé. Nous l'avons en production depuis juin.
Il a changé d'observable à ceci à un moment donné (nous n'utilisons pas de dactylographié)

      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);
        }
      );
    };
Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

jvandenaardweg picture jvandenaardweg  ·  4Commentaires

sanilcgs picture sanilcgs  ·  3Commentaires

coldfins picture coldfins  ·  3Commentaires

bakedbean picture bakedbean  ·  5Commentaires

jvandenaardweg picture jvandenaardweg  ·  4Commentaires