Call or Embed Google Pay from API - Complete Example

 

Declare the version of the Google Pay API that your site uses. The major and minor versions are required in the fields of each passed object, and are included in the response.

The following code sample shows declared API versions:

const baseRequest = {
  apiVersion
: 2,
  apiVersionMinor
: 0
};

Google encrypts information about a payer's selected card for secure processing by a payment provider.

const tokenizationSpecification = {
  type
: 'PAYMENT_GATEWAY',
  parameters
: {
   
'gateway': 'example',
   
'gatewayMerchantId': 'exampleGatewayMerchantId'
 
}
};

Replace example and exampleGatewayMerchantId with the appropriate values for your payment provider. Use the following table to find the specific gateway and gatewayMerchantId values for your payment provider:

GatewayParameters and documents
ACI
  "gateway": "aciworldwide"
 
"gatewayMerchantId": "YOUR_ENTITY_ID"

Developer docs

Acquired.com
  "gateway": "acquired"
 
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"

Developer docs

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

Developer docs

Airwallex
  "gateway": "airwallex"
 
"gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"

Developer docs

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

The PAYMENT_GATEWAY tokenization type is the most common merchant implementation of the card payment method in the Google Pay API. If your payment provider isn't supported, you might be able to accept Google Pay by a DIRECT integration. For more information, see the Direct tokenization documentation.

Define the card networks accepted by your site. See the following code sample:

const allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "MIR", "VISA"];

The Google Pay API might return cards on file with Google (PAN_ONLY), and/or a device token on an Android device that's authenticated with a 3-D Secure cryptogram (CRYPTOGRAM_3DS). See the following code sample:

const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];

For more information, see CardParameters in our Object reference documentation. Also, check with your gateway or processor for the card networks that are supported, and for support for Android device tokens.

To describe your allowed payment methods, complete the following steps:

  1. Combine your supported authentication methods and supported card networks in order to describe your site's support for the CARD payment method. See the following code sample:
    const baseCardPaymentMethod = {
      type
    : 'CARD',
      parameters
    : {
        allowedAuthMethods
    : allowedCardAuthMethods,
        allowedCardNetworks
    : allowedCardNetworks
     
    }
    };
  2. Extend the base card payment method object to describe information you expect to be returned to your application. Include a description of the tokenized payment data. See the following code sample:
    const cardPaymentMethod = Object.assign(
     
    {tokenizationSpecification: tokenizationSpecification},
      baseCardPaymentMethod
    );
  3. For more information about supported parameters, see CardParameters.

    Google Pay currently only supports the CARD payment method type.

To load the Google Pay API JavaScript library, complete the following steps:

  1. Include Google's hosted JavaScript on your page. See the following code sample:
    <script
     
    async
     
    src="https://pay.google.com/gp/p/js/pay.js"
     
    onload="console.log('TODO: add onload function')">
    </script>
  2. After the Google Pay API JavaScript library loads, initialize a PaymentsClient object. Initial development uses a TEST environment, which returns dummy payment methods that are suitable to reference the structure of a payment response. In this environment, a selected payment method isn't capable of a transaction. See the following code sample.
    const paymentsClient =
       
    new google.payments.api.PaymentsClient({environment: 'TEST'});

    For more information about the requirements for a PRODUCTION environment that returns chargeable payment methods, see the Integration checklist.

To determine readiness to pay with the Google Pay API, complete the following steps:

  1. Add your allowed payment methods to your base request object. See the following code sample:
    const isReadyToPayRequest = Object.assign({}, baseRequest);
    isReadyToPayRequest
    .allowedPaymentMethods = [baseCardPaymentMethod];
  2. Call isReadyToPay() to determine if the Google Pay API is supported by the current device and browser for your specified payment methods. See the following code sample:
    paymentsClient.isReadyToPay(isReadyToPayRequest)
       
    .then(function(response) {
         
    if (response.result) {
           
    // add a Google Pay payment button
         
    }
       
    })
       
    .catch(function(err) {
         
    // show error in developer console for debugging
          console
    .error(err);
       
    });

Add a Google Pay payment button to your page to encourage shoppers to check out with payment methods that are supported by the Google Pay API and your site. For more information about available button types, colors, and display requirements, see the Brand guidelines.

See the following payment button code sample:

const button =
    paymentsClient
.createButton({onClick: () => console.log('TODO: click handler'),
    allowedPaymentMethods
: []}); // make sure to provide an allowed payment method
document
.getElementById('container').appendChild(button);

