3.3.9 (mas também experimenta isso no 3.0.0 e antes)
0,59,9
iOS (não testado no Android)
Mesma matriz sempre que chamo getAvailablePurchases
Mesmo comprimento de array sempre
Array diferente sempre que chamo getAvailablePurchases
Comprimento diferente da matriz sempre que chamo getAvailablePurchases
Dispositivo real
Acho que isso só é visível com muitas transações, mas não posso confirmar isso. Minha conta Sandbox tem mais de 50 transações.
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;
}
Com o código acima, quando pressiono "Restaurar compra", obtenho registros diferentes a cada vez:
Pressionando "Restaurar compra" 6 vezes, com uma espera entre para deixar os resultados chegarem:
// 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
Eu esperaria que a matriz fosse sempre a mesma, certo? O que está acontecendo aqui?
O resultado de getAvailablePurchases()
é diferente a cada vez que eu o executo
Eu também estou vendo isso. O que é realmente perigoso é que existe a possibilidade de o recibo válido mais recente não constar dos resultados.
Olhando para o código deste módulo, honestamente parece um problema do lado da Apple, já que este módulo está efetivamente apenas passando por qualquer coisa que restoreCompletedTransactions()
devolve
Eu me pergunto se getPurchaseHistory()
é uma boa alternativa para ser usado para assinaturas. Atualmente estou usando isso como alternativa, pois me dá resultados confiáveis. Não tenho nenhuma outra compra em meu aplicativo, apenas assinaturas.
Conforme declarado nos documentos iap deste pacote, getAvailablePurchases()
está falando sobre consumíveis. Uma assinatura não é um produto "consumível" ou "não consumível". É uma "assinatura auto-renovável" Então getPurchaseHistory()
deve servir?
Descobri que getPurchaseHistory () forneceu vários comprimentos de array também. Parecia que a frequência de pedidos efetuava isso. No final, descobrimos que isso não importava muito para nós, uma vez que qualquer um dos recibos da transação foi enviado para validação, todos os recibos foram devolvidos pela Apple no array latest_receipt_info
qualquer maneira, o que é tudo o que importa para nós.
Estou tendo o mesmo problema (não sei se é um erro do modo sandbox). Além disso, quando eu mudo o ID da apple em um dispositivo real, a compra feita com outra conta é devolvida.
Ex:
1 - Fiz uma compra com a conta [email protected]
2 - ID da apple alterado para
3 - getAvailablePurchases retorna o transactionId da compra feita com a conta [email protected]
Outro problema que descobri é que se eu restaurar o dispositivo (redefinição de fábrica), os dois métodos getPurchaseHistory()
e getAvailablePurchases
fornecem resultados aleatórios
A resposta da Apple para restaurar uma compra é:
"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."
Encontrado um tópico dos Fóruns de Desenvolvedores da Apple sobre os resultados variáveis de restoreCompletedTransactions
conforme dito por @ ssg-luke anteriormente.
https://forums.developer.apple.com/thread/115242
Talvez, isso esteja relacionado:
Parece que você está se referindo a um usuário com muitas transações para as quais o aplicativo ainda não chamou o finishTransaction.
https://forums.developer.apple.com/thread/115242#thread -post-355444
Tive outras contas de sandbox no mesmo dispositivo. Então, poderiam ser as transações de contas diferentes, no mesmo dispositivo, apenas bagunçadas e não "finalizadas"?
No entanto, executei um loop em todas as transações e chamei finishTransactionIOS
em todas elas. Mas isso não os fez desaparecer ou resultou em uma saída confiável de getAvailablePurchases()
... Talvez porque eu já esteja em uma conta de sandbox mais recente e as transações sejam de uma conta de sandbox mais antiga?
Também poderia explicar o que o @fcandiani experimenta.
Descobri que getPurchaseHistory () forneceu vários comprimentos de array também. Parecia que a frequência de pedidos efetuava isso. No final, descobrimos que isso realmente não importava para nós, uma vez que qualquer um dos recibos da transação foi enviado para validação, todos os recibos foram devolvidos pela Apple no array latest_receipt_info de qualquer maneira que é tudo o que importou para nós.
Obrigado pela informação @ ssg-luke, vou fazer o mesmo.
Também executei um loop em todas as transações e não fui capaz de removê-las com o finishTransactionIOS. Minhas transações são assinaturas de renovação automática.
Enfrentando quase o mesmo. Estava criando um problema, mas resolvi colocar aqui todas as informações para ajudar outras pessoas a encontrar o problema e a solução.
3.5.9
0,60,5
iOS
Usuário inscrito uma vez , getAvailablePurchases
deve devolver apenas uma compra
getAvailablePurchases
está devolvendo mais de uma compra,
Dispositivo real com nova conta sandbox.
getAvailablePurchases
, não retorna nenhuma compra (como esperado)purchaseUpdatedListener
é chamado, e eu chamo RNIap.finishTransactionIOS(subscription.transactionId);
que retorna apenas undefined
(como esperado, eu acho)getAvailablePurchases
, retorna uma compra (como esperado)getAvailablePurchases
, retorna duas compras , cada uma com 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...."
}
getAvailablePurchases
, retorna três compras , cada uma com transactionId
(diferente do 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..."
}
getAvailablePurchases
, retorna quatro compras , cada uma com transactionId
(diferente do resultado anterior) ...Este não parece ser o comportamento correto, pelo que li na documentação e pelo que acontece no Android.
Agradeço qualquer ajuda.
getAvaialblePurchases () está retornando mais de 150 resultados em minha conta de teste do sandbox. Decidi não usar getAvailablePurchases () e apenas armazenar a última compra no dispositivo e também no servidor. Se o aplicativo for excluído ou o usuário for movido para um novo telefone, ainda teremos a última compra em nosso servidor vinculada ao ID de usuário e plataforma de nossa empresa (iOS ou Android). Chamar getAvailablePurchases () leva quase um minuto e, às vezes, chamando esse listener atualizado de compra acionadora tentando restaurar várias compras. Modificamos nosso fluxo assim:
1) Quando o usuário faz login no dispositivo:
a) veja se existe uma última compra válida em nosso servidor para o usuário e plataforma.
b) Caso não haja registro no servidor, verifique se existe alguma compra local salva no DB
c) Se não houver nenhuma ou se houver uma expirada, mostre a exibição de assinaturas.
Inicialmente, estávamos chamando getAvailablePurchases () e tentando ver se a última compra ainda era válida. Não tenho certeza se isso ajuda outras pessoas, mas não estamos mais tendo problemas com isso. Estamos reagindo 59 e essa é outra dor com a qual temos que lidar.
@ramakula e se o usuário cancelar sua assinatura?
Da forma como você disse, você manterá a assinatura em seu banco de dados até a data de término, e "verá" que não está mais disponível para compra.
Olá, parece que não houve nenhuma atividade sobre este problema recentemente. O problema foi corrigido ou ainda requer a atenção da comunidade? Este problema pode ser resolvido se nenhuma outra atividade ocorrer. Você também pode rotular esse problema como "Para discussão" ou "Bom primeiro problema" e eu o deixarei em aberto. Obrigado por suas contribuições.
Encerrando este problema após um período prolongado de inatividade. Se esse problema ainda estiver presente na versão mais recente, sinta-se à vontade para criar um novo problema com informações atualizadas.
getAvaialblePurchases () está retornando mais de 150 resultados em minha conta de teste do sandbox. Decidi não usar getAvailablePurchases () e apenas armazenar a última compra no dispositivo e também no servidor. Se o aplicativo for excluído ou o usuário for movido para um novo telefone, ainda teremos a última compra em nosso servidor vinculada ao ID de usuário e plataforma de nossa empresa (iOS ou Android). Chamar getAvailablePurchases () leva quase um minuto e, às vezes, chamando esse listener atualizado de compra acionadora tentando restaurar várias compras. Modificamos nosso fluxo assim:
- Quando o usuário faz login no dispositivo:
a) veja se existe uma última compra válida em nosso servidor para o usuário e plataforma.
b) Caso não haja registro no servidor, verifique se existe alguma compra local salva no DB
c) Se não houver nenhuma ou se houver uma expirada, mostre a exibição de assinaturas.
Inicialmente, estávamos chamando getAvailablePurchases () e tentando ver se a última compra ainda era válida. Não tenho certeza se isso ajuda outras pessoas, mas não estamos mais tendo problemas com isso. Estamos reagindo 59 e essa é outra dor com a qual temos que lidar.
Acredito que podemos obter as compras mais recentes no recibo. Ao verificar o recebimento de um usuário, com exclude-old-transactions: true, podemos obter as informações de assinatura mais recentes (apenas para tipo auto-renovável). Acredito que podemos usar esse método para restaurar as compras de assinaturas auto-renováveis. Não tenho certeza se este é um método ideal.
Comentários muito úteis
Também executei um loop em todas as transações e não fui capaz de removê-las com o finishTransactionIOS. Minhas transações são assinaturas de renovação automática.