Accept cards with Google Pay™ Coming soon

This feature is coming soon! The information below describes a feature that is not yet available in production. The API details are subject to change.
Moov allows you to accept card payments with Google Pay. This step by step guide covers how you can start accepting Google Pay on the web using the open standard Payment Request API.

In addition to being a fast and easy way to accept payments, Google Pay offers strong privacy and security. In this guide, we'll direct you to Google's guidelines, and bring you through a step by step process of adding a functional Google Pay button.

Prerequisites

Before getting started, make sure your website follows Google's guidelines, and that your server is set up accordingly.

Add Google Pay JavaScript library

Include the Google Pay JavaScript library:

<!-- Load the Google Pay JavaScript library -->
<script
  async src="https://pay.google.com/gp/p/js/pay.js"
  onload="onGooglePayLoaded()">
</script>

Add Google Pay button

Add a div element to your webpage and use the Google Pay documentation to customize the button type, and to see best practices on using CSS.

Here's sample code for adding a simple black Buy with Google Pay button, using the default size and corner radius:

<div id="gpay-button-container"></div>

Set up Google Pay PaymentsClient

After adding the button, you can set up the PaymentsClient. Start with a base configuration and modify it to your needs:

// Environment: TEST or PRODUCTION
// Configure object for a production environment once your implementation testing is completed. environment: 'PRODUCTION'  
const googlePayEnv = 'TEST';

// Moov Account ID
const accountID = 'payer-uuid';

// Bearer token
const bearerToken = 'my token';

// This is the base configuration for all Google Pay payment data requests.
// -- Update `tokenizationSpecification.parameters.gatewayMerchantId` with your own value in the Moov Dashboard.
// -- Update the `merchantInfo.merchantId` and `merchantInfo.merchantName` properties with your own values from Google.
// Moov only supports the following Auth Methods: 'PAN_ONLY' and 'CRYPTOGRAM_3DS' --> Moov does NOT support 3DS from a third-party provider
// Moov only supports the following Card Networks: 'AMEX', 'DISCOVER', 'MASTERCARD' and 'VISA'
const googlePayBaseConfiguration = {
  apiVersion: 2,
  apiVersionMinor: 0,
  allowedPaymentMethods: [
    {
      type: 'CARD',
      parameters: {
        allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
        allowedCardNetworks: ['AMEX', 'DISCOVER', 'MASTERCARD', 'VISA'],
        billingAddressRequired: true,
        billingAddressParameters: {
          format: 'FULL',
        },
      },
      tokenizationSpecification: {
        type: 'PAYMENT_GATEWAY',
        parameters: {
          'gateway': 'moov',
          'gatewayMerchantId': 'a2c4e6g8-i9k1-m3o5-q7s9u1w3y5a7c9e1g'
        }
      },
    },
  ],
  merchantInfo: {
    merchantId: '01234567890123456789',
    merchantName: 'Example Merchant',
  },
  emailRequired: true,
};

Now create the PaymentsClient:

let googlePayClient = null;

// Create a new PaymentsClient instance.
function getGooglePaymentsClient() {
  if (googlePayClient === null) {
    googlePayClient = new google.payments.api.PaymentsClient({
      environment: googlePayEnv,
    });
  }

  return googlePayClient;
}

Set up event handlers for page load and Google Pay button click

Create an event handler to show the button after the scripts on the page load:

function onGooglePayLoaded() {
  paymentRequest = Object.assign({}, googlePayBaseConfiguration);
  
  getGooglePaymentsClient()
    .isReadyToPay(paymentRequest)
    .then(function(res) {
      if (res.result) {
        button = getGooglePaymentsClient().createButton({
          onClick: onGooglePayButtonClick
        });
        document.getElementById('gpay-button-container').appendChild(button);
      } else {
        console.log("Google Pay is not ready for this user.");
      }
    })
    .catch(console.error);
}

When the Google Pay button is clicked, update the transaction info:

// Moov only supports USD for the United States
function onGooglePayButtonClick() {
  paymentRequest.transactionInfo = {
    totalPriceStatus: 'FINAL',
    totalPrice: '12.34',
    currencyCode: 'USD',
    countryCode: 'US',
  };
  googlePayClient.loadPaymentData(paymentRequest).then(onGooglePayPaymentLoaded).catch(console.error);
}

Create payment method

Once the customer selects their desired payment method and clicks continue, the client will receive the Google Pay token. Send it to the Moov Platform to get a payment method:

// When the token is received from Google Pay, pass the token to the Moov Platform to receive a payment method
function onGooglePayPaymentLoaded(paymentResponse) {
  let url = 'https://api.moov.io/accounts/' + accountID;
  let paymentMethodURL = url + '/google-pay/tokens';

  // Create Moov payment method
  const moovCreatePaymentMethodResponse = fetch(paymentMethodURL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer ' + bearerToken,
    },
    body: JSON.stringify({ paymentMethodData: paymentResponse.paymentMethodData })
  }).then(response => {
    response.json();
    });
  }).catch(console.error);
}

Create Moov transfer

Now that you have a Moov payment method associated to the Google Pay token, create a transfer:

// Create Moov transfer
let transferURL = url + '/transfers';
const moovTransferResponse = fetch(transferURL, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + bearerToken,
    'X-Wait-For': 'rail-response'
  },
  body: JSON.stringify({ paymentMethodID: moovCreatePaymentMethodResponse.paymentMethodID, amount: 12.34 })
}).then(response => {
  response.json();
});

Use the X-Wait-For header on the transfer request to receive a synchronous response from the card network

let status;
if (moovTransferResponse.source.cardDetails.status === 'confirmed') {
  status = 'success';
} else {
  status = 'fail';
}

Seeing it all together

Here's a sample that synthesizes the steps above all in one place:

<div id="gpay-button-container"></div>
<script type="text/javascript">
  //=============================================================================
  // Configuration
  //=============================================================================

  // Environment: TEST or PRODUCTION
  // Configure object for a production environment once your implementation testing is completed. environment: 'PRODUCTION'  
  const googlePayEnv = 'TEST';

  // Moov Account ID
  const accountID = 'payer-uuid';

  // Bearer token
  const bearerToken = 'my token';

  // This is the base configuration for all Google Pay payment data requests.
  // -- Update `tokenizationSpecification.parameters.gatewayMerchantId` with your own value from Moov.
  // -- Update the `merchantId` and `merchantName` properties with your own values from Google.
  const googlePayBaseConfiguration = {
    apiVersion: 2,
    apiVersionMinor: 0,
    allowedPaymentMethods: [
      {
        type: 'CARD',
        parameters: {
          allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
          allowedCardNetworks: ['AMEX', 'DISCOVER', 'INTERAC', 'JCB', 'MASTERCARD', 'VISA'],
          billingAddressRequired: true,
          billingAddressParameters: {
            format: 'FULL',
          },
        },
        tokenizationSpecification: {
          type: 'PAYMENT_GATEWAY',
          parameters: {
            'gateway': 'moov',
            'gatewayMerchantId': 'a2c4e6g8-i9k1-m3o5-q7s9u1w3y5a7c9e1g'
          }
        },
      },
    ],
    merchantInfo: {
      merchantId: '01234567890123456789',
      merchantName: 'Example Merchant',
    },
    emailRequired: true,
  };

  // Prevent accidental edits to the base configuration
  Object.freeze(googlePayBaseConfiguration);


  //========================
  // Google Payments Client
  //========================
  let googlePayClient = null;

  // Create a new PaymentsClient instance.
  function getGooglePaymentsClient() {
    if (googlePayClient === null) {
      googlePayClient = new google.payments.api.PaymentsClient({
        environment: googlePayEnv,
      });
    }

    return googlePayClient;
  }


  //=========
  // Helpers
  //=========
  let paymentRequest = null;

  //================
  // Event Handlers
  //================

  // Invoked when the pay.js script has completed loading. 
  // The isReadyToPay() method determines if the Google Pay button should be shown.
  //   If the customer is ready to pay (they have a form of payment stored in their Google Wallet) then the Google Pay button is shown.
  function onGooglePayLoaded() {
    paymentRequest = Object.assign({}, googlePayBaseConfiguration);
    
    getGooglePaymentsClient()
      .isReadyToPay(paymentRequest)
      .then(function(res) {
        if (res.result) {
          button = getGooglePaymentsClient().createButton({
            onClick: onGooglePayButtonClick
          });
          document.getElementById('gpay-button-container').appendChild(button);
        } else {
          console.log("Google Pay is not ready for this user.");
        }
      })
      .catch(console.error);
  }

  // Update totalPrice to the intended amount of the transaction
  function onGooglePayButtonClick() {
    paymentRequest.transactionInfo = {
      totalPriceStatus: 'FINAL',
      totalPrice: '12.34',
      currencyCode: 'USD',
      countryCode: 'US',
    };
    googlePayClient.loadPaymentData(paymentRequest).then(onGooglePayPaymentLoaded).catch(console.error);
  }

  // When the token is received from Google Pay, pass the token to the Moov platform to receive a payment method
  function onGooglePayPaymentLoaded(paymentResponse) {
    let url = 'https://api.moov.io/accounts/' + accountID;
    let paymentMethodURL = url + '/google-pay/tokens';

    // Create Moov payment method
    const moovCreatePaymentMethodResponse = fetch(paymentMethodURL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + bearerToken,
      },
      body: JSON.stringify({ paymentMethodData: paymentResponse.paymentMethodData })
    }).then(response => {
      response.json();

      // Create Moov transfer
      let transferURL = url + '/transfers';
      const moovTransferResponse = fetch(transferURL, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': 'Bearer ' + bearerToken,
          'X-Wait-For': 'rail-response'
        },
        body: JSON.stringify({ paymentMethodID: moovCreatePaymentMethodResponse.paymentMethodID, amount: 12.34 })
      }).then(response => {
        response.json();
        let status;
        if (moovTransferResponse.source.cardDetails.status === 'confirmed') {
          status = 'success';
        } else {
          status = 'fail';
        }

        // Completes the payment request process and closes the payment sheet
        resolve(status);
      });
    }).catch(console.error);
  }
</script>

<!-- Load the Google Pay JavaScript library -->
<script
  async src="https://pay.google.com/gp/p/js/pay.js"
  onload="onGooglePayLoaded()">
</script>

For more information, refer to Google’s documentation.

Summary Beta