Usar Faturamento em apps com AIDL

É possível usar uma interface Android Interface Definition Language (AIDL) para implementar alguns recursos do serviço de Faturamento em apps.

Comprar produtos

Figura 1. A sequência básica de uma solicitação de compra.

Um fluxo de compra típico com a API In-app Billing é o seguinte:

  1. O aplicativo envia uma solicitação isBillingSupported ao Google Play para determinar se a versão de destino da API In-app Billing que você está usando é compatível. A solicitação também verifica se o Google Play é compatível com o faturamento no país do usuário.
  2. Quando o aplicativo é iniciado ou o usuário faz login, é recomendável verificar com o Google Play para determinar quais itens são de propriedade do usuário. Para consultar as compras no aplicativo do usuário, envie uma solicitação getPurchases. Se a solicitação for bem-sucedida, o Google Play retornará um Bundle contendo uma lista de IDs de produto dos itens comprados, uma lista dos detalhes individuais da compra e uma lista das assinaturas para as compras.
  3. Normalmente, informe o usuário sobre os produtos que estão disponíveis para compra. Para consultar os detalhes dos produtos no aplicativo definidos no Google Play, seu aplicativo pode enviar um pedido getSkuDetails. É necessário especificar uma lista de IDs de produto na solicitação de consulta. Se a solicitação for bem-sucedida, o Google Play retornará um Bundle contendo detalhes do produto, incluindo o preço, o título, a descrição e o tipo de compra do produto.
  4. Se o usuário não possuir determinado produto no aplicativo, você poderá iniciar uma compra para ele. Para iniciar uma solicitação de compra, o aplicativo envia uma solicitação getBuyIntent, especificando o código do produto a ser comprado, junto com outros parâmetros. É necessário registrar o ID do produto ao criar um novo produto no aplicativo no Play Console.
    1. O Google Play retorna um Bundle que contém um PendingIntent. Seu aplicativo o utiliza para iniciar a IU do processo de finalização da compra.
    2. Seu aplicativo inicia o intent pendente chamando o método startIntentSenderForResult.
    3. Quando o fluxo de finalização da compra é concluído (ou seja, o usuário adquire o item ou cancela a compra), o Google Play envia uma resposta Intent para seu método onActivityResult. O código de resultado do onActivityResult possui um código de resultado que indica se a compra foi realizada ou cancelada. A resposta Intent contém informações sobre o item comprado, incluindo uma string purchaseToken que é gerada pelo Google Play para identificar exclusivamente essa transação de compra. A Intent também contém a assinatura da compra, assinada com sua chave de desenvolvedor privada.

Para saber mais sobre as chamadas da API In-app Billing e as respostas do servidor, consulte Referência do Faturamento em apps.

Consumir produtos no aplicativo

É possível usar o mecanismo de consumo para rastrear os produtos gerenciados que o usuário possui.

Todos os produtos gerenciados são administrados na API In-app Billing. Isso significa que a propriedade do usuário de todas as compras de produtos gerenciados é mantida pelo Google Play, e seu aplicativo pode consultar as informações de compra do usuário quando necessário. Quando o usuário adquire um produto gerenciado, essa compra é registrada no Google Play. Quando um produto interno do aplicativo é comprado, ele é considerado “detido”. Os produtos gerenciados no estado "detido" não podem ser comprados no Google Play. É necessário enviar uma solicitação de consumo para o produto gerenciado "detido" antes que o Google Play o torne disponível para compra novamente. O consumo do produto gerenciado o reverte para o estado "não detido" e descarta os dados de compra anteriores.

Figura 2. A sequência básica para uma solicitação de consumo.

Para obter a lista de produtos detidos pelo usuário, seu aplicativo envia uma chamada getPurchases ao Google Play. O aplicativo pode fazer uma solicitação de consumo enviando uma chamada consumePurchase. No argumento da solicitação, é preciso especificar a string purchaseToken exclusiva do produto gerenciado conseguida no Google Play no ato da compra. O Google Play retorna um código de status que indica se o consumo foi registrado.

Produtos gerenciados não consumíveis e consumíveis

Cabe a você decidir se quer tratar seus produtos gerenciados como itens não consumíveis ou consumíveis.

