Integrar a Biblioteca Play Faturamento ao seu app

Este tópico descreve como integrar a Biblioteca Play Faturamento ao seu aplicativo para começar a vender produtos.

O ciclo de uma compra

Veja um fluxo de compra típico para uma compra única ou assinatura.

  1. Mostre ao usuário o que ele pode comprar.
  2. Inicie o fluxo de compra para que o usuário a aceite.
  3. Verifique a compra no seu servidor.
  4. Forneça conteúdo ao usuário.
  5. Confirme a entrega do conteúdo. Para produtos de consumo, consuma a compra para que o usuário possa comprar o item de novo.

As assinaturas são renovadas automaticamente até que sejam canceladas. Uma assinatura pode passar pelos seguintes estados:

  • Ativa: o usuário está em situação regular e tem acesso à assinatura.
  • Cancelada: o usuário cancelou, mas ainda tem acesso até o vencimento.
  • Em período de carência: o usuário teve um problema com o pagamento, mas ainda tem acesso enquanto o Google tenta executar a forma de pagamento de novo.
  • Suspensa: o usuário teve um problema com o pagamento e não tem mais acesso enquanto o Google tenta executar a forma de pagamento de novo.
  • Pausada: o usuário pausou e não tem acesso até retomar.
  • Vencida: o usuário cancelou a assinatura e perdeu o acesso. O usuário é considerado desligado na data do vencimento.

Inicializar uma conexão com o Google Play

A primeira etapa para fazer a integração do sistema de faturamento do Google Play é adicionar a Biblioteca Google Play Faturamento ao seu app e inicializar uma conexão.

Adicionar a dependência da Biblioteca Google Play Faturamento

Adicione a dependência da Biblioteca Google Play Faturamento ao arquivo build.gradle do seu app desta forma:

Groovy

dependencies {
    def billing_version = "6.1.0"

    implementation "com.android.billingclient:billing:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "6.1.0"

    implementation("com.android.billingclient:billing:$billing_version")
}

Se você usa o Kotlin, o módulo KTX da Biblioteca Google Play Faturamento oferece suporte a extensões e corrotinas de Kotlin que permitem escrever Kotlin idiomático ao usar a Biblioteca Google Play Faturamento. Para incluir essas extensões no projeto, adicione esta dependência ao arquivo build.gradle do app, como mostrado:

Groovy

dependencies {
    def billing_version = "6.1.0"

    implementation "com.android.billingclient:billing-ktx:$billing_version"
}

Kotlin

dependencies {
    val billing_version = "6.1.0"

    implementation("com.android.billingclient:billing-ktx:$billing_version")
}

Inicializar um BillingClient

Depois de adicionar uma dependência à Biblioteca Google Play Faturamento, você precisa inicializar uma instância de BillingClient, BillingClient é a interface principal de comunicação entre a biblioteca do Google Play Faturamento e o restante do app. O BillingClient fornece métodos de conveniência, síncronos e assíncronos, para muitas operações de faturamento comuns. É altamente recomendável ter uma conexão BillingClient ativa ao mesmo tempo para evitar vários callbacks de PurchasesUpdatedListener para um único evento.

Para criar um BillingClient, use newBuilder(). Você pode transmitir qualquer contexto para o newBuilder(), e ele será usado pelo BillingClient para ter um contexto de aplicativo. Ou seja, você não precisa se preocupar com vazamentos de memória. Para receber atualizações sobre compras, chame também setListener(), transmitindo uma referência para um PurchasesUpdatedListener. Esse listener recebe atualizações para todas as compras no seu app.

Kotlin

private val purchasesUpdatedListener =
   PurchasesUpdatedListener { billingResult, purchases ->
       // To be implemented in a later section.
   }

private var billingClient = BillingClient.newBuilder(context)
   .setListener(purchasesUpdatedListener)
   .enablePendingPurchases()
   .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // To be implemented in a later section.
    }
};

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .build();

Conectar ao Google Play

Depois de criar um BillingClient, você precisa estabelecer uma conexão com o Google Play.

Para se conectar ao Google Play, chame startConnection(). O processo de conexão é assíncrono, e é necessário implementar um BillingClientStateListener para receber um callback assim que a configuração do cliente for concluída e estiver pronta para fazer mais solicitações.

