4.4.6
0.61.5
ios
purchaseUpdatedListener
llamado cada vez, después de requestSubscription
llamada
purchaseUpdatedListener llamó solo una vez al inicio de la aplicación, y nunca llama después de requestSubscription call
Dispositivo real
Solo sigue el archivo Léame e intenta solicitar una suscripción
¿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
hasta4.4.3
funcionan bien, el problema comienza en4.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:
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);
}
);
};
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í:
Creo que esta parte "En iOS, simplemente llamará a canMakePayments" debería eliminarse, también debería añadirse
initConnection()
al ejemplo básicoEstaba 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