To create a PaymentDataRequest object, complete the following steps:

  1. Build a JavaScript object that describes your site's support for the Google Pay API. For a full list of supported properties, see PaymentDataRequest. See the following code sample:
    const paymentDataRequest = Object.assign({}, baseRequest);
  2. Add the payment methods supported by your app, such as any configuration of additional data that's expected in the response. See the following code sample:
    paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod];
  3. Define a total price and currency for a shopper to authorize. See the following code sample:
    paymentDataRequest.transactionInfo = {
      totalPriceStatus
    : 'FINAL',
      totalPrice
    : '123.45',
      currencyCode
    : 'USD',
      countryCode
    : 'US'
    };
  4. Provide a user-visible merchant name, and use our TEST merchantId value when in TEST. For more details, and for information on when to replace the TEST merchantId value, see MerchantInfo. See the following code sample of a user-visible merchant name:
    paymentDataRequest.merchantInfo = {
      merchantName
    : 'Example Merchant'
      merchantId
    : '12345678901234567890'
    };

To register an event handler for user gestures, complete the following steps:

  1. Register a click event handler for the purchase button. The event handler calls loadPaymentData() immediately after it interacts with the Google Pay, payment button.
  2. After a Google user grants permission for your site to receive information about the user's selected form of payment and optional contact data, handle the response from the Google Pay API.
  3. Extract the payment token from the paymentData response. If you implement a gateway integration, pass this token to your gateway without any modifications.
    paymentsClient.loadPaymentData(paymentDataRequest).then(function(paymentData){
     
    // if using gateway tokenization, pass this token without modification
      paymentToken
    = paymentData.paymentMethodData.tokenizationData.token;
    }).catch(function(err){
     
    // show error in developer console for debugging
      console
    .error(err);
    });

To improve execution time, prefetch your website's payment configuration from the Google Pay API before you call loadPaymentData(). See the following example:

paymentsClient.prefetchPaymentData(paymentDataRequest);

Authorize Payments is used to start the payment process and acknowledge a payment's authorization status. To set up Authorize Payments, take the following steps:

  1. Register an onPaymentAuthorized() callback in PaymentOptions.
  2. Call the loadPaymentData() function with the PAYMENT_AUTHORIZATION callback intent.
  3. Implement onPaymentAuthorized().

The following code sample shows how to register onPaymentAuthorized callbacks:

{
  environment
: "TEST",
  merchantInfo
: {
    merchantName
: "Example Merchant",
    merchantId
: "12345678901234567890"
 
},
  paymentDataCallbacks
: {
    onPaymentAuthorized
: onPaymentAuthorized
 
}
}

The following code sample shows how to initialize the payment sheet with Authorize Payments:

const paymentDataRequest = Object.assign({}, baseRequest);
paymentDataRequest
.allowedPaymentMethods = [cardPaymentMethod];
paymentDataRequest
.transactionInfo = getGoogleTransactionInfo();
paymentDataRequest
.merchantInfo = {
  merchantName
: 'Example Merchant'
  merchantId
: '12345678901234567890',
};

paymentDataRequest
.callbackIntents = ["PAYMENT_AUTHORIZATION"];

The onPaymentAuthorized() callback is invoked with a PaymentData object by Google after a payer approves payment through a user gesture, such as if they click Pay.

The callback returns a Promise<PaymentAuthorizationResult> value. The PaymentAuthorizationResult object has a SUCCESS or ERROR transaction state status. Upon success, the payment sheet is closed successfully. If you encounter an error, the payment sheet renders the error details returned after the payment is processed. The user can change the payment sheet’s payment data and authorize the payment again. See the following code sample:

function onPaymentAuthorized(paymentData) {
 
return new Promise(function(resolve, reject){
   
// handle the response
    processPayment
(paymentData)
   
.then(function() {
      resolve
({transactionState: 'SUCCESS'});
   
})
   
.catch(function() {
      resolve
({
        transactionState
: 'ERROR',
        error
: {
          intent
: 'PAYMENT_AUTHORIZATION',
          message
: 'Insufficient funds',
          reason
: 'PAYMENT_DATA_INVALID'
       
}
     
});
   
});
 
});
}

Dynamic Price Updates allows a merchant to dynamically update shipping options and transaction information based on a chosen shipping address. Additionally, you can dynamically update transaction information based on a chosen shipping option.

To set up Dynamic Price Updates, take the following steps:

  1. Register both the onPaymentAuthorized and onPaymentDataChanged callbacks in PaymentOptions.
  2. Call the loadPaymentData() function with callback intents. For details, see the corresponding example.
  3. Implement onPaymentAuthorized and onPaymentDataChanged.

The following code sample shows that Dynamic Price Updates requires callback functions to be registered in the PaymentsClient paymentOptions object.