Também é necessário implementar a lógica de nova tentativa para gerenciar as conexões perdidas com o Google Play. Para implementar essa lógica, substitua o método de callback onBillingServiceDisconnected() e confira se o BillingClient chama o método startConnection() para se reconectar ao Google Play antes de fazer outras solicitações.

O exemplo abaixo demonstra como iniciar uma conexão e testar se ela está pronta para uso:

Kotlin

billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    override fun onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
})

Java

billingClient.startConnection(new BillingClientStateListener() {
    @Override
    public void onBillingSetupFinished(BillingResult billingResult) {
        if (billingResult.getResponseCode() ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    @Override
    public void onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
});

Mostrar produtos disponíveis para compra

Depois de estabelecer uma conexão com o Google Play, estará tudo pronto para você consultar seus produtos disponíveis e mostrá-los aos usuários.

Consultar detalhes do produto é uma etapa importante antes de mostrar seus produtos para os usuários, já que retorna informações localizadas do produto. Para assinaturas, verifique se a exibição do produto segue todas as políticas do Google Play.

Para consultar detalhes do produto no app, chame queryProductDetailsAsync().

Para gerenciar o resultado da operação assíncrona, você também precisa especificar um listener que implemente a interface ProductDetailsResponseListener. Em seguida, você pode substituir onProductDetailsResponse(), que notifica o listener quando a consulta é concluída, conforme mostrado neste exemplo:

Kotlin

val queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build()

billingClient.queryProductDetailsAsync(queryProductDetailsParams) {
    billingResult,
    productDetailsList ->
      // check billingResult
      // process returned productDetailsList
}

Java

QueryProductDetailsParams queryProductDetailsParams =
    QueryProductDetailsParams.newBuilder()
        .setProductList(
            ImmutableList.of(
                Product.newBuilder()
                    .setProductId("product_id_example")
                    .setProductType(ProductType.SUBS)
                    .build()))
        .build();

billingClient.queryProductDetailsAsync(
    queryProductDetailsParams,
    new ProductDetailsResponseListener() {
        public void onProductDetailsResponse(BillingResult billingResult,
                List<ProductDetails> productDetailsList) {
            // check billingResult
            // process returned productDetailsList
        }
    }
)

Ao consultar detalhes do produto, transmita uma instância de QueryProductDetailsParams que especifique uma lista de strings de ID do produto criadas no Google Play Console e um ProductType. O ProductType pode ser ProductType.INAPP para produtos únicos ou ProductType.SUBS para assinaturas.

Consultar com extensões do Kotlin

Se você usa as extensões do Kotlin, pode consultar os detalhes do produto no app chamando a função de extensão queryProductDetails().

A função queryProductDetails() usa as corrotinas do Kotlin para que você não precise definir um listener separado. Em vez disso, a função é suspensa até que a consulta seja concluída. Depois, é possível processar o resultado:

suspend fun processPurchases() {
    val productList = ArrayList<String>()
    productList.add(
              QueryProductDetailsParams.Product.newBuilder()
                  .setProductId("product_id_example")
                  .setProductType(BillingClient.ProductType.SUBS)
                  .build()
           )
    val params = QueryProductDetailsParams.newBuilder()
    params.setProductList(productList)

    // leverage queryProductDetails Kotlin extension function
    val productDetailsResult = withContext(Dispatchers.IO) {
        billingClient.queryProductDetails(params.build())
    }

    // Process the result.
}

Em casos raros, alguns dispositivos não oferecem suporte a ProductDetails e queryProductDetailsAsync(). Isso costuma ocorrer devido a versões desatualizadas do Google Play Services. Para garantir o suporte adequado a esse cenário, aprenda a usar os recursos de compatibilidade com versões anteriores no guia de migração da Biblioteca Play Faturamento 5.

Processar o resultado

A Biblioteca Google Play Faturamento armazena os resultados de consulta em uma List de objetos ProductDetails. Depois disso, você pode chamar vários métodos em cada um dos objetos ProductDetails da lista para conferir informações relevantes sobre um produto no aplicativo, como o preço ou a descrição. Para conferir as informações de detalhes do produto disponíveis, consulte a lista de métodos na classe ProductDetails.

Antes de oferecer um item para venda, confira se o usuário ainda não tem o item. Se o usuário tiver um produto de consumo que ainda está na biblioteca de itens, ele precisará consumir o item antes de comprá-lo de novo.

Antes de oferecer uma assinatura, verifique se o usuário ainda não é assinante. Observe também o seguinte:

  • queryProductDetailsAsync() retorna detalhes do produto por assinatura e um máximo de 50 ofertas por assinatura.
  • queryProductDetailsAsync() retorna somente ofertas para as quais o usuário está qualificado. Se o usuário tentar comprar uma oferta para a qual não está qualificado (por exemplo, se o app estiver mostrando uma lista desatualizada de ofertas qualificadas), o Google Play vai avisar sobre a não qualificação e avisar que o usuário pode comprar o plano básico.

Iniciar o fluxo de compra

Para iniciar um pedido de aprovação de compra no seu app, chame o método launchBillingFlow() na linha de execução principal do app. Esse método usa uma referência a um objeto BillingFlowParams que contém o objeto ProductDetails relevante recebido ao chamar queryProductDetailsAsync(). Para criar um objeto BillingFlowParams, use a classe BillingFlowParams.Builder.

Kotlin

// An activity reference from which the billing flow will be launched.
val activity : Activity = ...;

val productDetailsParamsList = listOf(
    BillingFlowParams.ProductDetailsParams.newBuilder()
        // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
        .setProductDetails(productDetails)
        // For One-time product, "setOfferToken" method shouldn't be called.
        // For subscriptions, to get an offer token, call ProductDetails.subscriptionOfferDetails()
        // for a list of offers that are available to the user
        .setOfferToken(selectedOfferToken)
        .build()
)

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build()

// Launch the billing flow
val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

Java

// An activity reference from which the billing flow will be launched.
Activity activity = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
             // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // For one-time products, "setOfferToken" method shouldn't be called.
            // For subscriptions, to get an offer token, call
            // ProductDetails.subscriptionOfferDetails() for a list of offers
            // that are available to the user.
            .setOfferToken(selectedOfferToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

O método launchBillingFlow() retorna um dos vários códigos de resposta listados em BillingClient.BillingResponseCode. Verifique esse resultado para garantir que não houve erros ao iniciar o fluxo de compra. O BillingResponseCode OK indica que o pedido foi bem-sucedido.

Em uma chamada bem-sucedida para launchBillingFlow(), o sistema mostra a tela de compra do Google Play. A Figura 1 mostra uma tela de compra para uma assinatura:

A tela de compra do Google Play mostra uma assinatura
            disponível para compra
Figura 1. A tela de compra do Google Play mostra uma assinatura disponível para compra.

O Google Play chama onPurchasesUpdated() para entregar o resultado da operação de compra a um listener que implementa a interface PurchasesUpdatedListener. O listener é especificado com o método setListener() ao inicializar o cliente.

Implemente onPurchasesUpdated() para gerenciar possíveis códigos de resposta. O exemplo abaixo mostra como substituir onPurchasesUpdated():

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
   if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) {
       for (purchase in purchases) {
           handlePurchase(purchase)
       }
   } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) {
       // Handle an error caused by a user cancelling the purchase flow.
   } else {
       // Handle any other error codes.
   }
}

