Tutorial

Siga as etapas deste tutorial para integrar seu aplicativo para Android distribuído na Google Play Store com a API Google Pay e veja como configurar esse app para aceitar cartões de pagamento.

Etapa 1: definir a versão da API Google Pay

Declare a versão da API Google Pay que o aplicativo usa. As versões principal e secundária afetam os campos esperados em cada objeto transmitido e são incluídas na resposta.

Crie um objeto de solicitação básico que contenha as propriedades presentes em todos os outros objetos de solicitação.


      private static JSONObject getBaseRequest() throws JSONException {
        return new JSONObject().put("apiVersion", 2).put("apiVersionMinor", 0);
      }
    

Etapa 2: solicitar um token de pagamento para seu provedor de pagamento.

O Google criptografa informações sobre o cartão selecionado de um pagador para processamento seguro por um provedor de pagamento.


      private static JSONObject getGatewayTokenizationSpecification() throws JSONException {
        return new JSONObject(){{
          put("type", "PAYMENT_GATEWAY");
          put("parameters", new JSONObject(){{
            put("gateway", "example");
            put("gatewayMerchantId", "exampleGatewayMerchantId");
            }
          });
        }};
      }

Substitua example e exampleGatewayMerchantId pelos valores adequados para seu provedor de pagamento. Use a tabela a seguir para encontrar os valores gateway e gatewayMerchantId específicos para seu provedor de pagamento:

Gateway Parâmetros e documentos
ACI
"gateway": "aciworldwide"
"gatewayMerchantId": "YOUR_ENTITY_ID"

Documentos do desenvolvedor

Adyen
"gateway": "adyen"
"gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"

Documentos do desenvolvedor

Alfa-Bank
"gateway": "alfabank"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Alfa-Bank Ukraine
"gateway": "alfabankua"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

APPEX
"gateway": "epos"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Assist
"gateway": "assist"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Sistemas de faturamento
"gateway": "billingsystems"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Bizzon
"gateway": "bizzon"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Blue Media
"gateway": "bluemedia"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

BlueSnap
"gateway": "bluesnap"
"gatewayMerchantId": "YOUR_shopToken"

Documentos do desenvolvedor

Braintree
"gateway": "braintree"
"braintree:apiVersion": "v1"
"braintree:sdkVersion": "braintree.client.VERSION"
"braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID"
"braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY"

Documentos do desenvolvedor

Braspag
"gateway": "cielo"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

CardConnect
"gateway": "cardconnect"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Cathay United Bank
"gateway": "cathaybk"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Chase Merchant Services
"gateway": "chase"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Checkout.com
"gateway": "checkoutltd"
"gatewayMerchantId": "YOUR_PUBLIC_KEY"

Documentos do desenvolvedor

CloudPayments
"gateway": "cloudpayments"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Computop
"gateway": "computop"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

ConcordPay
"gateway": "concordpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Credorax
"gateway": "credorax"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Cybersource
"gateway": "cybersource"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Datatrans
"gateway": "datatrans"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

dLocal
"gateway": "dlocal"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Dotpay
"gateway": "dotpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

e-SiTef da Software Express
"gateway": "softwareexpress"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

EasyPay
"gateway": "easypay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

EBANX
"gateway": "ebanx"
"gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY"

Documentos do desenvolvedor

eCard
"gateway": "ecard"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

ECPay
"gateway": "ecpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

eGHL
"gateway": "eghl"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

eSafe
"gateway": "esafe"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Gateway de pagamento da Evo
"gateway": "evopaymentgateway"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Fat Zebra
"gateway": "fatzebra"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

First Data (Payeezy)
"gateway": "firstdata"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

FreedomPay
"gateway": "freedompay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Gestpay
"gateway": "gestpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Global One Pay
"gateway": "globalonepay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Global Payments
"gateway": "globalpayments"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Gateway de pagamento GMO
"gateway": "gmopg"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

GoPay
"gateway": "gopay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

GP Webpay
"gateway": "gpwebpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

HiTrust
"gateway": "hitrustpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

iPay88
"gateway": "ipay88"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

iQmetrix
"gateway": "iqmetrixpaymentservicesgateway"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

IXOPAY
"gateway": "ixopay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

JudoPay
"gateway": "judopay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Kassa
"gateway": "kassacom"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Kineox
"gateway": "kineox"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

LogPay
"gateway": "logpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Lyra
"gateway": "lyra"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Mastercard Payment Gateway Services
"gateway": "mpgs"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

MOBI.Money
"gateway": "mobimoney"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Molpay
"gateway": "molpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Moneris
"gateway": "moneris"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Moneta
"gateway": "moneta"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Monext
"gateway": "monext"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Money.Mail.Ru
"gateway": "moneymailru"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Multicarta
"gateway": "mulitcarta"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Mundipagg
"gateway": "mundipagg"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