{
  environment
: "TEST",
  merchantInfo
: {
    merchantName
: "Example Merchant",
    merchantId
: "12345678901234567890"
 
},
  paymentDataCallbacks
: {
    onPaymentAuthorized
: onPaymentAuthorized,
    onPaymentDataChanged
: onPaymentDataChanged
 
}
}

The following code sample shows how a payment sheet must be initialized with a required shipping address and shipping options configuration:

const paymentDataRequest = Object.assign({}, baseRequest);
paymentDataRequest
.allowedPaymentMethods = [cardPaymentMethod];
paymentDataRequest
.transactionInfo = getGoogleTransactionInfo();
paymentDataRequest
.merchantInfo = {
  merchantId
: '12345678901234567890',
  merchantName
: 'Example Merchant'
};

paymentDataRequest
.callbackIntents = ["SHIPPING_ADDRESS",  "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"];


paymentDataRequest
.shippingAddressRequired = true;
paymentDataRequest
.shippingAddressParameters = getGoogleShippingAddressParameters();
paymentDataRequest
.shippingOptionRequired = true;

The onPaymentDataChanged callback is invoked with an IntermediatePaymentData object, which includes the shipping address and shipping option selected in the payment sheet.

The callback returns a Promise<PaymentDataRequestUpdate>. The PaymentDataRequestUpdate object has new transaction information, shipping options, and a payment data error. This data updates the payment sheet.

Handle any exception cases, such as an unserviceable shipping address or invalid shipping option, directly in the payment sheet. Set up a PaymentDataError object to highlight the reason for the error with an error message to the user. Be sure to include the related intent in the message. For details on how to set up the object and message, see the following code sample:

function onPaymentDataChanged(intermediatePaymentData) {
 
return new Promise(function(resolve, reject) {

    let shippingAddress
= intermediatePaymentData.shippingAddress;
    let shippingOptionData
= intermediatePaymentData.shippingOptionData;
    let paymentDataRequestUpdate
= {};

   
if (intermediatePaymentData.callbackTrigger == "INITIALIZE" || intermediatePaymentData.callbackTrigger == "SHIPPING_ADDRESS") {
     
if(shippingAddress.administrativeArea == "NJ")  {
        paymentDataRequestUpdate
.error = getGoogleUnserviceableAddressError();
     
}
     
else {
        paymentDataRequestUpdate
.newShippingOptionParameters = getGoogleDefaultShippingOptions();
        let selectedShippingOptionId
= paymentDataRequestUpdate.newShippingOptionParameters.defaultSelectedOptionId;
        paymentDataRequestUpdate
.newTransactionInfo = calculateNewTransactionInfo(selectedShippingOptionId);
     
}
   
}
   
else if (intermediatePaymentData.callbackTrigger == "SHIPPING_OPTION") {
      paymentDataRequestUpdate
.newTransactionInfo = calculateNewTransactionInfo(shippingOptionData.id);
   
}

    resolve
(paymentDataRequestUpdate);
 
});
}

Promo Codes allow a merchant to dynamically update shipping options and transaction information based on a provided promotional code.

To set up Promo Codes, take the following steps:

  1. Register the onPaymentDataChanged callbacks in PaymentOptions.
  2. Call the loadPaymentData() function with callback intents. For details, see the corresponding example.
  3. Implement the onPaymentDataChanged callback function.

The following code sample shows that Promo Codes require callback functions to be registered in the PaymentsClient paymentOptions object.

{
  environment
: "TEST",
  merchantInfo
: {
    merchantName
: "Example Merchant",
    merchantId
: "12345678901234567890"
 
},
  paymentDataCallbacks
: {
    onPaymentDataChanged
: onPaymentDataChanged
 
}
}

The following code sample shows how a payment sheet must be initialized with an OFFER callback intent:

const paymentDataRequest = Object.assign({}, baseRequest);
paymentDataRequest
.allowedPaymentMethods = [cardPaymentMethod];
paymentDataRequest
.transactionInfo = getGoogleTransactionInfo();
paymentDataRequest
.merchantInfo = {
  merchantId
: '12345678901234567890',
  merchantName
: 'Example Merchant'
};

paymentDataRequest
.callbackIntents = ["OFFER"];

The onPaymentDataChanged callback is invoked with an IntermediatePaymentData object, which includes the shipping address and shipping option selected in the payment sheet.

The callback must return a Promise<PaymentDataRequestUpdate>. The PaymentDataRequestUpdate object has new transaction information, shipping options, offer data, and a payment data error. This data updates the payment sheet.

