React-native-iap: purchaseUpdatedListener llamó solo una vez al inicio de la aplicación, y nunca llama después de requestSubscription call

Creado en 21 abr. 2020  ·  22Comentarios  ·  Fuente: dooboolab/react-native-iap

Versión de react-native-iap

4.4.6

Versión de react-native

0.61.5

Plataformas a las que se enfrentó el error (¿IOS o Android o ambos?)

ios

Comportamiento esperado

purchaseUpdatedListener llamado cada vez, después de requestSubscription llamada

Comportamiento real

purchaseUpdatedListener llamó solo una vez al inicio de la aplicación, y nunca llama después de requestSubscription call

Entorno probado (¿Emulador? ¿Dispositivo real?)

Dispositivo real

Pasos para reproducir el comportamiento

Solo sigue el archivo Léame e intenta solicitar una suscripción

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

Comentario más útil

Tuve el mismo problema que no agregué la llamada initConnection() .
Parece que el README acaba de actualizarse con la parte en negrita aquí:

initConnection() En iOS, simplemente llamará al método canMakePayments y devolverá el valor __que es necesario para que los oyentes funcionen correctamente .__

Creo que esta parte "En iOS, simplemente llamará a canMakePayments" debería eliminarse, también debería añadirse initConnection() al ejemplo básico

Estaba realmente convencido de que era opcional porque no estaba en el ejemplo.

Agregar el initConnection() antes de registrar el o los oyentes de compra solucionó esto para mí, por lo que probablemente esté relacionado con # 1002 y # 756

Todos 22 comentarios

¿Alguien más tiene el mismo problema? @Strate, ¿has llamado finishTransaction ?

@hyochan sí, pero en realidad esta llamada ocurre después del reinicio de la aplicación

@hyochan He probado el paquete expo-in-app-purchase, y no hay ningún problema como este: todo parece estar bien

@Strate Quiero ver tu código. No puedo encontrar ningún error yo mismo :(

este problema es absolutamente exasperante. ¿Existe una versión anterior donde este no sea el caso?

¿Alguien más tiene el mismo problema? @Strate, ¿has llamado finishTransaction ?

¿Cómo sería esto posible si la compra es un argumento en finishTransaction? Por lo tanto, necesita que el detector de eventos obtenga el argumento para pasar a finishTransaction.

Se espera que purchaseUpdatedListener

@hyochan lo siento, pero parece que no tengo un código real en este momento, he cambiado al módulo expo-in-app-purchase . Parece que @Sophrinix experimenta el mismo problema.

Por cierto, no había nada especial en mi código: registre el oyente tan pronto como se inicie la aplicación y simplemente siga el archivo Léame.

Resulta que esto es una regresión.

Si usa las siguientes versiones, entonces todo funciona:

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

El problema surge cuando intentas usar react-native-iap 4.4.4 y una versión de react-native antes de 0.60

@Sophrinix Acabo de probar requestPurchase en mi lado y todo parece estar funcionando. ¿Podría compartir algo de su código?

Además, verifique nuevamente si ha llamado a initConnection . Se trata de cambios críticos en una actualización reciente que ahora es necesario llamar en iOS como en android .

Confirmo que volver a 4.3.0 funciona. Me estaba volviendo loco con la última versión, he estado depurando durante más de 1 hora tratando de encontrar el problema.

Si puedo agregar, 4.3.4 hasta 4.4.3 funcionan bien, el problema comienza en 4.4.4

Si puedo agregar, 4.3.4 hasta 4.4.3 funcionan bien, el problema comienza en 4.4.4

Lo mismo aquí, degradado de 4.4.8 a 4.4.3 y ahora está funcionando.

¿Alguien más tiene el mismo problema? @Strate, ¿has llamado finishTransaction ?

Tengo el mismo problema en 4.4.0 : no se está llamando a purchaseErrorSubscription .

Solo lea sobre la degradación, estoy a punto de intentar eso ...

Editar: este es un problema grave porque:

  • evita que las compras se envíen para el procesamiento del servidor
  • evita la reversión del estado cuando alguien cancela la compra.

También puedo confirmar que 4.3.0 está funcionando.

Tuve el mismo problema durante unos días con RN 0.62.2 y react-native-iap 4.4.8
De alguna manera me perdí el initConnection() probablemente porque falta en el ejemplo en el README

Tuve el mismo problema en iOS al actualizar a 4.4.8, lo que hizo que algunas suscripciones no se completaran. La degradación a 4.4.3 resolvió el problema, por ahora. ¿Es obligatorio initConnection ()? El doctor hace que parezca que no lo es

Tuve el mismo problema que no agregué la llamada initConnection() .
Parece que el README acaba de actualizarse con la parte en negrita aquí:

initConnection() En iOS, simplemente llamará al método canMakePayments y devolverá el valor __que es necesario para que los oyentes funcionen correctamente .__

Creo que esta parte "En iOS, simplemente llamará a canMakePayments" debería eliminarse, también debería añadirse initConnection() al ejemplo básico

Estaba realmente convencido de que era opcional porque no estaba en el ejemplo.

Agregar el initConnection() antes de registrar el o los oyentes de compra solucionó esto para mí, por lo que probablemente esté relacionado con # 1002 y # 756

Estoy en 4.4.9 y el problema descrito por este ticket también me está sucediendo.
El oyente solo se invoca cuando se inicia, pero si lo configuro y luego realizo la compra, no se llama.
Lo resolví suscribiéndome al evento nativo directamente, después de mirar react-native-iap/index.ts y descubrir que eso es lo que sucede internamente.
Esto se puede hacer en cualquier momento y persistirá. (Solo asegúrate de que esté hecho solo una 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...
});

Mucha gente se está encontrando con errores porque initConnection() no está en el código de ejemplo de README. Lo agregué aquí: # 1088, pero si alguien pudiera verificar mi código, se lo agradecería. (Todavía no tengo mi código en pleno funcionamiento, así que no tengo mucha confianza en él ...)

También me encontré con este problema en v5.1.1. initConnection no lo resolvió. Las devoluciones de llamada del oyente nunca se activan en purchaseUpdate. Sin embargo, funciona bien en Android. Mi solución fue usar Observables como lo hizo

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;

Ahora puede usar esto para envolver su aplicación en su App.tsx :


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

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

                    <AppNavigator />

                </InAppSubscriptionManager>
        </Provider>
    );
}

export default App;

Me alegro de que haya ayudado. Tenemos esto en producción desde junio.
Cambió de Observable a esto en algún momento (no estamos usando mecanografiado)

      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);
        }
      );
    };
¿Fue útil esta página
0 / 5 - 0 calificaciones