Tutorial

Follow the steps in this tutorial to integrate your Android application that is distributed through the Google Play Store with the Google Pay API, and configure it to accept payment cards.

    Step 1: Define your Google Pay API version

    Declare the version of the Google Pay API that your app uses. The major and minor version affects the fields expected in each passed object and is included in the response.

    Create a base request object that contains properties that are present in all other request objects.

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

    Step 2: Choose a payment tokenization method

    Google encrypts information about a payer's selected card for secure processing by a supported gateway or directly on a merchant's secured servers. Examples for both options are provided below.

    Gateway

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

    Replace example with a gateway identifier of a Google-supported gateway and exampleGatewayMerchantId with a unique merchant identifier provided by your gateway.

    See gateway tokenization documentation for more information about supported gateways and unique identifiers. The PAYMENT_GATEWAY tokenization type is the most common merchant implementation of the card payment method in the Google Pay API.

    Direct

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

    Replace the abbreviated publicKey value with a public key you provided in your Google Pay Developer Profile to receive payment information encrypted with that key. See our payment data cryptography documentation for information about configuring encryption keys suitable for the Google Pay API.

    Step 3: Define supported payment card networks

    Define the card networks that your app accepts.

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

    The Google Pay API may return cards on file on Google.com (PAN_ONLY) and/or a device token on an Android device authenticated with a 3-D Secure cryptogram (CRYPTOGRAM_3DS).

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

    See CardParameters in our JSON object reference for more information. Check with your gateway or processor for the card networks supported and support for Android device tokens.

    Step 4: Describe your allowed payment methods

    Combine your supported authentication methods and supported card networks in order to describe your app's support for the CARD payment method.

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

    Extend the base card payment method object to describe information expected to be returned to your application including tokenized payment data.

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

    See CardParameters in our JSON object reference for more information about supported parameters.

    Step 5: Create a PaymentsClient instance

    Create an instance of PaymentsClient in the onCreate method in your Activity. The PaymentsClient is used for interaction with the 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());
    }

    Step 6: Determine readiness to pay with the Google Pay API

    Add your allowed payment methods to your base request object with the following code snippet:

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

    Call the isReadyToPay API to determine if the user can make payments using the Google Pay API. See the IsReadyToPayRequest JSON object documentation for a full list of configuration properties.

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

    Google Pay should be presented as a payment option after receiving a successful result from the isReadyToPay. Displaying a Google Pay payment button through a layout include is the most common implementation. See Brand guidelines for more information about Google Pay payment buttons, logos, and marks available for use in your app.

    Step 7: Create a PaymentDataRequest object

    A PaymentDataRequest JSON object describes the information you would like to request from a payer in a Google Pay payment sheet.

    Provide information about the transaction price and the status of the provided price. See TransactionInfo JSON object documentation for more information.

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

    Provide a user-visible merchant name. See the MerchantInfo JSON object documentation for more information.

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

    Assign your base request object to a new PaymentDataRequest JSON object. Add the payment methods supported by your app including any configuration of additional data expected in the response. Also, add information about the transaction and the requesting merchant.

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

    See the PaymentDataRequest JSON object documentation for more information.

    Step 8: Register event handler for user gesture

    Define an OnClickListener to request display of a Google Pay payment sheet after user activation of a Google Pay payment button.

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

    The PaymentDataRequest object is a Parcelable representing a payment data request, which provides information that is necessary in order to support a payment. Use the AutoResolveHelper class to auto resolve the Task and then handle the result in the onActivityResult method of your Activity class.

    Step 9: Handle the response object

    A PaymentData object is returned to onActivityResult after a payer has successfully provided the requested information in the Google Pay payment sheet.

    Convert a successful response to JSON in order to pass payment information to your processor and to present the user with a confirmation of their purchase. If the transactionInfo.totalPriceStatus passed to PaymentDataRequest was ESTIMATED, you are expected to show a final price before charging the returned payment method.

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

    See the PaymentData JSON object reference for more information about the content and structure of the response.

    Put it all together

    The following example shows a complete example for a properly configured project. See the "Configure your project" section of Set up Google Pay API for the project-level setup.

    YourActivity.java

    This example Activity assumes a Google Pay payment button with an ID attribute of googlepay exists in your layout.

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

    This example file builds JSON objects suitable to build an IsReadyToPayRequest or a PaymentDataRequest.

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

Send feedback about...

Google Pay API for Android