Handle any exception cases, such as an invalid promo code, directly in the payment sheet. Set up a PaymentDataError object to highlight the reason for the error with an error message to the user. Be sure to include the related intent in the message. For details on how to set up the object and message, see the following code sample, which references an object (validPromoCodes) containing the promo code values:

function onPaymentDataChanged(intermediatePaymentData) {
 
return new Promise(function(resolve, reject) {

    let redemptionCodes
= [];
    let shippingOptionData
= intermediatePaymentData.shippingOptionData;
    let paymentDataRequestUpdate
= {};
    paymentDataRequestUpdate
.newTransactionInfo = getGoogleTransactionInfo();

   
// ensure that promo codes set is unique
   
if(typeof intermediatePaymentData.offerData != 'undefined') {
     
// convert to set then back to array
      redemptionCodes
= Array.from(
       
new Set(intermediatePaymentData.offerData.redemptionCodes)
     
);
   
}

   
// OPTIONAL: ensure that the newest promo code is the only one applied
   
// redemptionCodes = new Array(redemptionCodes[redemptionCodes.length -1]);

   
// validate promo codes and add descriptions to payment sheet
   
if (intermediatePaymentData.callbackTrigger === 'OFFER') {
      paymentDataRequestUpdate
.newOfferInfo = {};
      paymentDataRequestUpdate
.newOfferInfo.offers = [];
     
for (redemptionCode of redemptionCodes) {
       
if (validPromoCodes[redemptionCode]) {
          paymentDataRequestUpdate
= validPromoCodes[redemptionCode].function(
            validPromoCodes
[redemptionCode],
            paymentDataRequestUpdate
         
);
       
} else {
          paymentDataRequestUpdate
.error = getGoogleOfferInvalidError(redemptionCode);
       
}
     
}
   
}

The example code blocks in this section show a complete end-to-end example of the Google Pay API JavaScript library tutorial, Authorize Payments, Dynamic Price Updates, and Promo Codes.

<div id="container"></div>

<script>
/**
 * Define the version of the Google Pay API referenced when creating your
 * configuration
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|apiVersion in PaymentDataRequest}
 */

const baseRequest = {
  apiVersion
: 2,
  apiVersionMinor
: 0
};

/**
 * Card networks supported by your site and your gateway
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
 * @todo confirm card networks supported by your site and gateway
 */

const allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "MIR", "VISA"];

/**
 * Card authentication methods supported by your site and your gateway
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
 * @todo confirm your processor supports Android device tokens for your
 * supported card networks
 */

const allowedCardAuthMethods = ["PAN_ONLY", "CRYPTOGRAM_3DS"];

/**
 * Identify your gateway and your site's gateway merchant identifier
 *
 * The Google Pay API response will return an encrypted payment method capable
 * of being charged by a supported gateway after payer authorization
 *
 * @todo check with your gateway on the parameters to pass
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#gateway|PaymentMethodTokenizationSpecification}
 */

const tokenizationSpecification = {
  type
: 'PAYMENT_GATEWAY',
  parameters
: {
   
'gateway': 'example',
   
'gatewayMerchantId': 'exampleGatewayMerchantId'
 
}
};

/**
 * Describe your site's support for the CARD payment method and its required
 * fields
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
 */

const baseCardPaymentMethod = {
  type
: 'CARD',
  parameters
: {
    allowedAuthMethods
: allowedCardAuthMethods,
    allowedCardNetworks
: allowedCardNetworks
 
}
};

/**
 * Describe your site's support for the CARD payment method including optional
 * fields
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#CardParameters|CardParameters}
 */

const cardPaymentMethod = Object.assign(
 
{},
  baseCardPaymentMethod
,
 
{
    tokenizationSpecification
: tokenizationSpecification
 
}
);

/**
 * An initialized google.payments.api.PaymentsClient object or null if not yet set
 *
 * @see {@link getGooglePaymentsClient}
 */

let paymentsClient
= null;

/**
 * Configure your site's support for payment methods supported by the Google Pay
 * API.
 *
 * Each member of allowedPaymentMethods should contain only the required fields,
 * allowing reuse of this base request when determining a viewer's ability
 * to pay and later requesting a supported payment method
 *
 * @returns {object} Google Pay API version, payment methods supported by the site
 */

function getGoogleIsReadyToPayRequest() {
 
return Object.assign(
     
{},
      baseRequest
,
     
{
        allowedPaymentMethods
: [baseCardPaymentMethod]
     
}
 
);
}

/**
 * Configure support for the Google Pay API
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#PaymentDataRequest|PaymentDataRequest}
 * @returns {object} PaymentDataRequest fields
 */

function getGooglePaymentDataRequest() {
 
const paymentDataRequest = Object.assign({}, baseRequest);
  paymentDataRequest
.allowedPaymentMethods = [cardPaymentMethod];
  paymentDataRequest
.transactionInfo = getGoogleTransactionInfo();
  paymentDataRequest
.merchantInfo = {
   
// @todo a merchant ID is available for a production environment after approval by Google
   
// See {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist|Integration checklist}
   
// merchantId: '12345678901234567890',
    merchantName
: 'Example Merchant'
 
};
 
return paymentDataRequest;
}

/**
 * Return an active PaymentsClient or initialize
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/client#PaymentsClient|PaymentsClient constructor}
 * @returns {google.payments.api.PaymentsClient} Google Pay API client
 */

function getGooglePaymentsClient() {
 
if ( paymentsClient === null ) {
    paymentsClient
= new google.payments.api.PaymentsClient({environment: 'TEST'});
 
}
 
return paymentsClient;
}

/**
 * Initialize Google PaymentsClient after Google-hosted JavaScript has loaded
 *
 * Display a Google Pay payment button after confirmation of the viewer's
 * ability to pay.
 */

function onGooglePayLoaded() {
 
const paymentsClient = getGooglePaymentsClient();
  paymentsClient
.isReadyToPay(getGoogleIsReadyToPayRequest())
     
.then(function(response) {
       
if (response.result) {
          addGooglePayButton
();
         
// @todo prefetch payment data to improve performance after confirming site functionality
         
// prefetchGooglePaymentData();
       
}
     
})
     
.catch(function(err) {
       
// show error in developer console for debugging
        console
.error(err);
     
});
}

/**
 * Add a Google Pay purchase button alongside an existing checkout button
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#ButtonOptions|Button options}
 * @see {@link https://developers.google.com/pay/api/web/guides/brand-guidelines|Google Pay brand guidelines}
 */

function addGooglePayButton() {
 
const paymentsClient = getGooglePaymentsClient();
 
const button =
      paymentsClient
.createButton({
        onClick
: onGooglePaymentButtonClicked,
        allowedPaymentMethods
: [baseCardPaymentMethod]
     
});
  document
.getElementById('container').appendChild(button);
}

/**
 * Provide Google Pay API with a payment amount, currency, and amount status
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo|TransactionInfo}
 * @returns {object} transaction info, suitable for use as transactionInfo property of PaymentDataRequest
 */

function getGoogleTransactionInfo() {
 
return {
    countryCode
: 'US',
    currencyCode
: 'USD',
    totalPriceStatus
: 'FINAL',
   
// set to cart total
    totalPrice
: '1.00'
 
};
}

/**
 * Prefetch payment data to improve performance
 *
 * @see {@link https://developers.google.com/pay/api/web/reference/client#prefetchPaymentData|prefetchPaymentData()}
 */

function prefetchGooglePaymentData() {
 
const paymentDataRequest = getGooglePaymentDataRequest();
 
// transactionInfo must be set but does not affect cache
  paymentDataRequest
.transactionInfo = {
    totalPriceStatus
: 'NOT_CURRENTLY_KNOWN',
    currencyCode
: 'USD'
 
};
 
const paymentsClient = getGooglePaymentsClient();
  paymentsClient
.prefetchPaymentData(paymentDataRequest);
}

/**
 * Show Google Pay payment sheet when Google Pay payment button is clicked
 */

function onGooglePaymentButtonClicked() {
 
const paymentDataRequest = getGooglePaymentDataRequest();
  paymentDataRequest
.transactionInfo = getGoogleTransactionInfo();

 
const paymentsClient = getGooglePaymentsClient();
  paymentsClient
.loadPaymentData(paymentDataRequest)
     
.then(function(paymentData) {
       
// handle the response
        processPayment
(paymentData);
     
})
     
.catch(function(err) {
       
// show error in developer console for debugging
        console
.error(err);
     
});
}
/**
 * Process payment data returned by the Google Pay API
 *
 * @param {object} paymentData response from Google Pay API after user approves payment
 * @see {@link https://developers.google.com/pay/api/web/reference/response-objects#PaymentData|PaymentData object reference}
 */

function processPayment(paymentData) {
 
// show returned data in developer console for debugging
    console
.log(paymentData);
 
// @todo pass payment token to your gateway to process payment
  paymentToken
= paymentData.paymentMethodData.tokenizationData.token;
}
</script>
<script async
 
src="https://pay.google.com/gp/p/js/pay.js"
 
onload="onGooglePayLoaded()"></script>

No comments:

Post a Comment

PeopleCode to retrieve Google map between two addresses

  PeopleCode Example: /* Define constants for the API request */ Local string &origin = "123 Main St, Anytown, USA";   /* ...