React-native-iap: buySubscription retorna E_UNKNOWN apesar da compra bem-sucedida

Criado em 13 out. 2018  ·  30Comentários  ·  Fonte: dooboolab/react-native-iap

Versão do react-native-iap

2.2.2 (porque qualquer versão mais recente falha no iOS devido a # 279)

Plataformas em que você enfrentou o erro (IOS ou Android ou ambos?)

iOS

Comportamento esperado

Nenhum erro deve ser lançado. A compra foi bem-sucedida (ao vivo e em produção)

Comportamento real

E_UNKNOWN erro é retornado da promessa
Nosso rastreamento de erros Sentry.io relata o seguinte:

{"framesToPop":1,"code":"E_UNKNOWN","nativeStackIOS":["0   LuCoaching                          0x000000010062f6fc LuCoaching + 1996540","1   LuCoaching                          0x000000010060aa98 LuCoaching + 1845912","2   LuCoaching                          0x00000001007cad98 __cxa_throw + 438380","3   LuCoaching                          0x00000001007cc62c __cxa_throw + 444672","4   libdispatch.dylib                   0x000000019d078484 <redacted> + 16","5   libdispatch.dylib                   0x000000019d025610 <redacted> + 56","6   LuCoaching                          0x00000001007cc46c __cxa_throw + 444224","7   libdispatch.dylib                   0x000000019d0776c8 <redacted> + 24","8   libdispatch.dylib                   0x000000019d078484 <redacted> + 16","9   libdispatch.dylib                   0x000000019d0249ec <redacted> + 1068","10  CoreFoundation                      0x000000019d5ce1bc <redacted> + 12","11  CoreFoundation                      0x000000019d5c9084 <redacted> + 1964","12  CoreFoundation                      0x000000019d5c85b8 CFRunLoopRunSpecific + 436","13  GraphicsServices                    0x000000019f83c584 GSEventRunModal + 100","14  UIKitCore                           0x00000001ca444bc8 UIApplicationMain + 212","15  LuCoaching                          0x000000010044d110 LuCoaching + 20752","16  libdyld.dylib                       0x000000019d088b94 <redacted> + 4"],"userInfo":{"NSLocalizedDescription":"Verbindung mit iTunes Store nicht möglich"},"domain":"SKErrorDomain","line":26,"column":1877,"sourceURL":"/var/containers/Bundle/Application/818C8439-E250-42E8-AD57-EC4FB5FE5547/LuCoaching.app/main.jsbundle"}

Ambiente testado (emulador? Dispositivo real?)

Dispositivo real. Clientes ao vivo. Falha muito consistente

Passos para reproduzir o comportamento

Ao testar o procedimento com usuários do Sandbox, o erro não pode ser reproduzido.

🐛 bug 📱 iOS

Comentários muito úteis

: +1: Estamos enfrentando esse problema. Parece estar acontecendo com cerca de 10% dos nossos usuários atualmente. Vamos tentar adicionar esse ouvinte, mas não acho que, no final das contas, essa seja uma boa solução. @hyochan Existe alguma maneira de obter informações mais detalhadas nos casos em que isso acarreta, ou é uma resposta padrão das APIs StoreKit? Em todos os casos de erro, a mensagem parece ser "Não é possível conectar à iTunes Store", mesmo quando a compra é bem-sucedida.

Todos 30 comentários

@ Gaia-Nutrition Você verificaria este problema antigo? Pode ser a mesma causa.
https://github.com/dooboolab/react-native-iap/issues/201

@JJMoon em # 201, o erro era E_DEVELOPER_ERROR e foi causado por não preencher a lista validProducts usando getSubscriptions() .
No entanto, estou chamando a função antes de tentar realizar a verificação e também recebo um erro diferente.
Mas agora que penso nisso. Pode ocorrer que haja um certo atraso entre a chamada getSubscriptions() e buySubscription() causada pelo usuário reconsiderando se deseja realizar a compra. Isso poderia ser um problema? O aplicativo pode ter sido colocado em segundo plano nesse meio tempo.
EDIT: Mas, novamente, a compra é executada com sucesso, então o problema deve ser onde a resposta da app store está sendo processada

Olá,

Mesmo comportamento de problema com "buyProductWithoutFinishTransaction" ou "buyProduct".

Versão 2.2.1

o retorno armazenado é
{ "framesToPop": 1, "code": "E_UNKNOWN", "nativeStackIOS": [...], "userInfo": { "NSLocalizedDescription": "Connexion à l’iTunes Store impossible" }, "domain": "SKErrorDomain", "line": 16, "column": 1599, "sourceURL": "..." }

Atualizamos o módulo porque reproduzimos esse bug na produção com versões anteriores.

A parte interessante é que a compra de restauração também falha para meus usuários quando isso acontece. Isso só acontece com cerca de 1% dos nossos usuários iOS.

@fierysolid Mesmo caso, cerca de 5% das compras no iOS falharam. Quando o cliente tenta comprar novamente, ele exibe uma compra de restauração.

Oi pessoal. Espero que esteja corrigido em nossa nova versão hoje, que é 2.3.15 . Tenho notado que usar NSDictionary puramente no iOS não é seguro e pode causar um comportamento inesperado. Corrigi isso e espero que agora funcione bem em todos os dispositivos. Por favor, teste isso.

Abra novamente quando ainda estiver enfrentando o problema.

@dooboolab
Ainda consigo esse problema ao usar buySubscription() com um usuário de teste de sandbox com iPhone 6S.

{"userInfo":{"NSLocalizedDescription":"Cannot connect to iTunes Store"}}

@danrevah Então você experimentou nossa nova versão que é 2.3.15 ? @JJMoon Você pode testar isso mais uma vez?

@dooboolab sim, estou usando essa versão.

@danrevah Por favor, tente 2.3.16 .

@dooboolab funcionou uma vez, mas enquanto eu tentava novamente, continuava recebendo esses erros. (usado v 2.3.17)

@JJMoon Você tem alguma pista sobre isso? ele está usando iPhone6S

Eu reabri o problema. cc @JJMoon

Se mais pessoas votarem nesta questão, nós nos esforçaremos mais para cavar mais fundo.

@danrevah , espero que você consulte este documento.
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html#//apple_ref/doc/uid/TP40008267 -CH7-SW6
Para testar a assinatura no modo sandbox, você precisa recomprar a assinatura depois de algum tempo.
E pode ser necessário cancelá-lo para comprar novamente.
E há algumas reações estranhas do servidor sandbox da Apple, o que torna o teste mais difícil.

Se o caso de @JJMoon for o problema, podemos fechá-lo novamente. Reabra se ainda precisar de ajuda com este. @danrevah

@JJMoon Eu enfrentei o mesmo problema. qualquer solução? buySubscription lança exceção e ainda o pagamento é deduzido. Preciso ter dados de resultados para armazená-los e validá-los.
@hyochans

+1 tenho o mesmo problema

Tente usar addAdditionalSuccessPurchaseListenerIOS em buySubscription também. Este é o mesmo problema que em # 307.

Tente usar addAdditionalSuccessPurchaseListenerIOS em buySubscription também. Este é o mesmo problema que em # 307.

Alguém já está usando na produção?

@hyochan , tentei fazer isso, mas sem sucesso.

if (subscription && subscription.success) {
      this.props.subscribe(subscription.result);
    } else {
      if (Platform.OS === 'ios') {
        const sub = RNIap.addAdditionalSuccessPurchaseListenerIOS(async (purchase) => {
          this.props.subscribe(purchase); // -> This code is never fired
          sub.remove();
        });
      }
    }

@cbfranca Por favor, siga o código atual. Você nem mesmo está usando promises . Você deve ouvir addAdditionalSuccessPurchaseListenerIOS após a rejeição da promessa.

Além disso, você não precisa de Platform.OS === 'ios' extra.

@hyochan
Desculpem minha ignorância, mas acho que não entendi bem. Segui as mesmas bases do exemplo, adequando ao meu cenário. Criei uma abstração que trata dessa promessa usando async / await. Este objeto de assinatura é retornado por minha abstração.

static purchaseSubscription(newSubscriptionID, currentSubscriptionID) {
    if (Platform.OS === 'ios') {
      const purchaseResult = KinvoBilling.purchaseSubscriptionIOS(newSubscriptionID);
      return purchaseResult;
    }

    const purchaseResult = KinvoBilling.purchaseSubscriptionANDROID(newSubscriptionID, currentSubscriptionID);
    return purchaseResult;
  }

  static purchaseSubscriptionANDROID = async (newSubscriptionID, currentSubscriptionID) => {
    const hasCurrentSubscription = currentSubscriptionID !== null;

    if (hasCurrentSubscription) {
      const purchaseResult = KinvoBilling.updateSubscription(newSubscriptionID, currentSubscriptionID);
      return purchaseResult;
    }
    const purchaseResult = KinvoBilling.buySubscription(newSubscriptionID);
    return purchaseResult;
  }

  static purchaseSubscriptionIOS = async (subscriptionID) => {
    await KinvoBilling.getSubscriptions();
    const purchaseResult = await KinvoBilling.buySubscription(subscriptionID);

    return purchaseResult;
}

@cbfranca
`` `
static purchaseSubscriptionIOS = async (subscriptionID) => {
aguarde KinvoBilling.getSubscriptions ();
tentar {
const purchaseResult = await KinvoBilling.buySubscription (subscriptionID);
} catch (errar) {
assinatura const = RNIap.addAdditionalSuccessPurchaseListenerIOS (assíncrono (compra) => {
// dooboolab => verifique a chamada aqui.
this.setState ({recibo: compra.transactionReceipt}, () => this.goToNext ());
assinatura.remove ();
}
}
return purchaseResult;
}
`` ``

Verifique o código acima. Eu acho que você precisa refatorar seu código para ajustar seu ciclo de vida.

@hyochan Não funciona para mim.

Meu cenário de teste é:

  • Compre o plano de assinatura mensal - Ok
  • Atualizar para o plano de assinatura anual - falha e o ouvinte não funciona

Outra dúvida: devo usar finishTransaction () em assinaturas também?

Também estou vendo esse erro. E acho que conheço uma maneira de reproduzi-lo.

Versão do react-native-iap

^ 2.4.1

Versão do react-native

https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz

Plataforma

iOS, ao testar no TestFlight em um dispositivo real.

Observações

Percebi que, quando qualquer função RNIap era chamada em meu aplicativo, o iOS me pedia para inserir uma senha de um usuário anterior do iTunes / App Store (que desde então fiz logout e substituí nas configurações do iOS). Eu li em algum lugar online que este é um problema que persegue os usuários do iPhone de vez em quando: às vezes, um aplicativo é comprado com uma conta do iTunes, então o telefone é trocado para uma nova conta do iTunes, mas o aplicativo continua a pedir a senha do conta do iTunes antiga.

Eu tentei deletar meu aplicativo (e TestFlight) e reinstalar com o novo usuário da App Store, sem sucesso. A única maneira de me livrar desse comportamento era limpar o dispositivo. Depois de fazer isso, não consegui mais reproduzir esse erro.

Comportamento Real

  1. buySubscription ()
  2. Selecione Continuar quando for apresentado o modal iOS "Termos de assinatura"
  3. Selecione OK quando apresentado o modal iOS "Confirmar Assinatura"
  4. Erro gerado por buySubscription ():
{
   code: E_UNKNOWN, 
   column: 1565, 
   domain: NSURLErrorDomain, 
   framesToPop: 1, 
   line: 20, 
   nativeStackIOS: [...],
   sourceURL: ...,
   userInfo: {
      _kCFStreamErrorCodeKey: -4, 
      _kCFStreamErrorDomainKey: 4, 
      NSErrorFailingURLKey: None, 
      NSErrorFailingURLStringKey: https://p100-sandbox.itunes.apple.com/WebObjects/MZFinance.woa/wa/inAppBuy, 
      NSLocalizedDescription: Cannot connect to iTunes Store, 
      NSUnderlyingError: {
         code: "-1005", 
         domain: "kCFErrorDomainCFNetwork", 
         message: "underlying error", 
         nativeStackIOS: [...],
         userInfo:{"NSErrorPeerAddressKey":null,"_kCFStreamErrorCodeKey":-4,"_kCFStreamErrorDomainKey":4}
      }
   }
}

Passos para reproduzir o comportamento

  1. Crie um usuário de teste no App Store Connect
  2. Instale o aplicativo da App Store (ou convide o usuário de teste para TestFlight e instale o TestFlight e depois o aplicativo por meio do TestFlight)
  3. Compre uma assinatura no aplicativo
  4. Deixe a assinatura expirar
  5. Logout iOS Apple ID (Configurações> Apple ID, Sair)
  6. Login novo ID Apple
  7. Compre uma assinatura no aplicativo

Espero que isso ajude alguém!

@hyochan

Depois de tentar muitas coisas ainda estou com o mesmo problema e muito mais. No código abaixo, o RNIap.buySubscription (sku) retorna indefinido. Por favor, alguém resolveu?

`` `
static purchaseSubscriptionIOS = async (subscriptionID) => {
aguarde KinvoBilling.getSubscriptions ();

try {
  const purchaseResult = await RNIap.buySubscription(subscriptionID);
  return createResponse(true, purchaseResult);
} catch (error) {
  const subscription = RNIap.addAdditionalSuccessPurchaseListenerIOS(async (purchase) => {
    // dooboolab => check the call here.
    console.tron.log('--- ERROR ----');
    console.tron.log(error);
    console.tron.log('--- PURCHASE ----');
    console.tron.log(purchase);
    const result = purchase;
    subscription.remove();
    console.tron.log(result);

    if (result) {
      return createResponse(true, result);
    }
    return createResponse(false, result);
  });
}

};
`` `

: +1: Estamos enfrentando esse problema. Parece estar acontecendo com cerca de 10% dos nossos usuários atualmente. Vamos tentar adicionar esse ouvinte, mas não acho que, no final das contas, essa seja uma boa solução. @hyochan Existe alguma maneira de obter informações mais detalhadas nos casos em que isso acarreta, ou é uma resposta padrão das APIs StoreKit? Em todos os casos de erro, a mensagem parece ser "Não é possível conectar à iTunes Store", mesmo quando a compra é bem-sucedida.

Temos um problema muito semelhante com 3.4.6: a primeira tentativa de compra falha com E_UNKOWN , a tentativa é bem-sucedida. No entanto, para nós, isso acontece com buyProduct , não com buySubscription . @hyochan poderia ser a mesma causa raiz?

Olá! Estou tendo o mesmo problema depois de chamar RNIap.requestSubscription (). Obtenho um resultado indefinido, mas o pagamento é bem-sucedido, o cartão de crédito é debitado.

A única maneira desse usuário superar isso é restaurando a compra.

Alguém conseguiu consertar isso? Estou usando a versão 3.5.9

Esta página foi útil?
0 / 5 - 0 avaliações