教程

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

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

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

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

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

    第 2 步:选择支付的令牌化方法

    Google 会通过支持的网关或直接在商家的安全服务器上加密付款人所选卡的相关信息,从而实现安全处理。下面提供了这两种选项的示例。

    网关

    private static JSONObject getTokenizationSpecification() {
      JSONObject tokenizationSpecification = new JSONObject();
      tokenizationSpecification.put("type", "PAYMENT_GATEWAY");
      tokenizationSpecification.put(
          "parameters",
          new JSONObject()
              .put("gateway", "example")
              .put("gatewayMerchantId", "exampleMerchantId"));
    
      return tokenizationSpecification;
    }

    请将 “example”替换为 Google 所支持网关的网关标识符,并将“exampleGatewayMerchantId”替换为您的网关所提供的商家唯一标识符。

    如需详细了解所支持的网关和唯一标识符,请参阅网关令牌化文档PAYMENT_GATEWAY 令牌化类型是 Google Pay API 中为商家实现卡付款方式的最常见类型。

    直接

    private static JSONObject getTokenizationSpecification() {
      JSONObject tokenizationSpecification = new JSONObject();
      tokenizationSpecification.put("type", "DIRECT");
      tokenizationSpecification.put(
          "parameters",
          new JSONObject()
              .put("protocolVersion", "ECv2")
              .put("publicKey", "BOdoXP1aiNp.....kh3JUhiSZKHYF2Y="));
    
      return tokenizationSpecification;
    }

    请将缩写的 publicKey 值替换为您在 Google Pay 开发者资料中提供的公钥,以接收使用该密钥加密的付款信息。如需了解如何配置适合 Google Pay API 的加密密钥,请参阅我们的付款数据加密文档。

    第 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() {
      JSONObject cardPaymentMethod = new JSONObject();
      cardPaymentMethod.put("type", "CARD");
      cardPaymentMethod.put(
          "parameters",
          new JSONObject()
              .put("allowedAuthMethods", getAllowedCardAuthMethods())
              .put("allowedCardNetworks", getAllowedCardNetworks()));
    
      return cardPaymentMethod;
    }

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

    private static JSONObject getCardPaymentMethod() {
      JSONObject cardPaymentMethod = getBaseCardPaymentMethod();
      cardPaymentMethod.put("tokenizationSpecification", getTokenizationSpecification());
    
      return cardPaymentMethod;
    }
    

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

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

    第 5 步:创建 PaymentsClient 实例

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

    private PaymentsClient mPaymentsClient;
    
    @Override
    public void onCreate() {
      super.onCreate();
    
      mPaymentsClient =
          Wallet.getPaymentsClient(
              this,
              new Wallet.WalletOptions.Builder()
                  .setEnvironment(WalletConstants.ENVIRONMENT_TEST)
                  .build());
    }

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

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

    public static JSONObject getIsReadyToPayRequest() {
      JSONObject isReadyToPayRequest = getBaseRequest();
      isReadyToPayRequest.put(
        "allowedPaymentMethods",
        new JSONArray()
          .put(getBaseCardPaymentMethod()));
    
      return isReadyToPayRequest;
    }
    

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

    IsReadyToPayRequest request =
        IsReadyToPayRequest.fromJson(getIsReadyToPayRequest().toString());
    Task<Boolean> task = mPaymentsClient.isReadyToPay(request);
    task.addOnCompleteListener(
        new OnCompleteListener<Boolean>() {
          @Override
          public void onComplete(@NonNull Task<Boolean> task) {
            try {
              boolean result = task.getResult(ApiException.class);
              if (result) {
                // show Google Pay as a payment option
              }
            } catch (ApiException e) {
            }
          }
        });

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

    第 7 步:创建 PaymentDataRequest 对象

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

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

    private static JSONObject getTransactionInfo() {
      JSONObject transactionInfo = new JSONObject();
      transactionInfo.put("totalPrice", "12.34");
      transactionInfo.put("totalPriceStatus", "FINAL");
      transactionInfo.put("currencyCode", "USD");
    
      return transactionInfo;
    }
    

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

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

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

    public static JSONObject getPaymentDataRequest() {
      JSONObject paymentDataRequest = getBaseRequest();
      paymentDataRequest.put(
        "allowedPaymentMethods",
        new JSONArray()
            .put(getCardPaymentMethod()));
      paymentDataRequest.put("transactionInfo", getTransactionInfo());
      paymentDataRequest.put("merchantInfo", getMerchantInfo());
    
      return paymentDataRequest;
    }

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

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

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

    findViewById(R.id.googlepay)
        .setOnClickListener(
            new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                PaymentDataRequest request =
                    PaymentDataRequest.fromJson(paymentDataRequest.toString());
                if (request != null) {
                  AutoResolveHelper.resolveTask(
                      mPaymentsClient.loadPaymentData(request),
                      this,
                      // LOAD_PAYMENT_DATA_REQUEST_CODE is a constant integer value you define
                      LOAD_PAYMENT_DATA_REQUEST_CODE);
                }
              }
            });

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

    第 9 步:处理响应对象

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

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

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

    @Override
    protected 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);
              String json = paymentData.toJson();
              // if using gateway tokenization, pass this token without modification
              String paymentMethodData = new JSONObject(json)
                                           .getJSONObject(“paymentMethodData”);
              String paymentToken = paymentMethodData
                                      .getJSONObject("tokenizationData")
                                      .getString("token");
              break;
            case Activity.RESULT_CANCELED:
              break;
            case AutoResolveHelper.RESULT_ERROR:
              Status status = AutoResolveHelper.getStatusFromIntent(data);
              // Log the status for debugging.
              // Generally, there is no need to show an error to the user.
              // The Google Pay payment sheet will present any account errors.
              break;
            default:
              // Do nothing.
          }
          break;
        default:
          // Do nothing.
      }
    }

    如需详细了解响应的内容和结构,请参阅 PaymentData JSON 对象参考

    总结

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

    YourActivity.java

    此示例 Activity 假定您的布局中含有 ID 属性为 googlepay 的 Google Pay 付款按钮。

    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.support.annotation.NonNull;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    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 com.google.android.gms.wallet.Wallet;
    import com.google.android.gms.wallet.WalletConstants;
    import java.util.Optional;
    import org.json.JSONObject;
    
    public class YourActivity extends AppCompatActivity {
      /**
       * 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;
    
      /** A constant integer you define to track a request for payment data activity */
      private static final int LOAD_PAYMENT_DATA_REQUEST_CODE = 42;
    
      /**
       * 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_main);
    
        // initialize a Google Pay API client for an environment suitable for testing
        mPaymentsClient =
            Wallet.getPaymentsClient(
                this,
                new Wallet.WalletOptions.Builder()
                    .setEnvironment(WalletConstants.ENVIRONMENT_TEST)
                    .build());
    
        possiblyShowGooglePayButton();
      }
    
      /**
       * 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#isReadyToPay(com.google.android.gms.wallet.IsReadyToPayRequest)">PaymentsClient#IsReadyToPay</a>
       */
      private void possiblyShowGooglePayButton() {
        final Optional<JSONObject> isReadyToPayJson = GooglePay.getIsReadyToPayRequest();
        if (!isReadyToPayJson.isPresent()) {
          return;
        }
        IsReadyToPayRequest request = IsReadyToPayRequest.fromJson(isReadyToPayJson.get().toString());
        if (request == null) {
          return;
        }
        Task<Boolean> task = mPaymentsClient.isReadyToPay(request);
        task.addOnCompleteListener(
            new OnCompleteListener<Boolean>() {
              @Override
              public void onComplete(@NonNull Task<Boolean> task) {
                try {
                  boolean result = task.getResult(ApiException.class);
                  if (result) {
                    // show Google as a payment option
                    mGooglePayButton = findViewById(R.id.googlepay);
                    mGooglePayButton.setOnClickListener(
                        new View.OnClickListener() {
                          @Override
                          public void onClick(View view) {
                            requestPayment(view);
                          }
                        });
                    mGooglePayButton.setVisibility(View.VISIBLE);
                  }
                } catch (ApiException exception) {
                  // handle developer errors
                }
              }
            });
      }
    
      /**
       * Display the Google Pay payment sheet after interaction with the Google Pay payment button
       *
       * @param view optionally uniquely identify the interactive element prompting for payment
       */
      public void requestPayment(View view) {
        Optional<JSONObject> paymentDataRequestJson = GooglePay.getPaymentDataRequest();
        if (!paymentDataRequestJson.isPresent()) {
          return;
        }
        PaymentDataRequest request =
            PaymentDataRequest.fromJson(paymentDataRequestJson.get().toString());
        if (request != null) {
          AutoResolveHelper.resolveTask(
              mPaymentsClient.loadPaymentData(request), this, LOAD_PAYMENT_DATA_REQUEST_CODE);
        }
      }
    
      /**
       * Handle a resolved activity from the Google Pay payment sheet
       *
       * @param requestCode the request code originally supplied to AutoResolveHelper in
       *     requestPayment()
       * @param resultCode the result code returned by the Google Pay API
       * @param data an 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
      protected 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);
                String json = paymentData.toJson();
                // if using gateway tokenization, pass this token without modification
                String paymentMethodData = new JSONObject(json)
                                             .getJSONObject(“paymentMethodData”);
                String paymentToken = paymentMethodData
                                        .getJSONObject("tokenizationData")
                                        .getString("token");
                break;
              case Activity.RESULT_CANCELED:
                break;
              case AutoResolveHelper.RESULT_ERROR:
                Status status = AutoResolveHelper.getStatusFromIntent(data);
                // Log the status for debugging.
                // Generally, there is no need to show an error to the user.
                // The Google Pay payment sheet will present any account errors.
                break;
              default:
                // Do nothing.
            }
            break;
          default:
            // Do nothing.
        }
      }
    }
    

    GooglePay.java

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

    import java.util.Optional;
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    /**
     * Google Pay API request configurations
     *
     * @see <a href="https://developers.google.com/pay/api/android/">Google Pay API Android
     *     documentation</a>
     */
    public class GooglePay {
      /**
       * 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);
      }
    
      /**
       * 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
       *
       * @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 getTokenizationSpecification() throws JSONException {
        JSONObject tokenizationSpecification = new JSONObject();
        tokenizationSpecification.put("type", "PAYMENT_GATEWAY");
        tokenizationSpecification.put(
            "parameters",
            new JSONObject()
                .put("gateway", "example")
                .put("gatewayMerchantId", "exampleGatewayMerchantId"));
    
        return tokenizationSpecification;
      }
    
      /**
       * Card networks supported by your app and your gateway
       *
       * <p>TODO: confirm card networks supported by your app and gateway
       *
       * @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()
            .put("AMEX")
            .put("DISCOVER")
            .put("JCB")
            .put("MASTERCARD")
            .put("VISA");
      }
    
      /**
       * Card authentication methods supported by your app and your gateway
       *
       * <p>TODO: confirm your processor supports Android device tokens on your supported card networks
       *
       * @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()
            .put("PAN_ONLY")
            .put("CRYPTOGRAM_3DS");
      }
    
      /**
       * 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");
        cardPaymentMethod.put(
            "parameters",
            new JSONObject()
                .put("allowedAuthMethods", GooglePay.getAllowedCardAuthMethods())
                .put("allowedCardNetworks", GooglePay.getAllowedCardNetworks()));
    
        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 = GooglePay.getBaseCardPaymentMethod();
        cardPaymentMethod.put("tokenizationSpecification", GooglePay.getTokenizationSpecification());
    
        return cardPaymentMethod;
      }
    
      /**
       * 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() throws JSONException {
        JSONObject transactionInfo = new JSONObject();
        transactionInfo.put("totalPrice", "12.34");
        transactionInfo.put("totalPriceStatus", "FINAL");
        transactionInfo.put("currencyCode", "USD");
    
        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 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 = GooglePay.getBaseRequest();
          isReadyToPayRequest.put(
              "allowedPaymentMethods", new JSONArray().put(getBaseCardPaymentMethod()));
          return Optional.of(isReadyToPayRequest);
        } catch (JSONException e) {
          return Optional.empty();
        }
      }
    
      /**
       * 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() {
        try {
          JSONObject paymentDataRequest = GooglePay.getBaseRequest();
          paymentDataRequest.put(
              "allowedPaymentMethods", new JSONArray().put(GooglePay.getCardPaymentMethod()));
          paymentDataRequest.put("transactionInfo", GooglePay.getTransactionInfo());
          paymentDataRequest.put("merchantInfo", GooglePay.getMerchantInfo());
          return Optional.of(paymentDataRequest);
        } catch (JSONException e) {
          return Optional.empty();
        }
      }
    }