Compartilhar via


Transações e verificação no Xamarin.iOS

Restaurando transações anteriores

Se o aplicativo der suporte a tipos de produto restauráveis, você deverá incluir alguns elementos de interface do usuário para permitir que os usuários restaurem essas compras. Essa funcionalidade permite que um cliente adicione o produto a dispositivos adicionais ou restaure o produto para o mesmo dispositivo depois de ser apagado limpo ou remover e reinstalar o aplicativo. Os seguintes tipos de produto são restauráveis:

  • Produtos não consumíveis
  • Assinaturas renováveis automáticas
  • Assinaturas gratuitas

O processo de restauração deve atualizar os registros que você mantém no dispositivo para atender aos seus produtos. O cliente pode optar por restaurar a qualquer momento, em qualquer um de seus dispositivos. O processo de restauração envia novamente todas as transações anteriores para esse usuário; em seguida, o código do aplicativo deve determinar qual ação tomar com essas informações (por exemplo, verificar se já há um registro dessa compra no dispositivo e, caso contrário, criar um registro da compra e habilitar o produto para o usuário).

Implementando a restauração

O botão Restaurar da interface do usuário chama o método a seguir, que dispara RestoreCompletedTransactions no SKPaymentQueue.

public void Restore()
{
   // theObserver will be notified of when the restored transactions start arriving <- AppStore
   SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();​​​
}

O StoreKit enviará a solicitação de restauração aos servidores da Apple de forma assíncrona.

Como o é registrado como um observador de transações, ele receberá mensagens quando os CustomPaymentObserver servidores da Apple responderem. A resposta conterá todas as transações que esse usuário já realizou neste aplicativo (em todos os seus dispositivos). O código percorre cada transação, detecta o estado Restaurado e chama o UpdatedTransactions método para processá-lo conforme mostrado abaixo:

// called when the transaction status is updated
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
   foreach (SKPaymentTransaction transaction in transactions)
   {
       switch (transaction.TransactionState)
       {
       case SKPaymentTransactionState.Purchased:
          theManager.CompleteTransaction(transaction);
           break;
       case SKPaymentTransactionState.Failed:
          theManager.FailedTransaction(transaction);
           break;
       case SKPaymentTransactionState.Restored:
           theManager.RestoreTransaction(transaction);
           break;
​default:
           break;
       }
   }
}

Se não houver produtos restauráveis para o usuário, UpdatedTransactions não será chamado.

O código mais simples possível para restaurar uma determinada transação no exemplo faz as mesmas ações de quando uma compra ocorre, exceto que a OriginalTransaction propriedade é usada para acessar a ID do Produto:

public void RestoreTransaction (SKPaymentTransaction transaction)
{
   // Restored Transactions always have an 'original transaction' attached
   var productId = transaction.OriginalTransaction.Payment.ProductIdentifier;
   // Register the purchase, so it is remembered for next time
   PhotoFilterManager.Purchase(productId); // it's as though it was purchased again
   FinishTransaction(transaction, true);
}

Uma implementação mais sofisticada pode marcar outras transaction.OriginalTransaction propriedades, como a data original e o número de recibo. Essas informações serão úteis para alguns tipos de produto (como assinaturas).

Conclusão da restauração

O CustomPaymentObserver tem dois métodos adicionais que serão chamados pelo StoreKit quando o processo de restauração for concluído (com êxito ou com uma falha), mostrados abaixo:

public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
   Console.WriteLine(" ** RESTORE Finished ");
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
   Console.WriteLine(" ** RESTORE FailedWithError " + error.LocalizedDescription);
}

No exemplo, esses métodos não fazem nada, no entanto, um aplicativo real pode optar por implementar uma mensagem para o usuário ou alguma outra funcionalidade.

Proteção de compras

Os dois exemplos neste documento usam NSUserDefaults para acompanhar as compras:

Consumíveis – o 'saldo' das compras de crédito é um valor inteiro simples NSUserDefaults que é incrementado a cada compra.

