react-native-iap": "^2.3.17
iOS
El pago debe realizarse solo cuando se llame a finishTransaction
El monto se detecta después de agregar un método de pago como tarjeta de crédito.
Pero se alcanzó el método RNIap.buyProductWithoutFinishTransaction(sku)
.
Dispositivo real - iPhone 6s
ComponentDidMount(){
await RNIap.initConnection();
await RNIap.consumeAllItems();
const prod = await RNIap.getProducts(product);
}
async componentWillUnmount() {
RNIap.endConnection()
}
buyProduct(sku){
await RNIap.clearTransaction();
RNIap.buyProductWithoutFinishTransaction(sku)
.then(purchase => {
// not reached
if(calltoserverisSuccess){
RNIap.finishTransaction();
}
})
.catch(error => {
// code enters catch case if ever
}}
Lamento decir esto, pero su código parece tener muchos errores de sintaxis. Consulte nuestro proyecto de ejemplo en nuestro repositorio y compare primero con su código.
@dooboolab
Gracias por la respuesta, el código que se publica aquí es solo un ejemplo, este no es el exacto que se está utilizando en la aplicación real.
Intentaré explicar cuál es el problema.
RNIap.initConnection();
RNIap.getProducts(product)
cuando el usuario hace clic en el botón de compra
RNIap.clearTransaction();
se llama solo para asegurarse de que no queden transacciones pendientes.RNIap.buyProductWithoutFinishTransaction(sku)
se llama en caso de éxito se activa una llamada al servidor de aplicaciones si el servidor da el caso de éxito verdadero, entonces se llama a RNIap.finishTransaction();
para completar el pago.componenteWillUnmount ()
RNIap.endConnection()
para finalizar la conexión.Este proceso funciona bien si el usuario ya ha agregado un método de pago. Cuando el usuario no tiene un método de pago agregado, debe agregar la página del método de pago y el monto se carga antes de llegar a RNIap.finishTransaction();
Gracias por el detalle. Tu problema parece claro ahora. cc @JJMoon
@JJMoon
@ zohaibahmed-22 ¿Es este caso de prueba de caja de arena?
@JJMoon No, es un caso de entorno real.
Entiendo que este error ocurre cuando el usuario está desconectado o no tiene información de tarjeta de crédito.
Si los métodos funcionan bien, la causa de este error se encuentra en otra parte.
Necesitamos preparar esta acción, que deja la aplicación, viewDidDisappear, etc.
En el modo sandbox, este síntoma ocurre de una manera algo diferente.
Cuando hago una nueva cuenta de sandbox y la primera compra no funciona.
En la segunda vez, el dispositivo se registra en el estado y funciona bien.
No tengo ni idea de este error.
@dooboolab @JJMoon echa un vistazo a este
https://forums.developer.apple.com/thread/6431
https://forums.developer.apple.com/thread/64489
@dooboolab y @JJMoon también creo que encontré el problema al updatedTransactions , cuando recibimos un mensaje de error en SKPaymentTransactionStateDeferred
o SKPaymentTransactionStateFailed
, no se supone que finishTransaction
.
Dado que en muchos casos el resultado SKPaymentTransactionStateFailed
es seguido por un SKPaymentTransactionStatePurchased
como se menciona en el hilo anterior 6431 . No estoy seguro sobre el código Objective-C, así que verifique y confirme si borramos la transacción en caso de falla.
@anandwahed Estoy de acuerdo contigo. Que es mi culpa. Lo siento por eso.
Revisaré el hilo de Apple y me ocuparé del problema.
@anandwahed Supongo que es la forma correcta de finish transaction
cuando falla. Busque este hilo. https://stackoverflow.com/questions/11008636/inapp-purchase-skpaymentqueue-finish-transaction-doesnt-work
Cuando falla, no habrá recibo, por lo que no aplica el producto de compra. Y la transacción final no siempre significa "compra".
Mientras tanto, investigaré el hilo 6431.
Acabo de leer el hilo 6431 (https://forums.developer.apple.com/thread/6431#14562)
La línea de fondo. Problema no resuelto desde 2015. Vaya ...
Hay dos formas diferentes de manejar este efecto de "flujo del kit de almacenamiento".
Y aprendí dos cosas.
A. Tenemos que finishTransaction
cuando falló. (Supongo con o sin opción, siempre)
B. El flujo de Storekit hace que la recepción sea exitosa y fallida. (es malo)
Les sugiero a todos que lean este hilo y vuelvan a este tema.
Supongo que la forma que elijas (1 o 2) es por tu cuenta.
Es posible que necesitemos una llamada de regreso para una respuesta de falla.
@JJMoon ¿significa que no deberíamos usar buyProductWithoutFinishTransaction?
@ maxs15 No
El flujo de StoreKit puede ocurrir en cualquier compra. Es un problema de iOS, no este módulo.
Por ahora, tampoco tengo ni idea. Esto sucede en cualquier aplicación nativa de iOS. ¿Correcto?
Cavaremos más en nuestro tiempo libre.
Hoy he intentado depurar este problema porque he generado este problema. El pago finishTransanction
y se completa pero no recibe el callback
cuando payMethod ha cambiado. Intenté depurar escribiendo algo de console.log
pero no pude probar la facturación real en el entorno dev
. ¿Alguien podría sugerirme cómo depurar este proceso para que pueda debug
esto por real purchase
? ¿Debería tener que usar esto en el modo sandbox
? Funciona perfectamente en sandbox, así que no tengo idea de cómo depurarlo. Esto es muy reacio.
Recopilemos algunas ideas porque creo que es muy importante arreglarlo.
Siempre recibo este error cuando intento realizar la compra con un usuario que no es sandbox.
@hyochan Si conecta el servidor real (el suyo), no importa si está en modo de depuración o en modo de liberación. Supongo que tienes 2 opciones.
@JJMoon Sí, ya me di cuenta de eso, pero aún así no pude hacer pruebas de compra en vivo en iOS. ¿Es cierto este desbordamiento de pila ? Entonces, ¿cómo puedo solucionar este problema? Tenemos que probar la compra en vivo.
Cualquiera que esté enfrentando este problema, estoy seguro de que todos lo hacen, por favor dénos una idea de cómo encontrar este problema. in-app purchase fail when payment method added live
como se describe en el título del problema. ¿Cómo podría depurar esto? @anandwahed ¿Alguna vez se
@hyochan No, no nos contactamos con el soporte de Apple.
Creo que debemos ponernos en contacto con apple
para esto y parece realmente terrible que haya un caso de prueba diferente que no es reproducible en el entorno sandbox
. Para aquellos que quieran entender el problema, he grabado la pantalla y pueden ver el clip aquí . @anandwahed ¿Podrías también ponerte en contacto con Apple para esto? Porque sé que no son tan solidarios, así que es mejor que más personas tengan contacto con ellos. Reunámonos para resolver este problema.
Hoy recibimos respuesta de Apple. Es posible que se devuelva la devolución de llamada después de failure
. Estamos trabajando en una solución alternativa en el n. ° 348, pero me temo que esto podría ser muy desagradable.
Lancé a 2.4.0-beta1
, tratando de encontrar una solución para este problema. El PR
# 348 se ha agregado a esta versión y también puede ver el archivo Léame de esta función . Tenga en cuenta que esto está bajo prueba.
Probé esto en una compra en vivo y parece estar funcionando. Sin embargo, tenga en cuenta que solo debe agregar un oyente cuando haya una falla o puede duplicarse con un resultado exitoso.
¡Muchachos, gracias por invertir tiempo en este problema! 🙏
Creo que la documentación actual debe ser más clara sobre el uso de addAdditionalSuccessPurchaseListenerIOS
. Eso es algo que traté de abordar en el # 414.
Pero también creo que esto deja margen para la mejora de la API. ¿Estarían abiertos a discutir un cambio en la API que pueda adaptarse mejor al llamado 'flujo de kit de tienda'? Algo tal vez usando RxJS, por ejemplo:
const observable = RNIap.buyProduct('com.example.coins100')
.subscribe(
purchase => console.log(purchase), // successful payment
err => console.log(err) // err.code and err.message are available
)
¿O algo diferente que esconda mejor la suscripción adicional para iOS?
@Edgpaez Eso es genial, pero eso cambiará el comportamiento de la compra que se realiza en android
. Espero poder investigar version 3
de este módulo en 2019
.
hola @hyochan , AFAICT, no necesitamos cambiar el comportamiento interno del paquete, solo la interfaz pública. Podemos mantener el método buyItemByType resolviendo las promesas y simplemente agregar un poco de Rx además de eso en index.js .
por ejemplo, tendríamos esto en index.js:
export const buyProduct = (sku) => Platform.select({
android: () => Observable.of(RNIapModule.buyItemByType(ANDROID_ITEM_TYPE_IAP, sku, null, 0)), // returns an observable that emits when the RNIapModule.buyItemByType promise resolves
ios: ... // ios would do the same but taking into account the usage of addAdditionalSuccessPurchaseListenerIOS
})();
Mi objetivo no es esta implementación específica, sino ocultar detalles específicos del 'flujo del kit de tienda'.
¿Crees que es buena idea?
¿Estaría interesado en un PR?
@Edgpaez Ok. Ahora entiendo el detalle. Sin embargo, creo que agregar RxJS
es demasiado para implementar feature
ya que creo que esto se puede cubrir sin él.
Además, creo que lo siguiente sería algo diferente.
RNIap.buyProduct('com.example.coins100')
.subscribe(
purchase => console.log(purchase), // successful payment
err => console.log(err) // err.code and err.message are available
)
Si llama a buyProduct
por dos elementos como los siguientes,
RNIap.buyProduct('com.example.coins100');
RNIap.buyProduct('com.example.coins200');
No podemos garantizar cuál terminaría primero, así que creo que deberíamos manejar esto de forma nativa a sendEvent
hasta JS
.
Siento que la implementación debería verse así
RNIap.buyProduct('com.example.coins100');
RNIap.buyProduct('com.example.coins200');
// receiving events
const subs = RNIap.purchaseUpdateListener(purchase => {
...
});
Dime si hay algo que me haya perdido.
Manejemos más disccustin en # 423
Comentario más útil
Creo que debemos ponernos en contacto con
apple
para esto y parece realmente terrible que haya un caso de prueba diferente que no es reproducible en el entornosandbox
. Para aquellos que quieran entender el problema, he grabado la pantalla y pueden ver el clip aquí . @anandwahed ¿Podrías también ponerte en contacto con Apple para esto? Porque sé que no son tan solidarios, así que es mejor que más personas tengan contacto con ellos. Reunámonos para resolver este problema.