Java

@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
    if (billingResult.getResponseCode() == BillingResponseCode.OK
        && purchases != null) {
        for (Purchase purchase : purchases) {
            handlePurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {
        // Handle an error caused by a user cancelling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

Compras concluídas geram uma tela de conclusão de compra do Google Play semelhante à Figura 2.

Tela de conclusão de compra do Google Play
Figura 2. Tela de conclusão de compra do Google Play.

Uma compra bem-sucedida também gera um token de compra, que é um identificador exclusivo que representa o usuário e o ID do produto no app comprado. Seus apps podem armazenar o token de compra localmente, embora seja recomendável transmiti-lo para o servidor de back-end seguro, onde você pode verificar a compra e proteger contra fraudes. Esse processo é descrito mais detalhadamente na próxima seção.

O usuário também recebe por e-mail um comprovante da transação, contendo o código do pedido ou um ID exclusivo para a transação. Os usuários recebem um e-mail com um código do pedido exclusivo para cada compra de produto único, assim como para a compra de assinatura inicial e as renovações automáticas seguintes. É possível usar o código do pedido para gerenciar reembolsos no Google Play Console.

Indicar um preço personalizado

Caso seu app possa ser distribuído aos usuários na União Europeia, use o método setIsOfferPersonalized() para divulgar que o preço de um item foi personalizado usando a tomada de decisões automatizada.

A tela de compra do Google Play indica que o preço foi personalizado para o usuário.
Figura 3. A tela de compra do Google Play indica que o preço foi personalizado para o usuário.

Consulte o Art. 6 (1) (ea) CRD da Diretiva de Direitos do Consumidor (2011/83/EU) para determinar se o preço que você está oferecendo aos usuários é personalizado.

setIsOfferPersonalized() recebe uma entrada booleana. Quando é true, a IU do Google Play inclui a declaração. Quando false, a interface omite a declaração. O valor padrão é false.

Consulte a Central de Ajuda do consumidor para mais informações.

Como processar compras

Depois que um usuário conclui uma compra, seu app precisa fazer o processamento. Na maioria dos casos, o app é notificado sobre as compras pelo PurchasesUpdatedListener. No entanto, há casos em que ele é informado sobre as compras chamando BillingClient.queryPurchasesAsync(), conforme descrito em Como buscar compras.

Além disso, se você tiver um cliente de Notificações do desenvolvedor em tempo real no seu back-end seguro, poderá registrar novas compras recebendo uma subscriptionNotification ou uma oneTimeProductNotification (somente para compras pendentes), que vai enviar um alerta sempre que ocorrer uma compra. Depois de receber essas notificações, chame a API Google Play Developer para conferir o status completo e atualizar seu próprio estado de back-end.

Seu app precisa processar uma compra da seguinte maneira:

  1. Verifique a compra.
  2. Forneça conteúdo ao usuário e confirme a entrega do conteúdo. Opcionalmente, marque o item como consumido para que o usuário possa comprá-lo novamente.

Para verificar uma compra, primeiro confira se o estado é PURCHASED (comprado). Se a compra estiver PENDING (pendente), processe conforme descrito em Como processar transações pendentes. Para compras recebidas de onPurchasesUpdated() ou queryPurchasesAsync(), confira a compra para garantir a autenticidade antes que seu app conceda direito de acesso. Para aprender a verificar corretamente uma compra, consulte Verificar compras antes de conceder direito de acesso.

Depois da verificação da compra, seu app vai estar pronto para conceder direito de acesso ao usuário. A conta de usuário associada à compra poderá ser identificada com o ProductPurchase.obfuscatedExternalAccountId retornado por Purchases.products:get para compras de produtos no app e o SubscriptionPurchase.obfuscatedExternalAccountId retornado por Purchases.subscriptions:get para assinaturas do lado do servidor, ou ainda o obfuscatedAccountId de Purchase.getAccountIdentifiers() do lado do cliente, se ela tiver sido definida com setObfuscatedAccountId durante a ação.

Depois de conceder o direito, o app precisa confirmar a compra. Essa confirmação informa ao Google Play que você concedeu direito para a compra.

O processo para conceder o direito e confirmar a ação depende do tipo de compra, ou seja, se é de um produto de consumo, um produto que não é de consumo ou uma assinatura.

Produtos de consumo

No caso de produtos de consumo, se o app tiver um back-end seguro, recomendamos usar Purchases.products:consume para consumir compras de forma confiável. Confira se a compra já não foi consumida verificando o consumptionState do resultado da chamada de Purchases.products:get. Se o app for exclusivo para clientes sem um back-end, use o método consumeAsync() da Biblioteca Google Play Faturamento. Os dois métodos atendem ao requisito de confirmação e indicam que o app concedeu direito de acesso ao usuário. Eles também permitem que o app disponibilize o produto único correspondente ao token de compra de entrada para recompra. Com consumeAsync(), você também precisa transmitir um objeto que implemente a interface ConsumeResponseListener. Esse objeto cuida do resultado da operação de consumo. É possível substituir o método onConsumeResponse(), que a Biblioteca Google Play Faturamento chama quando a operação é concluída.

Confira um exemplo que ilustra o consumo de um produto com a Biblioteca Google Play Faturamento usando o token de compra associado:

Kotlin

suspend fun handlePurchase(purchase: Purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    val purchase : Purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    val consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build()
    val consumeResult = withContext(Dispatchers.IO) {
        client.consumePurchase(consumeParams)
    }
}

Java

void handlePurchase(Purchase purchase) {
    // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener.
    Purchase purchase = ...;

    // Verify the purchase.
    // Ensure entitlement was not already granted for this purchaseToken.
    // Grant entitlement to the user.

    ConsumeParams consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(purchase.getPurchaseToken())
            .build();

    ConsumeResponseListener listener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Handle the success of the consume operation.
            }
        }
    };

    billingClient.consumeAsync(consumeParams, listener);
}

