React-native-iap: getAvailablePurchases devuelve una matriz diferente cada vez

Creado en 9 ago. 2019  ·  13Comentarios  ·  Fuente: dooboolab/react-native-iap

Versión de react-native-iap

3.3.9 (pero también experimenta esto en 3.0.0 y antes)

Versión de react-native

0.59.9

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

iOS (no probado en Android)

Comportamiento esperado

Misma matriz cada vez que llamo getAvailablePurchases
La misma longitud de matriz cada vez

Comportamiento real

Matriz diferente cada vez que llamo getAvailablePurchases
Diferente longitud de matriz cada vez que llamo getAvailablePurchases

Entorno probado (¿Emulador? ¿Dispositivo real?)

Dispositivo real

Pasos para reproducir el comportamiento

Creo que esto solo es visible con muchas transacciones, pero no puedo confirmarlo. Mi cuenta Sandbox tiene más de 50 transacciones.

handleOnPressRestore = async () => {
  return this.setState({ isLoadingRestorePurchases: true }, async () => {
    try {

      // Get the previous purchases of the current user
      const purchases = await RNIap.getAvailablePurchases();

      // Get the latest receipt from the purchases to validate
      const { transactionReceipt, productId, transactionDate } = this.getLatestPurchase(purchases);

      console.log(purchases.length, productId, transactionDate);

      // Validate the receipt on our server
      await this.props.validateSubscriptionReceipt(productId, transactionReceipt);

      // The validation result is handled in componentDidUpdate
    } catch (err) {
      throw err;
    } finally {
      this.setState({ isLoadingRestorePurchases: false });
    }
  });
}

getLatestPurchase = (purchases: RNIap.ProductPurchase[]): RNIap.ProductPurchase => {
  // First, sort the array, so the latest purchase is on top
  // https://github.com/dooboolab/react-native-iap/issues/532#issuecomment-503174711
  const sortedPurchases = purchases.sort((a, b) => b.transactionDate - a.transactionDate);

  const purchase = sortedPurchases[0];

  return purchase;
}

Con el código anterior, cuando presiono "Restaurar compra", obtengo registros diferentes cada vez:

Al presionar "Restaurar compra" 6 veces, con una espera entre medias para que aparezcan los resultados:

// purchases.length, productId, transactionDate
9 "com.app.sub" 1565182529000
21 "com.app.sub" 1565181329000
22 "com.app.sub" 1565183001000
42 "com.app.sub" 1565183001000
53 "com.app.sub" 1565182529000
55 "com.app.sub" 1565183001000
15 "com.app.sub" 1565182529000

Esperaría que la matriz sea siempre la misma, ¿verdad? ¿Que esta pasando aqui?

El resultado de getAvailablePurchases() es diferente cada vez que lo ejecuto

📱 iOS 🙏 help wanted 🚶🏻 stale

Comentario más útil

También ejecuté un bucle en todas las transacciones y no pude eliminarlas con finishTransactionIOS. Mis transacciones son suscripciones de renovación automática.

Todos 13 comentarios

También estoy viendo esto. Lo realmente peligroso es que existe la posibilidad de que el recibo válido más reciente no esté en los resultados.

Al mirar el código de este módulo, honestamente parece un problema del lado de Apple, ya que este módulo está pasando por lo que restoreCompletedTransactions() devuelve

Me pregunto si getPurchaseHistory() es una buena alternativa para las suscripciones. Actualmente lo estoy usando como alternativa, ya que me da resultados confiables. No tengo otras compras en mi aplicación, solo suscripciones.

Como se indica en los documentos de iap de este paquete, getAvailablePurchases() está hablando de consumibles. Una suscripción no es un producto "consumible" o "no consumible". Es una "suscripción auto-renovable" ¿Entonces getPurchaseHistory() debería ser suficiente?

Screenshot 2019-08-16 at 18 11 13

Encontré getPurchaseHistory () también proporcionó diferentes longitudes de matriz. Parecía que la frecuencia de las solicitudes lo afectaba. Al final, resultó que esto realmente no nos importaba, una vez que cualquiera de los recibos de transacción se envió para su validación, Apple devolvió todos los recibos en la matriz latest_receipt_info todos modos, que es todo lo que nos importaba.

Tengo el mismo problema (no sé si es un error del modo sandbox). Además, cuando cambio la identificación de Apple dentro de un dispositivo real, se devuelve la compra realizada con otra cuenta.