Produtos não consumíveis
Normalmente, você não implementaria o consumo de produtos gerenciados que só podem ser comprados uma vez no aplicativo e fornecem um benefício permanente. Depois de comprados, esses produtos são permanentemente associados à Conta do Google do usuário. Um exemplo de produto gerenciado não consumível é um upgrade premium ou um pacote de nível.
Produtos consumíveis
Por outro lado, é possível implementar o consumo de produtos que podem ser disponibilizados para compra várias vezes. Normalmente, esses produtos fornecem determinados efeitos temporários. Por exemplo, o personagem no jogo do usuário pode ganhar pontos de vida ou ganhar moedas de ouro extras no inventário. O fornecimento dos benefícios ou efeitos do produto adquirido no aplicativo é chamado de provisionamento do produto gerenciado. Você é responsável por controlar e acompanhar o modo como os produtos gerenciados são provisionados para os usuários.

Importante: antes de provisionar o produto gerenciado consumível no aplicativo, é preciso enviar uma solicitação de consumo ao Google Play e receber uma resposta indicando que o consumo foi registrado.

Gerenciar compras de consumíveis no aplicativo

Veja o fluxo básico para comprar um produto gerenciado consumível:

  1. Chame o método getBuyIntent para iniciar um fluxo de compra.
  2. Inspecione o Bundle retornado no Google Play para determinar se a compra foi concluída.
  3. Se a compra tiver sido realizada, consuma-a chamando o método consumePurchase.
  4. Inspecione o código de resposta do Google Play para determinar se o consumo foi concluído.
  5. Se sim, provisione o produto no aplicativo.

Em seguida, quando o usuário inicializar ou efetuar login no aplicativo, será preciso verificar se ele possui produtos consumíveis pendentes nele. Nesse caso, consuma e provisione esses itens. Veja o fluxo recomendado de inicialização do aplicativo ao implementar produtos consumíveis no aplicativo:

  1. Envie uma solicitação getPurchases para consultar os produtos no aplicativo detidos pelo usuário.
  2. Se houver algum produto consumível no aplicativo, consuma os itens chamando consumePurchase. Essa etapa é necessária porque o aplicativo pode concluir a ordem de compra do produto consumível, mas parar ou desconectar-se antes de o aplicativo conseguir enviar uma solicitação de consumo.
  3. Inspecione o código de resposta do Google Play para determinar se o consumo foi concluído.
  4. Se sim, provisione o produto no aplicativo.

Configurar compras concedidas como prêmios

Ao trabalhar com produtos concedidos como prêmios usando a AIDL, é necessário armazenar em cache a compra "Intent" antes que um usuário precise coletar o prêmio. É possível chamar o intent de compra em uma linha de execução em segundo plano e salvar a resposta "Intent" bem-sucedida até que o usuário realize uma ação para coletar a recompensa.

Listar e carregar SKUs

Antes de oferecer um produto concedido como prêmio a um usuário, consiga os detalhes do produto chamando getSkuDetails(). Um novo campo JSON, "rewardToken", é preenchido para cada produto concedido como prêmio na lista de SKUs.

Para fornecer a melhor experiência do usuário, é necessário garantir que um anúncio seja carregado e disponibilizado antes de oferecer o produto concedido como prêmio ao usuário. Para fazer isso, chame getBuyIntentExtraParams() em uma linha de execução em segundo plano. Depois de receber uma resposta de BILLING_RESPONSE_RESULT_OK, ative o produto concedido como prêmio para o usuário e salve o objeto PendingIntent retornado para uso posterior. O snippet de código a seguir demonstra o processo de carregamento do anúncio associado a um produto concedido como prêmio:

Kotlin

    val rewardToken = skuDetailsJson.optString("rewardToken")
    val extraParams = Bundle().putString("rewardToken", rewardToken)

    // This call blocks the current thread, so do this in the background.
    val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName,
            sku, "inapp", "", extraParams)

    val response = buyIntentBundle.getInt("RESPONSE_CODE")
    if (response == BILLING_RESPONSE_RESULT_OK) {
        // Enable rewarded product.

        // Save this object for use later.
        val pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT)
    } else {
        // Don't offer rewarded product.
    }
    