Produtos que não são de consumo

Se o app tiver um back-end seguro, recomendamos usar Purchases.products:acknowledge para confirmar de maneira confiável as compras de produtos que não são de consumo. Confira se a compra não foi confirmada anteriormente verificando o acknowledgementState no resultado da chamada de Purchases.products:get.

Se o app for exclusivo para clientes, use o método BillingClient.acknowledgePurchase() da Biblioteca Google Play Faturamento. Antes de confirmar uma compra, o app precisa conferir se ela já foi confirmada usando o método isAcknowledged() na Biblioteca Google Play Faturamento.

O exemplo abaixo mostra como confirmar uma compra usando a Biblioteca Google Play Faturamento:

Kotlin

val client: BillingClient = ...
val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ...

suspend fun handlePurchase() {
    if (purchase.purchaseState === PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged) {
            val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.purchaseToken)
            val ackPurchaseResult = withContext(Dispatchers.IO) {
               client.acknowledgePurchase(acknowledgePurchaseParams.build())
            }
        }
     }
}

Java

BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
    }
}

Inscrições

As assinaturas são processadas de forma semelhante aos produtos que não são de consumo. Se possível, use Purchases.subscriptions.acknowledge da API Google Play Developer para confirmar de maneira confiável a compra no back-end seguro. Confira se a compra não foi confirmada anteriormente, verificando o acknowledgementState no recurso de compra de Purchases.subscriptions:get. Também é possível confirmar uma assinatura usando BillingClient.acknowledgePurchase() da Biblioteca Google Play Faturamento depois de conferir o isAcknowledged(). Todas as compras de assinatura inicial precisam ser confirmadas. Renovações de assinatura, por outro lado, não precisam passar por essa etapa. Para saber mais sobre quando as assinaturas precisam ser confirmadas, consulte a seção Vender assinaturas.