Ex:
1 - Realicé una compra con la cuenta
2 - Se cambió la identificación de Apple a [email protected]
3 - getAvailablePurchases devuelve el transactionId de la compra realizada con la cuenta [email protected]

Otro problema que encontré es que si restauro el dispositivo (restablecimiento de fábrica) ambos métodos getPurchaseHistory() y getAvailablePurchases dan resultados aleatorios

La respuesta de Apple para restaurar una compra es:

"Users restore transactions to maintain access to content they've already purchased. For example, when they upgrade to a new phone, they don't lose all of the items they purchased on the old phone. Include some mechanism in your app to let the user restore their purchases, such as a Restore Purchases button."

Encontré un tema de los foros de desarrolladores de Apple sobre los resultados variables de restoreCompletedTransactions como lo dijo @ ssg-luke anteriormente.

https://forums.developer.apple.com/thread/115242

Quizás, esto esté relacionado:

Parece que te refieres a un usuario que tiene muchas transacciones para las que la aplicación aún no ha llamado finishTransaction.
https://forums.developer.apple.com/thread/115242#thread -post-355444

He tenido otras cuentas de sandbox en el mismo dispositivo. Entonces, ¿podrían ser las transacciones de diferentes cuentas, en el mismo dispositivo, simplemente desordenadas y no "terminadas" en absoluto?

Sin embargo, ejecuté un bucle en todas las transacciones y llamé finishTransactionIOS en todas ellas. Pero eso no los hizo desaparecer ni dio como resultado una salida confiable de getAvailablePurchases() ... ¿Quizás porque ya estoy en una cuenta de sandbox más nueva y las transacciones son de una cuenta de sandbox más antigua?

También podría explicar lo que experimenta @fcandiani .

Encontré getPurchaseHistory () también proporcionó diferentes longitudes de matriz. Parecía que la frecuencia de las solicitudes lo afectaba. Al final, resultó que esto realmente no nos importaba, una vez que cualquiera de los recibos de transacción se envió para su validación, Apple devolvió todos los recibos en la matriz latest_receipt_info de todos modos, que es todo lo que nos importaba.

Gracias por la info @ ssg-luke, haré lo mismo.

También ejecuté un bucle en todas las transacciones y no pude eliminarlas con finishTransactionIOS. Mis transacciones son suscripciones de renovación automática.

Frente a casi lo mismo. Estaba creando un problema, pero decidí poner aquí toda la información para ayudar a otros a encontrar el problema y la solución.

Versión de react-native-iap

3.5.9

Versión de react-native

0,60,5

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

iOS

  • El mismo código funciona perfectamente en Android, ya en producción.

Comportamiento esperado

El usuario se suscribió una vez , getAvailablePurchases debe devolver solo una compra

Comportamiento real

getAvailablePurchases devuelve más de una compra,

Entorno probado (¿Emulador? ¿Dispositivo real?)

Dispositivo real con nueva cuenta de sandbox.

Pasos para reproducir el comportamiento

  • Cree un usuario de prueba de sandbox en https://appstoreconnect.apple.com/access/testers
  • Construir y ejecutar un proyecto en xcode
  • Llame getAvailablePurchases , no devuelve compras (como se esperaba)
  • Suscríbete a algún producto
  • mi purchaseUpdatedListener se llama, y ​​yo llamo RNIap.finishTransactionIOS(subscription.transactionId); que devuelve solo undefined (como se esperaba, supongo)
  • Llame getAvailablePurchases , devuelve una compra (como se esperaba)
  • Recargar la aplicación
  • Llame getAvailablePurchases , devuelve dos compras , cada una con diferente transactionId :
{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571145019000
   transactionId: "1000000579415509"
   transactionReceipt: "MIIVnQYJKoZIhvcN..."
},
{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571144839000
   transactionId: "1000000579416705"
   transactionReceipt: "MIIVnQYJKoZIhvcN...."
}
  • Vuelve a cargar la aplicación
  • Llame getAvailablePurchases , devuelve tres compras , cada una con transactionId (no es el mismo del resultado anterior):
{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571145739000
   transactionId: "1000000579423546"
   transactionReceipt: "MIIb1AYJKoZIhvcN..."
},{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571145019000
   transactionId: "1000000579426352"
   transactionReceipt: "MIIb1AYJKoZI..."
},{
   originalTransactionDateIOS: 1571144840000
   originalTransactionIdentifierIOS: "1000000579413333"
   productId: "io.appmasters.lowcarb.development"
   transactionDate: 1571144839000
   transactionId: "1000000579426353"
   transactionReceipt: "MIIb1AYJKoZIhvcN..."
}
  • Vuelve a cargar la aplicación
  • Llame getAvailablePurchases , devuelve cuatro compras , cada una con transactionId (no es el mismo del resultado anterior) ...