MyCheck
"gateway": "mycheck"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

MyPay
"gateway": "mypay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Nenhum documento do desenvolvedor disponível

Newebpay
"gateway": "newebpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Nexi
"gateway": "nexi"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

NMI
"gateway": "creditcall"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Nuvei
"gateway": "nuvei"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

paygent
"gateway": "paygent"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

PayLane
"gateway": "paylane"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Payler
"gateway": "payler"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Payload
"gateway": "payload"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Paymark
"gateway": "paymark"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Paymentwall
"gateway": "paymentwall"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Paymo
"gateway": "paymo"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

PayOnline
"gateway": "payonline"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Paysafe
"gateway": "paysafe"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Payture
"gateway": "payture"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

PayU
"gateway": "payu"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Payway
  "gateway": "payway"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Platon
  "gateway": "platon"
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Portmone
"gateway": "portmonecom"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Przelewy24
"gateway": "przelewy24"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

RBK.money
"gateway": "rbkmoney"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Redsys
"gateway": "redsys"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Sberbank
"gateway": "sberbank"
"gatewayMerchantId": "YOUR_ORGANIZATION_NAME"

Documentos do desenvolvedor

Sipay
"gateway": "sipay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Softbank Payment Service
"gateway": "sbps"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Solid
"gateway": "solid"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Sony Payment Services
"gateway": "sonypaymentservices"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Spreedly
"gateway": "spreedly"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Square
"gateway": "square"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Stripe
"gateway": "stripe"
"stripe:version": "2018-10-31"
"stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY"

Documentos do desenvolvedor

TapPay (Cherri Tech)
"gateway": "tappay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Tatra banka (CardPay)
"gateway": "tatrabanka"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

No Documentos do desenvolvedor available

Tinkoff
"gateway": "tinkoff"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

theMAP
"gateway": "themap"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

TPay.com
"gateway": "tpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Tranzzo
"gateway": "tranzzo"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Uniteller
"gateway": "uniteller"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

UPC
"gateway": "upc"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Vantiv
"gateway": "vantiv"
"vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID"
"vantiv:merchantOrderId": "YOUR_ORDER_ID"
"vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID"
"vantiv:merchantReportGroup": "*web"

Documentos do desenvolvedor

Veritrans
"gateway": "veritrans"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Vindicia
"gateway": "vindicia"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

WayForPay
"gateway": "wayforpay"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Windcave
"gateway": "windcave"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Wirecard
"gateway": "wirecard"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Worldnet
"gateway": "worldnet"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Documentos do desenvolvedor

Worldpay
"gateway": "worldpay"
"gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"

Documentos do desenvolvedor

Yandex.Checkout
"gateway": "yandexcheckout"
"gatewayMerchantId": "YOUR_SHOP_ID"

Documentos do desenvolvedor

O tipo de tokenização de PAYMENT_GATEWAY é a implementação de comerciante mais comum da forma de pagamento com cartão na API Google Pay. Caso seu provedor de pagamento não seja compatível, você pode aceitar o Google Pay por meio de uma integração DIRECT. Para mais informações, consulte a documentação de tokenização Direct.

Etapa 3: definir as redes de cartões de pagamento compatíveis

Defina as redes de cartões que seu aplicativo aceita.

    private static JSONArray getAllowedCardNetworks() {
      return new JSONArray()
          .put("AMEX")
          .put("DISCOVER")
          .put("INTERAC");
          .put("JCB")
          .put("MASTERCARD")
          .put("VISA");
    }

A API Google Pay pode retornar cartões registrados em arquivos no Google.com (PAN_ONLY) ou um token em um dispositivo Android autenticado com um criptograma 3-D Secure (CRYPTOGRAM_3DS).

    private static JSONArray getAllowedCardAuthMethods() {
      return new JSONArray()
          .put("PAN_ONLY")
          .put("CRYPTOGRAM_3DS");
    }

Consulte CardParameters em nossa referência de objeto JSON para mais informações. Verifique com o gateway ou processador quais são as redes de cartões compatíveis e se há suporte para tokens de dispositivos Android.

Etapa 4: descrever as formas de pagamento permitidas

Combine os métodos de autenticação e as redes de cartões compatíveis para descrever o suporte do aplicativo à forma de pagamento CARD.


      private static JSONObject getBaseCardPaymentMethod() throws JSONException {
        JSONObject cardPaymentMethod = new JSONObject();
        cardPaymentMethod.put("type", "CARD");

        JSONObject parameters = new JSONObject();
        parameters.put("allowedAuthMethods", getAllowedCardAuthMethods());
        parameters.put("allowedCardNetworks", getAllowedCardNetworks());
        // Optionally, you can add billing address/phone number associated with a CARD payment method.
        parameters.put("billingAddressRequired", true);

        JSONObject billingAddressParameters = new JSONObject();
        billingAddressParameters.put("format", "FULL");

        parameters.put("billingAddressParameters", billingAddressParameters);

        cardPaymentMethod.put("parameters", parameters);

        return cardPaymentMethod;
      }
    