Como buscar compras

Ouvir atualizações de compra usando um PurchasesUpdatedListener não é suficiente para garantir que seu app processe todas as compras. É possível que seu app não esteja informado de todas as compras que um usuário fez. Confira alguns cenários em que seu app pode perder o controle ou não tomar conhecimento de compras:

  • Problemas de rede durante a compra: um usuário faz uma compra bem-sucedida e recebe a confirmação do Google, mas o dispositivo perde a conexão de rede antes que receba uma notificação da compra pelo PurchasesUpdatedListener.
  • Vários dispositivos: um usuário compra um item em um dispositivo e espera que ele esteja em outros.
  • Processamento de compras feitas fora do app: algumas compras, como resgates de promoções, podem ser feitas fora do app.

Para lidar com essas situações, seu app precisa chamar BillingClient.queryPurchasesAsync() no método onResume() e garantir que todas as compras sejam processadas conforme descrito em Como processar compras.

O exemplo abaixo mostra como buscar as compras de assinatura de um usuário. Observe que queryPurchasesAsync() retorna apenas assinaturas ativas e compras únicas não consumidas.

Kotlin

val params = QueryPurchasesParams.newBuilder()
               .setProductType(ProductType.SUBS)

// uses queryPurchasesAsync Kotlin extension function
val purchasesResult = billingClient.queryPurchasesAsync(params.build())