Java

    String rewardToken = skuDetailsJson.optString("rewardToken");
    Bundle extraParams = new Bundle();
    extraParams.putString("rewardToken", rewardToken);

    // This call blocks the current thread, so do this in the background.
    Bundle buyIntentBundle = mService.getBuyIntentExtraParams(9, getPackageName(),
            sku, "inapp", "", extraParams);

    int response = buyIntentBundle.getInt("RESPONSE_CODE");
    if (response == BILLING_RESPONSE_RESULT_OK) {
        // Enable rewarded product.

        // Save this object for use later.
        PendingIntent pendingIntentToSave = bundle.getParcelable(RESPONSE_BUY_INTENT);
    } else {
        // Don't offer rewarded product.
    }
    

Declarar anúncios adequados à idade

Para a facilitar o cumprimento das obrigações legais relacionadas a crianças e a usuários menores de idade, incluindo a Lei de Proteção da Privacidade On-line das Crianças (COPPA, na sigla em inglês) e o Regulamento geral de proteção de dados (GDPR, na sigla em inglês), é necessário que seu aplicativo declare quais anúncios podem ser tratados como direcionados a crianças nos Estados Unidos ou direcionados a usuários que estão abaixo da idade de consentimento aplicável no país deles. A Central de Ajuda da AdMob explica quando é preciso marcar as solicitações de anúncios com tratamento para direcionamento a crianças e com tratamento para usuários abaixo da idade de consentimento, além dos efeitos de fazer isso.

Para indicar que um pedido concedido como prêmio é direcionado para crianças ou para usuários menores de idade, inclua os parâmetros extras childDirected e underAgeOfConsent, como mostrado no seguinte snippet de código:

Kotlin

    val rewardToken = skuDetailsJson.optString("rewardToken")
    val extraParams = Bundle().putString("rewardToken", rewardToken)
            .putInt("childDirected", ChildDirected.CHILD_DIRECTED)
            .putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT)

    // This call blocks the current thread, so do this in the background.
    val buyIntentBundle : Bundle = mService.getBuyIntentExtraParams(9, packageName,
            sku, "inapp", "", extraParams)
    

Java

    Bundle extraParams = new Bundle();
    extraParams.putString("rewardToken", rewardToken);
    extraParams.putInt("childDirected", ChildDirected.CHILD_DIRECTED);
    extraParams.putInt("underAgeOfConsent", UnderAgeOfConsent.UNDER_AGE_OF_CONSENT);

    // This call blocks the current thread, so do this in the background.
    Bundle buyIntentBundle =
      mService.getBuyIntentExtraParams(
        9, getPackageName(), sku, "inapp", "", extraParams);
    

Mostrar anúncios antes de recompensar o usuário

Depois que o usuário clica no botão para começar a assistir ao anúncio, o aplicativo pode usar o objeto PendingIntent salvo para começar a mostrar anúncios. Para fazer isso, chame startIntentSenderForResult():

Kotlin

    startIntentSenderForResult(
        pendingIntentToSave,
        RC_BUY, Intent(),
        0,
        0,
        0
    )
    

Java

    startIntentSenderForResult(pendingIntentToSave, RC_BUY, new Intent(),
            0, 0, 0);
    

Em seguida, processe os resultados do fluxo de trabalho de faturamento em onActivityResult(), conforme mostrado nos snippets de código a seguir. Ao gerenciar o processo de exibição de anúncios, o Google Play usa o mesmo conjunto de códigos de resposta do servidor que usa para outros fluxos de faturamento.

Kotlin

    fun onActivityResult(requestCode : Int, resultCode : Int, data : Intent) {
        if (requestCode == RC_BUY) {
            int responseCode = data.getIntExtra(RESPONSE_CODE)
            String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA)
            String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE)

            // Handle reward purchase.
        }
    }
    

Java

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == RC_BUY) {
            int responseCode = data.getIntExtra(RESPONSE_CODE);
            String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
            String signature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);

            // Handle reward purchase.
        }
    }
    

Armazenamento em cache local

Como o cliente do Google Play agora armazena em cache informações do Faturamento em apps localmente no dispositivo, é possível usar a API In-app Billing para consultar essas informações com mais frequência. As seguintes chamadas da API In-app Billing são atendidas por meio de pesquisas de cache, em vez de exigir uma conexão de rede. Isso acelera significativamente o tempo de resposta da API:

  • getBuyIntent
  • getPurchases
  • isBillingSupported