Estenda o objeto da forma de pagamento por cartão base para descrever as informações que precisam ser retornadas ao aplicativo, incluindo dados de pagamento tokenizados.


      private static JSONObject getCardPaymentMethod() throws JSONException {
        JSONObject cardPaymentMethod = getBaseCardPaymentMethod();
        cardPaymentMethod.put("tokenizationSpecification", getGatewayTokenizationSpecification());

        return cardPaymentMethod;
      }
    

Consulte CardParameters em nossa referência de objeto JSON para mais informações sobre os parameters compatíveis.

Além de "CARD", o Google Pay também é compatível com a forma de pagamento "PAYPAL". Para mais detalhes sobre como adicionar "PAYPAL" como forma de pagamento ao Google Pay, consulte a documentação do desenvolvedor do PayPal.

Etapa 5: criar uma instância do PaymentsClient

Crie uma instância de PaymentsClient no método onCreate na sua Activity. O PaymentsClient é usado para interação com a API Google Pay.


      public static PaymentsClient createPaymentsClient(Activity activity) {
        Wallet.WalletOptions walletOptions =
            new Wallet.WalletOptions.Builder().setEnvironment(Constants.PAYMENTS_ENVIRONMENT).build();
        return Wallet.getPaymentsClient(activity, walletOptions);
      }
    

Etapa 6: determinar a disponibilidade para pagar com a API Google Pay

Adicione as formas de pagamento permitidas ao objeto de solicitação básico com o seguinte snippet de código:


      public static Optional<JSONObject> getIsReadyToPayRequest() {
        try {
          JSONObject isReadyToPayRequest = getBaseRequest();
          isReadyToPayRequest.put(
              "allowedPaymentMethods", new JSONArray().put(getBaseCardPaymentMethod()));

          return Optional.of(isReadyToPayRequest);
        } catch (JSONException e) {
          return Optional.empty();
        }
      }
    

Antes de exibir o botão Google Pay, chame a API isReadyToPay para determinar se o usuário pode fazer pagamentos com a API Google Pay. Consulte a documentação do objeto JSON IsReadyToPayRequest para uma lista completa das propriedades de configuração.


      private void possiblyShowGooglePayButton() {
        final Optional<JSONObject> isReadyToPayJson = PaymentsUtil.getIsReadyToPayRequest();
        if (!isReadyToPayJson.isPresent()) {
          return;
        }
        IsReadyToPayRequest request = IsReadyToPayRequest.fromJson(isReadyToPayJson.get().toString());
        if (request == null) {
          return;
        }

        // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an
        // OnCompleteListener to be triggered when the result of the call is known.
        Task<Boolean> task = mPaymentsClient.isReadyToPay(request);
        task.addOnCompleteListener(this,
            new OnCompleteListener<Boolean>() {
              @Override
              public void onComplete(@NonNull Task<Boolean> task) {
                if (task.isSuccessful()) {
                  setGooglePayAvailable(task.getResult());
                } else {
                  Log.w("isReadyToPay failed", task.getException());
                }
              }
            });
      }
    

Como neste exemplo, o Google Pay deve ser apresentado como uma opção de pagamento somente depois que você receber um resultado bem-sucedido da função isReadyToPay. É mais comum exibir um botão de pagamento do Google Pay por meio de um layout include ao implementar uma opção de pagamento. Consulte as diretrizes da promoção da marca para mais informações sobre os botões de pagamento, logotipos e marcas do Google Pay disponíveis para uso no aplicativo.

Etapa 7: criar um objeto PaymentDataRequest

Um objeto JSON PaymentDataRequest descreve as informações que você quer solicitar de um pagador na página de pagamento do Google Pay.

Forneça informações sobre o preço da transação e o status do preço fornecido. Consulte a documentação do objeto JSON TransactionInfo para mais informações.

No exemplo a seguir, mostramos como receber informações da transação, especificamente preço, status do preço e moeda.


      private static JSONObject getTransactionInfo(String price) throws JSONException {
        JSONObject transactionInfo = new JSONObject();
        transactionInfo.put("totalPrice", price);
        transactionInfo.put("totalPriceStatus", "FINAL");
        transactionInfo.put("countryCode", Constants.COUNTRY_CODE);
        transactionInfo.put("currencyCode", Constants.CURRENCY_CODE);

        return transactionInfo;
      }
    

Forneça um nome de comerciante visível ao usuário. Consulte a documentação do objeto JSON MerchantInfo para mais informações.