// check purchasesResult.billingResult
// process returned purchasesResult.purchasesList, e.g. display the plans user owns

Java

billingClient.queryPurchasesAsync(
    QueryPurchasesParams.newBuilder()
      .setProductType(ProductType.SUBS)
      .build(),
    new PurchasesResponseListener() {
      public void onQueryPurchasesResponse(BillingResult billingResult, List purchases) {
        // check billingResult
        // process returned purchase list, e.g. display the plans user owns

      }
    }
);

Buscar o histórico de compras

O método queryPurchaseHistoryAsync() retorna a compra mais recente feita pelo usuário para cada produto, mesmo que essa compra tenha sido cancelada, consumida ou estiver vencida.

Caso você esteja usando extensões Kotlin, é possível usar a função de extensão queryPurchaseHistory().

Kotlin

val params = QueryPurchaseHistoryParams.newBuilder()
               .setProductType(ProductType.SUBS)

// uses queryPurchaseHistory Kotlin extension function
val purchaseHistoryResult = billingClient.queryPurchaseHistory(params.build())

// check purchaseHistoryResult.billingResult
// process returned purchaseHistoryResult.purchaseHistoryRecordList, e.g. display purchase

Java

billingClient.queryPurchaseHistoryAsync(
    QueryPurchaseHistoryParams.newBuilder()
        .setProductType(ProductType.SUBS)
        .build(),
    new PurchaseHistoryResponseListener() {
      public void onPurchaseHistoryResponse(
        BillingResult billingResult, List purchasesHistoryList) {
          // check billingResult
          // process returned purchase history list, e.g. display purchase history
        }
    }
);

Como processar compras feitas fora do app

Algumas compras, como resgates de promoções, podem acontecer fora do app. Quando um usuário faz uma compra desse tipo, ele espera que o app mostre uma mensagem ou use algum tipo de mecanismo de notificação para informar que recebeu e processou corretamente a compra. Confira alguns mecanismos aceitáveis:

  • Mostrar um pop-up no app.
  • Entregar a mensagem a uma caixa de mensagens no aplicativo e informar claramente que há uma nova mensagem.
  • Usar uma mensagem de notificação do SO.

Lembre-se de que é possível que seu app esteja em qualquer estado quando reconhecer a compra. É possível até mesmo que ele não estivesse instalado quando a compra foi feita. Os usuários esperam receber a compra quando retomam o app, independentemente do estado em que ele está.

Você precisa detectar as compras, independentemente do estado em que o app estava quando a compra foi feita. No entanto, há algumas exceções em que pode ser aceitável não notificar imediatamente o usuário de que o item foi recebido. Por exemplo:

  • Durante a parte de ação de um jogo, em que exibir uma mensagem pode distrair o usuário. Nesse caso, notifique-o após o término da ação.
  • Durante cenas, em que a exibição de uma mensagem pode distrair o usuário. Nesse caso, notifique o usuário após o término da cena.
  • Durante o tutorial inicial e as partes da configuração do usuário no jogo. Recomendamos que você notifique os novos usuários sobre o prêmio assim que eles abrirem o jogo ou durante a configuração inicial. No entanto, é aceitável aguardar até que a sequência principal do jogo esteja disponível para enviar a notificação.

Sempre pense na experiência do usuário ao decidir quando e como notificá-lo sobre compras feitas fora do app. Sempre que um usuário não recebe uma notificação imediatamente, ele pode ficar confuso e parar de usar seu app, entrar em contato com o suporte ao usuário ou reclamar nas mídias sociais. Observação: o PurchasesUpdatedListener é registrado no contexto do aplicativo para processar as atualizações de compras, incluindo aquelas iniciadas fora do app. Isso significa que, se o processo do app não existir, o PurchasesUpdatedListener não será notificado. É por esse motivo que o app precisa chamar BillingClient.queryPurchasesAsync() no método onResume(), conforme mencionado em Buscar compras.

Processar transações pendentes