Não Consumíveis – cada compra de filtro de foto é armazenada como um par chave-valor no NSUserDefaults.

Usar NSUserDefaults mantém o código de exemplo simples, mas não oferece uma solução muito segura, pois pode ser possível que os usuários tecnicamente conscientes atualizem as configurações (ignorando o mecanismo de pagamento).

Observação: os aplicativos do mundo real devem adotar um mecanismo seguro para armazenar conteúdo comprado que não esteja sujeito a violação de usuário. Isso pode envolver criptografia e/ou outras técnicas, incluindo a autenticação de servidor remoto.

O mecanismo também deve ser projetado para aproveitar os recursos internos de backup e recuperação do iOS, iTunes e iCloud. Isso garantirá que, depois que um usuário restaurar um backup, suas compras anteriores estarão imediatamente disponíveis.

Consulte o Guia de Codificação Segura da Apple para obter diretrizes mais específicas do iOS.

Verificação de recibo e produtos de Server-Delivered

Os exemplos neste documento até agora consistiam apenas no aplicativo se comunicando diretamente com os servidores App Store para realizar transações de compra, que desbloqueiam recursos ou recursos já codificados no aplicativo.

A Apple fornece um nível adicional de segurança de compra, permitindo que os recibos de compra sejam verificados independentemente por outro servidor, o que pode ser útil para validar uma solicitação antes de fornecer conteúdo digital como parte de uma compra (como um livro digital ou revista).

Produtos Internos – assim como os exemplos neste documento, o produto que está sendo comprado existe como funcionalidade fornecida com o aplicativo. Uma compra no aplicativo permite que o usuário acesse a funcionalidade. As IDs do produto são codificadas.

Produtos entregues pelo servidor – o produto consiste em conteúdo baixável armazenado em um servidor remoto até que uma transação bem-sucedida faça com que o conteúdo seja baixado. Exemplos podem incluir livros ou edições de revistas. As IDs do produto geralmente são originadas de um servidor externo (em que o conteúdo do produto também está hospedado). Os aplicativos devem implementar uma maneira robusta de gravação quando uma transação for concluída, para que, se o download de conteúdo falhar, ele possa ser tentado novamente sem confundir o usuário.

Produtos Server-Delivered

Alguns conteúdos do produto, como livros e revistas (ou até mesmo um nível de jogo) precisam ser baixados de um servidor remoto durante o processo de compra. Isso significa que um servidor adicional é necessário para armazenar e entregar o conteúdo do produto depois que ele é comprado.

Obtendo preços para produtos Server-Delivered

Como os produtos são entregues remotamente, também é possível adicionar mais produtos ao longo do tempo (sem atualizar o código do aplicativo), como adicionar mais livros ou novas edições de uma revista. Para que o aplicativo possa descobrir esses produtos de notícias e exibi-los ao usuário, o servidor adicional deve armazenar e entregar essas informações.

Obtendo preços para produtos Server-Delivered

  1. As informações do produto devem ser armazenadas em vários locais: no servidor e no iTunes Connect. Além disso, cada produto terá arquivos de conteúdo associados a ele. Esses arquivos serão entregues após uma compra bem-sucedida.

  2. Quando o usuário deseja comprar um produto, o aplicativo deve determinar quais produtos estão disponíveis. Essas informações podem ser armazenadas em cache, mas devem ser entregues de um servidor remoto em que a lista master de produtos é armazenada.

  3. O servidor retorna uma lista de IDs do produto para o aplicativo analisar.

  4. Em seguida, o aplicativo determina quais dessas IDs de produto enviar ao StoreKit para recuperar preços e descrições.

  5. O StoreKit envia a lista de IDs de produto para os servidores da Apple.

  6. Os servidores do iTunes respondem com informações válidas do produto (descrição e preço atual).

  7. O do aplicativo é passado as informações do SKProductsRequestDelegate produto para exibição para o usuário.

Compra de produtos de Server-Delivered

