教程

按照本教程中的步骤操作,将您通过 Google Play 商店分发的 Android 应用与 Google Pay API 集成,并将其配置为接受支付卡。

第 1 步:定义您的 Google Pay API 版本

声明您的应用所使用的 Google Pay API 版本。该主要及次要版本会影响每个传递对象中预期的字段,并且会包含在响应中。

创建基本请求对象,其中包含所有其他请求对象中存在的属性。


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

第 2 步:为您的付款服务机构申请付款令牌

Google 会加密付款人所选卡的相关信息,以便付款服务机构进行安全处理。


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

示例exampleGatewayMerchantId 替换为付款服务机构的相应值。请使用下表查找您的付款服务机构的具体 gatewaygatewayMerchantId 值:

网关 参数和文档
ACI
"gateway": "aciworldwide"
"gatewayMerchantId": "YOUR_ENTITY_ID"

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

结算系统
"gateway": "billingsystems"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

没有开发者文档

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

开发者文档

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

没有开发者文档

Evo Payment Gateway
"gateway": "evopaymentgateway"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

没有开发者文档

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

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

开发者文档

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

Developer docs

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

开发者文档

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

没有开发者文档

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

开发者文档

GMO Payment Gateway
"gateway": "gmopg"
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

开发者文档

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

开发者文档

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

没有开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

Developer docs

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

没有开发者文档

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

Developer docs

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

没有开发者文档

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

开发者文档

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

没有开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

没有开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

Developer docs

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

Developer docs

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

Developer docs

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

No developer docs available

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

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

开发者文档

PAYMENT_GATEWAY 令牌化类型是 Google Pay API 中为商家实现卡付款方式的最常见类型。如果您的付款服务机构不受支持,您也许可以通过直接集成来接受 Google Pay。如需了解详情,请参阅直接令牌化文档

第 3 步:指定支持的支付卡网络

定义您的应用所接受的支付卡网络。

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

Google Pay API 可以返回在 Google.com 上留存的支付卡 (PAN_ONLY) 或在 Android 设备上以 3D 安全密文进行身份验证的设备令牌 (CRYPTOGRAM_3DS)。

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

如需了解详情,请参阅 JSON 对象参考中的 CardParameters。请与您的网关或处理方联系,了解所支持的支付卡网络以及对 Android 设备令牌的支持情况。

第 4 步:说明您允许的付款方式

为说明您的应用支持 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;
      }
    

扩展基本的卡付款方式对象,以说明预期返回给您的应用的信息,其中必须包括令牌化的付款数据。


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

        return cardPaymentMethod;
      }
    

如需详细了解受支持的 parameters,请参阅 JSON 对象参考中的 CardParameters

除了 CARD 之外,Google Pay 还支持 PAYPAL 付款方式。如需详细了解如何将 PAYPAL 添加为 Google Pay 的付款方式,请参阅 PayPal 开发者文档

第 5 步:创建 PaymentsClient 实例

Activity 中的 onCreate 方法中创建 PaymentsClient 的实例。PaymentsClient 用来与 Google Pay API 进行互动。


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

第 6 步:确定是否能使用 Google Pay API 进行付款

请使用以下代码段将您允许的付款方式添加到您的基本请求对象中:


      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();
        }
      }
    

在显示 Google Pay 按钮之前,请调用 isReadyToPay API 可确定用户是否能使用 Google Pay API 进行付款。如需查看配置属性的完整列表,请参阅 IsReadyToPayRequest JSON 对象文档


      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());
                }
              }
            });
      }
    

如本例所示,仅当您从 isReadyToPay 函数收到成功结果后,Google Pay 才应显示为付款方式。最常见的做法是,在实现付款方式时,通过布局 include 显示 Google Pay 付款按钮。如需详细了解可在您的应用中使用的 Google Pay 付款按钮、徽标和标识,请参阅品牌推广指南

第 7 步:创建 PaymentDataRequest 对象

PaymentDataRequest JSON 对象描述了您要通过 Google Pay 付款表格向付款人请求的信息。

请提供与交易价格以及所提供价格的状态相关的信息。如需了解详情,请参阅 TransactionInfo JSON 对象文档

以下示例演示了如何获取交易信息,特别是价格、价格状态和币种。


      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;
      }
    

提供用户可见的商家名称。如需了解详情,请参阅 MerchantInfo JSON 对象文档

以下示例演示了如何获取商家名称:


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

将您的基本请求对象分配给新的 PaymentDataRequest JSON 对象。然后,添加您的应用所支持的付款方式,例如响应中预期的任何其他数据的配置。最后,添加有关交易和提出请求的商家的信息。

以下示例演示了如何请求付款数据:


      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();
        }
      }
    

如需了解详情,请参阅 PaymentDataRequest JSON 对象文档

第 8 步:为用户手势注册事件处理程序

定义 OnClickListener 以便用户在激活 Google Pay 付款按钮后请求显示 Google Pay 付款表格。


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

PaymentDataRequest 对象是代表付款数据请求的 Parcelable,可提供支持付款所必需的信息。使用 AutoResolveHelper 类则可自动解析 Task,然后在您的 Activity 类的 onActivityResult 方法中处理结果。

第 9 步:处理响应对象

当付款人在 Google Pay 付款表格中成功提供所请求的信息后,系统会将 PaymentData 对象返回给 onActivityResult

为将付款信息传递给您的处理方,并向用户显示购买确认信息,需将成功的响应转换为 JSON。如果传递给 PaymentDataRequesttransactionInfo.totalPriceStatusESTIMATED,您必须先显示最终价格,然后才能按返回的付款方式扣费。

请从 paymentData 响应中提取付款令牌。如果您实现了网关集成,请将此令牌传递给您的网关,无需进行任何修改。


      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 JSON 对象参考

总结

以下示例展示了正确配置项目的完整示例。如需了解项目级设置步骤,请参阅设置 Google Pay API 的“配置您的项目”部分。

CheckoutActivity.java

此示例 Activity 假设您的布局中含有 googlepay_button 特性为 ID 的 Google Pay 付款按钮。

    /*
     * 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

此示例文件可建立适合建立 IsReadyToPayRequestPaymentDataRequest 的 JSON 对象。

    /*
     * 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();
      }
    }