O Google Play oferece suporte para transações pendentes, ou aquelas que exigem uma ou mais etapas extras entre o momento em que um usuário inicia uma compra e o processamento da forma de pagamento. Não conceda direito de acesso nesses tipos de compras até que o Google notifique você de que a cobrança foi feita na forma de pagamento do usuário.

Por exemplo, um usuário pode criar uma compra PENDING de um item no aplicativo escolhendo dinheiro como forma de pagamento. Em seguida, ele pode escolher uma loja física em que concluirá a transação e receberá um código por notificação e e-mail. Quando o usuário chegar à loja física, ele poderá resgatar o código com o caixa e pagar com dinheiro. O Google notifica você e o usuário de que pagamento foi recebido. Então, seu aplicativo pode conceder direito de acesso ao usuário.

O app precisa chamar enablePendingPurchases() como parte da inicialização do app para oferecer suporte para transações pendentes.

Quando seu app recebe uma nova compra, pelo PurchasesUpdatedListener ou ao chamar queryPurchasesAsync(), use o método getPurchaseState() para determinar se o estado de compra é PURCHASED ou PENDING.

Se o app estiver em execução quando o usuário concluir a compra, o PurchasesUpdatedListener será chamado de novo, e PurchaseState será PURCHASED. Nesse momento, seu app pode processar a compra usando o método padrão para processar compras únicas. O app também precisa chamar queryPurchasesAsync() no método onResume() para processar compras que fizeram a transição para o estado PURCHASED enquanto ele não estava em execução.

Seu app também pode usar Notificações do desenvolvedor em tempo real com compras pendentes detectando OneTimeProductNotifications. Quando a compra mudar de PENDING para PURCHASED, seu app vai receber uma notificação ONE_TIME_PRODUCT_PURCHASED. Se a compra for cancelada, seu app vai receber uma notificação ONE_TIME_PRODUCT_CANCELED. Isso poderá acontecer se o cliente não concluir o pagamento no prazo exigido. Ao receber essas notificações, você pode usar a API Google Play Developer, que inclui um estado PENDING para Purchases.products.

Confira instruções detalhadas sobre como testar esse cenário em Testar compras pendentes.

Como processar compras de quantidade múltipla

O Google Play permite que os clientes comprem mais de uma unidade do mesmo produto no app em uma única transação especificando a quantidade no carrinho de compras. Esse recurso está disponível nas versões 4.0 e mais recentes da Biblioteca Google Play Faturamento. O app precisa processar compras de quantidade múltipla e conceder direito de acesso ao usuário de acordo com a quantidade especificada na compra.

Para aceitar compras de quantidade múltipla, a lógica de provisionamento do app precisa verificar a quantidade de itens. É possível acessar um campo quantity em uma destas APIs:

Depois de adicionar a lógica de processamento de compras de quantidade múltipla, você precisará ativar esse recurso para o produto correspondente na página de gerenciamento de produtos do app no Google Play Console.

Consultar a configuração de faturamento do usuário

getBillingConfigAsync() mostra o país em que o usuário usa o Google Play.

É possível consultar a configuração de faturamento do usuário depois de criar um BillingClient. O snippet de código abaixo descreve como fazer uma chamada para getBillingConfigAsync(). Gerencie a resposta implementando BillingConfigResponseListener. Esse listener recebe atualizações para todas as consultas de configuração de faturamento iniciadas pelo seu app.

Se o BillingResult retornado não contiver erros, confira o campo countryCode no objeto BillingConfig para saber o país do Google Play do usuário.

Kotlin

// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
    object : BillingConfigResponseListener {
        override fun onBillingConfigResponse(
            billingResult: BillingResult,
            billingConfig: BillingConfig?
        ) {
            if (billingResult.responseCode == BillingResponseCode.OK
                && billingConfig != null) {
                val countryCode = billingConfig.countryCode
                ...
            } else {
                // TODO: Handle errors
            }
        }
    })

Java

// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
    new BillingConfigResponseListener() {
      public void onBillingConfigResponse(
          BillingResult billingResult, BillingConfig billingConfig) {
        if (billingResult.getResponseCode() == BillingResponseCode.OK
            && billingConfig != null) {
            String countryCode = billingConfig.getCountryCode();
            ...
         } else {
            // TODO: Handle errors
        }
      }
    });