O exemplo a seguir mostra como conseguir o nome do comerciante:


      private static JSONObject getMerchantInfo() throws JSONException {
        return new JSONObject().put("merchantName", "Example Merchant");
      }
    

Atribua seu objeto de solicitação básico a um novo objeto JSON PaymentDataRequest. Em seguida, adicione as formas de pagamento compatíveis com seu aplicativo, como qualquer configuração de dados adicionais esperados na resposta. Por fim, adicione informações sobre a transação e o comerciante que faz a solicitação.

O exemplo a seguir mostra como solicitar dados de pagamento:


      public static Optional<JSONObject> getPaymentDataRequest(String price) {
        try {
          JSONObject paymentDataRequest = PaymentsUtil.getBaseRequest();
          paymentDataRequest.put(
              "allowedPaymentMethods", new JSONArray().put(PaymentsUtil.getCardPaymentMethod()));
          paymentDataRequest.put("transactionInfo", PaymentsUtil.getTransactionInfo(price));
          paymentDataRequest.put("merchantInfo", PaymentsUtil.getMerchantInfo());

          /* An optional shipping address requirement is a top-level property of the PaymentDataRequest
          JSON object. */
          paymentDataRequest.put("shippingAddressRequired", true);

          JSONObject shippingAddressParameters = new JSONObject();
          shippingAddressParameters.put("phoneNumberRequired", false);

          JSONArray allowedCountryCodes = new JSONArray(Constants.SHIPPING_SUPPORTED_COUNTRIES);

          shippingAddressParameters.put("allowedCountryCodes", allowedCountryCodes);
          paymentDataRequest.put("shippingAddressParameters", shippingAddressParameters);
          return Optional.of(paymentDataRequest);
        } catch (JSONException e) {
          return Optional.empty();
        }
      }
    

Consulte a documentação do objeto JSON PaymentDataRequest para mais informações.

Etapa 8: registrar o manipulador de eventos para o gesto do usuário

Defina um OnClickListener para solicitar a exibição de uma página de pagamento do Google Pay após a ativação de um botão de pagamento do Google Pay pelo usuário.


        mGooglePayButton.setOnClickListener(
            new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                requestPayment(view);
              }
            });
    

O objeto PaymentDataRequest é um Parcelable que representa uma solicitação de dados de pagamento e fornece informações necessárias para aceitar um pagamento. Use a classe AutoResolveHelper para resolver automaticamente a Task e, em seguida, processe o resultado no método onActivityResult da classe Activity.

Etapa 9: processar o objeto de resposta

Um objeto PaymentData é retornado para onActivityResult após um pagador fornecer com êxito as informações solicitadas na página de pagamento do Google Pay.

Converta uma resposta bem-sucedida em JSON para passar as informações de pagamento para o processador e apresentar uma confirmação de compra ao usuário. Se o transactionInfo.totalPriceStatus passado para PaymentDataRequest for ESTIMATED, será necessário mostrar um preço final antes de cobrar a forma de pagamento retornada.

Extraia o token de pagamento da resposta paymentData. Se você implementar uma integração de gateway, passe esse token para o gateway sem nenhuma modificação.


      public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            // value passed in AutoResolveHelper
          case LOAD_PAYMENT_DATA_REQUEST_CODE:
            switch (resultCode) {
              case Activity.RESULT_OK:
                PaymentData paymentData = PaymentData.getFromIntent(data);
                handlePaymentSuccess(paymentData);
                break;
              case Activity.RESULT_CANCELED:
                // Nothing to here normally - the user simply cancelled without selecting a
                // payment method.
                break;
              case AutoResolveHelper.RESULT_ERROR:
                Status status = AutoResolveHelper.getStatusFromIntent(data);
                handleError(status.getStatusCode());
                break;
              default:
                // Do nothing.
            }

            // Re-enables the Google Pay payment button.
            mGooglePayButton.setClickable(true);
            break;
        }
      }
    

Consulte a referência de objeto JSON PaymentData para receber mais informações sobre o conteúdo e a estrutura da resposta.

Reunir todas as informações

O exemplo a seguir mostra um exemplo completo para um projeto configurado corretamente. Consulte os passos da configuração no nível do projeto na seção "Configurar seu projeto" em Configurar a API Google Pay.

CheckoutActivity.java