Este no parece ser el comportamiento correcto, por lo que leo en los documentos y por lo que sucede en Android.

Agradezco cualquier ayuda.

getAvaialblePurchases () devuelve más de 150 resultados en mi cuenta de prueba de la zona de pruebas. He decidido no usar getAvailablePurchases () en absoluto y simplemente almacenar la última compra en el dispositivo y también en el servidor. Si la aplicación se elimina o el usuario se traslada a un nuevo teléfono, aún tendremos la última compra en nuestro servidor vinculada a la plataforma e identificación de usuario de nuestra empresa (iOS o Android). Llamar a getAvailablePurchases () tarda cerca de un minuto y, a veces, llamar a este oyente actualizado de compra desencadenante que intenta restaurar varias compras. Hemos modificado nuestro flujo así:
1) Cuando el usuario inicia sesión en el dispositivo:
a) ver si existe una última compra válida en nuestro servidor para el usuario y la plataforma.
b) Si no hay registro en el servidor, vea si hay una compra local guardada en DB
c) Si no hay ninguno o ha caducado, muestra la vista de suscripciones.
Inicialmente llamábamos a getAvailablePurchases () e intentábamos ver si la última compra seguía siendo válida. No estoy seguro de si esto ayuda a otros, pero ya no tenemos problemas con esto. Estamos en Reaccionar 59 y ese es otro dolor con el que tenemos que lidiar.

@ramakula y ¿y si el usuario cancela su suscripción?

Como dijiste, mantendrás la suscripción en tu base de datos hasta la fecha de finalización y "verás" que ya no está disponible para comprar.

Hola, parece que no ha habido actividad sobre este tema recientemente. ¿Se ha solucionado el problema o aún requiere la atención de la comunidad? Este problema puede cerrarse si no se produce más actividad. También puede etiquetar este problema como "Para discusión" o "Buen primer número" y lo dejaré abierto. Gracias por sus aportaciones.

Cerrando este problema después de un período prolongado de inactividad. Si este problema todavía está presente en la última versión, no dude en crear un nuevo problema con información actualizada.

getAvaialblePurchases () devuelve más de 150 resultados en mi cuenta de prueba de la zona de pruebas. He decidido no usar getAvailablePurchases () en absoluto y simplemente almacenar la última compra en el dispositivo y también en el servidor. Si la aplicación se elimina o el usuario se traslada a un nuevo teléfono, aún tendremos la última compra en nuestro servidor vinculada a la plataforma e identificación de usuario de nuestra empresa (iOS o Android). Llamar a getAvailablePurchases () tarda cerca de un minuto y, a veces, llamar a este oyente actualizado de compra desencadenante que intenta restaurar varias compras. Hemos modificado nuestro flujo así:

  1. Cuando el usuario inicia sesión en el dispositivo:
    a) ver si existe una última compra válida en nuestro servidor para el usuario y la plataforma.
    b) Si no hay registro en el servidor, vea si hay una compra local guardada en DB
    c) Si no hay ninguno o ha caducado, muestra la vista de suscripciones.
    Inicialmente llamábamos a getAvailablePurchases () e intentábamos ver si la última compra seguía siendo válida. No estoy seguro de si esto ayuda a otros, pero ya no tenemos problemas con esto. Estamos en Reaccionar 59 y ese es otro dolor con el que tenemos que lidiar.

Creo que podemos obtener las últimas compras del recibo. Verificando la recepción de un usuario, con exclude-old-transaction: true podemos obtener la información de suscripción más reciente (solo para el tipo de renovación automática). Creo que podemos usar este método para restaurar las compras de suscripción renovable automáticamente. Sin embargo, no estoy seguro de si este es un método ideal.

¿Fue útil esta página
0 / 5 - 0 calificaciones