Como o servidor remoto requer alguma maneira de validar se uma solicitação de conteúdo é válida (ou seja, foi paga), as informações de recibo são passadas para autenticação. O servidor remoto encaminha esses dados para o iTunes para verificação e, se bem-sucedido, inclui o conteúdo do produto na resposta ao aplicativo.

Compra de produtos de Server-Delivered

  1. O aplicativo adiciona um SKPayment à fila. Se necessário, o usuário será solicitado a fornecer sua ID da Apple e solicitado a confirmar o pagamento.

  2. O StoreKit envia a solicitação ao servidor para processamento.

  3. Quando a transação é concluída, o servidor responde com um recibo de transação.

  4. A SKPaymentTransactionObserver subclasse recebe o recibo e o processa. Como o produto deve ser baixado de um servidor, o aplicativo inicia uma solicitação de rede para o servidor remoto.

  5. A solicitação de download é acompanhada pelos dados de recibo para que o servidor remoto possa verificar se está autorizado a acessar o conteúdo. O cliente de rede do aplicativo aguarda uma resposta a essa solicitação.

  6. Quando o servidor recebe uma solicitação de conteúdo, ele analisa os dados de recibo e envia uma solicitação diretamente aos servidores do iTunes para verificar se o recibo é para uma transação válida. O servidor deve usar alguma lógica para determinar se deseja enviar a solicitação para a URL de produção ou área restrita. A Apple sugere sempre usar a URL de produção e alternar para a área restrita se seu recebimento status 21007 (recibo de área restrita enviado ao servidor de produção). Consulte o Guia de Programação de Validação de Recibo da Apple para obter mais detalhes.

  7. O iTunes marcar o recibo e retornará um status de zero se for válido.

  8. O servidor aguarda a resposta do iTunes. Se ele receber uma resposta válida, o código deverá localizar o arquivo de conteúdo do produto associado a ser incluído na resposta ao aplicativo.

  9. O aplicativo recebe e analisa a resposta, salvando o conteúdo do produto no sistema de arquivos do dispositivo.

  10. O aplicativo habilita o produto e, em seguida, chama StoreKit de FinishTransaction. O aplicativo pode, opcionalmente, exibir o conteúdo comprado (por exemplo, mostrar a primeira página de um livro comprado ou edição de revista).

Uma implementação alternativa para arquivos de conteúdo de produto muito grandes pode envolver simplesmente armazenar o recibo da transação na etapa 9 para que a transação possa ser concluída rapidamente e fornecer uma interface do usuário para que o usuário baixe o conteúdo real do produto em algum momento posterior. A solicitação de download subsequente pode enviar novamente o recibo armazenado para acessar o arquivo de conteúdo do produto necessário.

Escrevendo Server-Side código de verificação de recibo

A validação de um recibo no código do lado do servidor pode ser feita com uma solicitação/resposta HTTP POST simples que abrange as etapas de 5 a 8 no diagrama de fluxo de trabalho.

Extraia a SKPaymentTansaction.TransactionReceipt propriedade no aplicativo. Esses são os dados que precisam ser enviados ao iTunes para verificação (etapa nº 5).

Codificar base64 os dados de recibo da transação (na etapa nº 5 ou nº 6).

Crie uma carga JSON simples como esta:

{
   "receipt-data" : "(base-64 encoded receipt here)"
}

HTTP POST o JSON para produção https://buy.itunes.apple.com/verifyReceipt ou https://sandbox.itunes.apple.com/verifyReceipt para teste.

A resposta JSON conterá as seguintes chaves:

{
   "status" : 0,
   "receipt" : { (receipt repeated here) }
}

Uma status de zero indica um recibo válido. Seu servidor pode continuar a atender ao conteúdo do produto comprado. A chave de recibo contém um dicionário JSON com as mesmas propriedades que o SKPaymentTransaction objeto que foi recebido pelo aplicativo, para que o código do servidor possa consultar esse dicionário para recuperar informações como o product_id e a quantidade da compra.

Confira a documentação do Guia de Programação de Validação de Recibo da Apple para obter informações adicionais.