Esta Activity de exemplo supõe a existência de um botão de pagamento do Google Pay com um atributo ID de googlepay_button no seu layout.

    /*
     * Copyright 2017 Google Inc.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    package com.google.android.gms.samples.wallet;

    import android.app.Activity;
    import android.app.AlertDialog;
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.annotation.NonNull;
    import android.util.Log;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    import com.google.android.gms.common.api.ApiException;
    import com.google.android.gms.common.api.Status;
    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.Task;
    import com.google.android.gms.wallet.AutoResolveHelper;
    import com.google.android.gms.wallet.IsReadyToPayRequest;
    import com.google.android.gms.wallet.PaymentData;
    import com.google.android.gms.wallet.PaymentDataRequest;
    import com.google.android.gms.wallet.PaymentsClient;
    import java.util.Optional;
    import org.json.JSONException;
    import org.json.JSONObject;

    /**
     * Checkout implementation for the app
     */
    public class CheckoutActivity extends Activity {
      /**
       * A client for interacting with the Google Pay API.
       *
       * @see <a
       *     href="https://developers.google.com/android/reference/com/google/android/gms/wallet/PaymentsClient">PaymentsClient</a>
       */
      private PaymentsClient mPaymentsClient;

      /**
       * A Google Pay payment button presented to the viewer for interaction.
       *
       * @see <a href="https://developers.google.com/pay/api/android/guides/brand-guidelines">Google Pay
       *     payment button brand guidelines</a>
       */
      private View mGooglePayButton;

      /**
       * Arbitrarily-picked constant integer you define to track a request for payment data activity.
       *
       * @value #LOAD_PAYMENT_DATA_REQUEST_CODE
       */
      private static final int LOAD_PAYMENT_DATA_REQUEST_CODE = 991;

      private TextView mGooglePayStatusText;

      private ItemInfo mBikeItem = new ItemInfo("Simple Bike", 300 * 1000000, R.drawable.bike);
      private long mShippingCost = 90 * 1000000;
      /**
       * Initialize the Google Pay API on creation of the activity
       *
       * @see Activity#onCreate(android.os.Bundle)
       */
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_checkout);

        // Set up the mock information for our item in the UI.
        initItemUI();

        mGooglePayButton = findViewById(R.id.googlepay_button);
        mGooglePayStatusText = findViewById(R.id.googlepay_status);

        // Initialize a Google Pay API client for an environment suitable for testing.
        // It's recommended to create the PaymentsClient object inside of the onCreate method.
        mPaymentsClient = PaymentsUtil.createPaymentsClient(this);
        possiblyShowGooglePayButton();

        mGooglePayButton.setOnClickListener(
            new View.OnClickListener() {
              @Override
              public void onClick(View view) {
                requestPayment(view);
              }
            });
      }

      /**
       * Determine the viewer's ability to pay with a payment method supported by your app and display a
       * Google Pay payment button.
       *
       * @see <a href=
       *     "https://developers.google.com/android/reference/com/google/android/gms/wallet/PaymentsClient.html#isReadyToPay(com.google.android.gms.wallet.IsReadyToPayRequest)">PaymentsClient#IsReadyToPay</a>
       */
      private void possiblyShowGooglePayButton() {
        final Optional<JSONObject> isReadyToPayJson = PaymentsUtil.getIsReadyToPayRequest();
        if (!isReadyToPayJson.isPresent()) {
          return;
        }
        IsReadyToPayRequest request = IsReadyToPayRequest.fromJson(isReadyToPayJson.get().toString());
        if (request == null) {
          return;
        }

        // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an
        // OnCompleteListener to be triggered when the result of the call is known.
        Task<Boolean> task = mPaymentsClient.isReadyToPay(request);
        task.addOnCompleteListener(this,
            new OnCompleteListener<Boolean>() {
              @Override
              public void onComplete(@NonNull Task<Boolean> task) {
                if (task.isSuccessful()) {
                  setGooglePayAvailable(task.getResult());
                } else {
                  Log.w("isReadyToPay failed", task.getException());
                }
              }
            });
      }

      /**
       * If isReadyToPay returned {@code true}, show the button and hide the "checking" text. Otherwise,
       * notify the user that Google Pay is not available. Please adjust to fit in with your current
       * user flow. You are not required to explicitly let the user know if isReadyToPay returns {@code
       * false}.
       *
       * @param available isReadyToPay API response.
       */
      private void setGooglePayAvailable(boolean available) {
        if (available) {
          mGooglePayStatusText.setVisibility(View.GONE);
          mGooglePayButton.setVisibility(View.VISIBLE);
        } else {
          mGooglePayStatusText.setText(R.string.googlepay_status_unavailable);
        }
      }

      /**
       * Handle a resolved activity from the Google Pay payment sheet.
       *
       * @param requestCode Request code originally supplied to AutoResolveHelper in requestPayment().
       * @param resultCode Result code returned by the Google Pay API.
       * @param data Intent from the Google Pay API containing payment or error data.
       * @see <a href="https://developer.android.com/training/basics/intents/result">Getting a result
       *     from an Activity</a>
       */
      @Override
      public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            // value passed in AutoResolveHelper
          case LOAD_PAYMENT_DATA_REQUEST_CODE:
            switch (resultCode) {
              case Activity.RESULT_OK:
                PaymentData paymentData = PaymentData.getFromIntent(data);
                handlePaymentSuccess(paymentData);
                break;
              case Activity.RESULT_CANCELED:
                // Nothing to here normally - the user simply cancelled without selecting a
                // payment method.
                break;
              case AutoResolveHelper.RESULT_ERROR:
                Status status = AutoResolveHelper.getStatusFromIntent(data);
                handleError(status.getStatusCode());
                break;
              default:
                // Do nothing.
            }

            // Re-enables the Google Pay payment button.
            mGooglePayButton.setClickable(true);
            break;
        }
      }

      /**
       * PaymentData response object contains the payment information, as well as any additional
       * requested information, such as billing and shipping address.
       *
       * @param paymentData A response object returned by Google after a payer approves payment.
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#PaymentData">Payment
       *     Data</a>
       */
      private void handlePaymentSuccess(PaymentData paymentData) {
        String paymentInformation = paymentData.toJson();

        // Token will be null if PaymentDataRequest was not constructed using fromJson(String).
        if (paymentInformation == null) {
          return;
        }
        JSONObject paymentMethodData;

        try {
          paymentMethodData = new JSONObject(paymentInformation).getJSONObject("paymentMethodData");
          // If the gateway is set to "example", no payment information is returned - instead, the
          // token will only consist of "examplePaymentMethodToken".
          if (paymentMethodData
                  .getJSONObject("tokenizationData")
                  .getString("type")
                  .equals("PAYMENT_GATEWAY")
              && paymentMethodData
                  .getJSONObject("tokenizationData")
                  .getString("token")
                  .equals("examplePaymentMethodToken")) {
            AlertDialog alertDialog =
                new AlertDialog.Builder(this)
                    .setTitle("Warning")
                    .setMessage(
                        "Gateway name set to \"example\" - please modify "
                            + "Constants.java and replace it with your own gateway.")
                    .setPositiveButton("OK", null)
                    .create();
            alertDialog.show();
          }

          String billingName =
              paymentMethodData.getJSONObject("info").getJSONObject("billingAddress").getString("name");
          Log.d("BillingName", billingName);
          Toast.makeText(this, getString(R.string.payments_show_name, billingName), Toast.LENGTH_LONG)
              .show();

          // Logging token string.
          Log.d("GooglePaymentToken", paymentMethodData.getJSONObject("tokenizationData").getString("token"));
        } catch (JSONException e) {
          Log.e("handlePaymentSuccess", "Error: " + e.toString());
          return;
        }
      }

      /**
       * At this stage, the user has already seen a popup informing them an error occurred. Normally,
       * only logging is required.
       *
       * @param statusCode will hold the value of any constant from CommonStatusCode or one of the
       *     WalletConstants.ERROR_CODE_* constants.
       * @see <a
       *     href="https://developers.google.com/android/reference/com/google/android/gms/wallet/WalletConstants#constant-summary">
       *     Wallet Constants Library</a>
       */
      private void handleError(int statusCode) {
        Log.w("loadPaymentData failed", String.format("Error code: %d", statusCode));
      }

      // This method is called when the Pay with Google button is clicked.
      public void requestPayment(View view) {
        // Disables the button to prevent multiple clicks.
        mGooglePayButton.setClickable(false);

        // The price provided to the API should include taxes and shipping.
        // This price is not displayed to the user.
        String price = PaymentsUtil.microsToString(mBikeItem.getPriceMicros() + mShippingCost);

        // TransactionInfo transaction = PaymentsUtil.createTransaction(price);
        Optional<JSONObject> paymentDataRequestJson = PaymentsUtil.getPaymentDataRequest(price);
        if (!paymentDataRequestJson.isPresent()) {
          return;
        }
        PaymentDataRequest request =
            PaymentDataRequest.fromJson(paymentDataRequestJson.get().toString());

        // Since loadPaymentData may show the UI asking the user to select a payment method, we use
        // AutoResolveHelper to wait for the user interacting with it. Once completed,
        // onActivityResult will be called with the result.
        if (request != null) {
          AutoResolveHelper.resolveTask(
              mPaymentsClient.loadPaymentData(request), this, LOAD_PAYMENT_DATA_REQUEST_CODE);
        }
      }

      private void initItemUI() {
        TextView itemName = findViewById(R.id.text_item_name);
        ImageView itemImage = findViewById(R.id.image_item_image);
        TextView itemPrice = findViewById(R.id.text_item_price);

        itemName.setText(mBikeItem.getName());
        itemImage.setImageResource(mBikeItem.getImageResourceId());
        itemPrice.setText(PaymentsUtil.microsToString(mBikeItem.getPriceMicros()));
      }
    }
    
    

PaymentsUtil.java

Este arquivo de exemplo cria objetos JSON adequados para criar um IsReadyToPayRequest ou um PaymentDataRequest.

    /*
     * Copyright 2017 Google Inc.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    package com.google.android.gms.samples.wallet;

    import android.app.Activity;
    import com.google.android.gms.wallet.PaymentsClient;
    import com.google.android.gms.wallet.Wallet;
    import java.math.BigDecimal;
    import java.math.RoundingMode;
    import java.util.HashMap;
    import java.util.Optional;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;

    /**
     * Contains helper static methods for dealing with the Payments API.
     *
     * <p>Many of the parameters used in the code are optional and are set here merely to call out their
     * existence. Please consult the documentation to learn more and feel free to remove ones not
     * relevant to your implementation.
     */
    public class PaymentsUtil {
      private static final BigDecimal MICROS = new BigDecimal(1000000d);

      private PaymentsUtil() {}

      /**
       * Create a Google Pay API base request object with properties used in all requests.
       *
       * @return Google Pay API base request object.
       * @throws JSONException
       */
      private static JSONObject getBaseRequest() throws JSONException {
        return new JSONObject().put("apiVersion", 2).put("apiVersionMinor", 0);
      }

      /**
       * Creates an instance of {@link PaymentsClient} for use in an {@link Activity} using the
       * environment and theme set in {@link Constants}.
       *
       * @param activity is the caller's activity.
       */
      public static PaymentsClient createPaymentsClient(Activity activity) {
        Wallet.WalletOptions walletOptions =
            new Wallet.WalletOptions.Builder().setEnvironment(Constants.PAYMENTS_ENVIRONMENT).build();
        return Wallet.getPaymentsClient(activity, walletOptions);
      }

      /**
       * Gateway Integration: Identify your gateway and your app's gateway merchant identifier.
       *
       * <p>The Google Pay API response will return an encrypted payment method capable of being charged
       * by a supported gateway after payer authorization.
       *
       * <p>TODO: Check with your gateway on the parameters to pass and modify them in Constants.java.
       *
       * @return Payment data tokenization for the CARD payment method.
       * @throws JSONException
       * @see <a href=
       *     "https://developers.google.com/pay/api/android/reference/object#PaymentMethodTokenizationSpecification">PaymentMethodTokenizationSpecification</a>
       */
      private static JSONObject getGatewayTokenizationSpecification() throws JSONException {
        return new JSONObject(){{
          put("type", "PAYMENT_GATEWAY");
          put("parameters", new JSONObject(){{
            put("gateway", "example");
            put("gatewayMerchantId", "exampleGatewayMerchantId");
            }
          });
        }};
      }

      /**
       * {@code DIRECT} Integration: Decrypt a response directly on your servers. This configuration has
       * additional data security requirements from Google and additional PCI DSS compliance complexity.
       *
       * <p>Please refer to the documentation for more information about {@code DIRECT} integration. The
       * type of integration you use depends on your payment processor.
       *
       * @return Payment data tokenization for the CARD payment method.
       * @throws JSONException
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#PaymentMethodTokenizationSpecification">PaymentMethodTokenizationSpecification</a>
       */
      private static JSONObject getDirectTokenizationSpecification()
          throws JSONException, RuntimeException {
        if (Constants.DIRECT_TOKENIZATION_PARAMETERS.isEmpty()
            || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY.isEmpty()
            || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY == null
            || Constants.DIRECT_TOKENIZATION_PUBLIC_KEY == "REPLACE_ME") {
          throw new RuntimeException(
              "Please edit the Constants.java file to add protocol version & public key.");
        }
        JSONObject tokenizationSpecification = new JSONObject();

        tokenizationSpecification.put("type", "DIRECT");
        JSONObject parameters = new JSONObject(Constants.DIRECT_TOKENIZATION_PARAMETERS);
        tokenizationSpecification.put("parameters", parameters);

        return tokenizationSpecification;
      }

      /**
       * Card networks supported by your app and your gateway.
       *
       * <p>TODO: Confirm card networks supported by your app and gateway & update in Constants.java.
       *
       * @return Allowed card networks
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#CardParameters">CardParameters</a>
       */
      private static JSONArray getAllowedCardNetworks() {
        return new JSONArray(Constants.SUPPORTED_NETWORKS);
      }

      /**
       * Card authentication methods supported by your app and your gateway.
       *
       * <p>TODO: Confirm your processor supports Android device tokens on your supported card networks
       * and make updates in Constants.java.
       *
       * @return Allowed card authentication methods.
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#CardParameters">CardParameters</a>
       */
      private static JSONArray getAllowedCardAuthMethods() {
        return new JSONArray(Constants.SUPPORTED_METHODS);
      }

      /**
       * Describe your app's support for the CARD payment method.
       *
       * <p>The provided properties are applicable to both an IsReadyToPayRequest and a
       * PaymentDataRequest.
       *
       * @return A CARD PaymentMethod object describing accepted cards.
       * @throws JSONException
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#PaymentMethod">PaymentMethod</a>
       */
      private static JSONObject getBaseCardPaymentMethod() throws JSONException {
        JSONObject cardPaymentMethod = new JSONObject();
        cardPaymentMethod.put("type", "CARD");

        JSONObject parameters = new JSONObject();
        parameters.put("allowedAuthMethods", getAllowedCardAuthMethods());
        parameters.put("allowedCardNetworks", getAllowedCardNetworks());
        // Optionally, you can add billing address/phone number associated with a CARD payment method.
        parameters.put("billingAddressRequired", true);

        JSONObject billingAddressParameters = new JSONObject();
        billingAddressParameters.put("format", "FULL");

        parameters.put("billingAddressParameters", billingAddressParameters);

        cardPaymentMethod.put("parameters", parameters);

        return cardPaymentMethod;
      }

      /**
       * Describe the expected returned payment data for the CARD payment method
       *
       * @return A CARD PaymentMethod describing accepted cards and optional fields.
       * @throws JSONException
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#PaymentMethod">PaymentMethod</a>
       */
      private static JSONObject getCardPaymentMethod() throws JSONException {
        JSONObject cardPaymentMethod = getBaseCardPaymentMethod();
        cardPaymentMethod.put("tokenizationSpecification", getGatewayTokenizationSpecification());

        return cardPaymentMethod;
      }

      /**
       * An object describing accepted forms of payment by your app, used to determine a viewer's
       * readiness to pay.
       *
       * @return API version and payment methods supported by the app.
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#IsReadyToPayRequest">IsReadyToPayRequest</a>
       */
      public static Optional<JSONObject> getIsReadyToPayRequest() {
        try {
          JSONObject isReadyToPayRequest = getBaseRequest();
          isReadyToPayRequest.put(
              "allowedPaymentMethods", new JSONArray().put(getBaseCardPaymentMethod()));

          return Optional.of(isReadyToPayRequest);
        } catch (JSONException e) {
          return Optional.empty();
        }
      }

      /**
       * Provide Google Pay API with a payment amount, currency, and amount status.
       *
       * @return information about the requested payment.
       * @throws JSONException
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#TransactionInfo">TransactionInfo</a>
       */
      private static JSONObject getTransactionInfo(String price) throws JSONException {
        JSONObject transactionInfo = new JSONObject();
        transactionInfo.put("totalPrice", price);
        transactionInfo.put("totalPriceStatus", "FINAL");
        transactionInfo.put("countryCode", Constants.COUNTRY_CODE);
        transactionInfo.put("currencyCode", Constants.CURRENCY_CODE);

        return transactionInfo;
      }

      /**
       * Information about the merchant requesting payment information
       *
       * @return Information about the merchant.
       * @throws JSONException
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#MerchantInfo">MerchantInfo</a>
       */
      private static JSONObject getMerchantInfo() throws JSONException {
        return new JSONObject().put("merchantName", "Example Merchant");
      }

      /**
       * An object describing information requested in a Google Pay payment sheet
       *
       * @return Payment data expected by your app.
       * @see <a
       *     href="https://developers.google.com/pay/api/android/reference/object#PaymentDataRequest">PaymentDataRequest</a>
       */
      public static Optional<JSONObject> getPaymentDataRequest(String price) {
        try {
          JSONObject paymentDataRequest = PaymentsUtil.getBaseRequest();
          paymentDataRequest.put(
              "allowedPaymentMethods", new JSONArray().put(PaymentsUtil.getCardPaymentMethod()));
          paymentDataRequest.put("transactionInfo", PaymentsUtil.getTransactionInfo(price));
          paymentDataRequest.put("merchantInfo", PaymentsUtil.getMerchantInfo());

          /* An optional shipping address requirement is a top-level property of the PaymentDataRequest
          JSON object. */
          paymentDataRequest.put("shippingAddressRequired", true);

          JSONObject shippingAddressParameters = new JSONObject();
          shippingAddressParameters.put("phoneNumberRequired", false);

          JSONArray allowedCountryCodes = new JSONArray(Constants.SHIPPING_SUPPORTED_COUNTRIES);

          shippingAddressParameters.put("allowedCountryCodes", allowedCountryCodes);
          paymentDataRequest.put("shippingAddressParameters", shippingAddressParameters);
          return Optional.of(paymentDataRequest);
        } catch (JSONException e) {
          return Optional.empty();
        }
      }

      /**
       * Converts micros to a string format accepted by {@link PaymentsUtil#getPaymentDataRequest}.
       *
       * @param micros value of the price.
       */
      public static String microsToString(long micros) {
        return new BigDecimal(micros).divide(MICROS).setScale(2, RoundingMode.HALF_EVEN).toString();
      }
    }