Google Pay

Google Pay is a trademark of Google LLC.

Overview

MoneyHash's Google Pay integration enables you to:

  • Accept payments using customers' saved cards in Google Pay
  • Provide a seamless, native payment experience

Prerequisites

Before implementing Google Pay, ensure you have:

  • A MoneyHash account with Google Pay enabled
  • Your MoneyHash Account ID (used as gatewayMerchantId)
  • A registered Google Pay merchant ID
  • HTTPS enabled on your domain (required by Google Pay™)

Branding

You must follow Google’s brand guidelines when referencing Google Pay™:

  • Ensure the first mention of Google Pay™ on every page includes the ™.
  • Use only official Google Pay buttons and assets:
  • Do not alter button colors, aspect ratio, or minimum size. Use dark or light button versions depending on your UI.
  • Place the Google Pay button equal in size and prominence to other payment options.

Quick Start (For Developers)

// 1. Get config from MoneyHash
const { expressMethods } = await moneyHash.getMethods({ currency: '<currency'>, amount: '<amount>');
const googlePayMethod = expressPayMethods.find(method => method.id === 'GOOGLE_PAY');
const googlePayNativeData = googlePayMethod?.nativePayData;

// 2. Configure Google Pay button
button.paymentRequest = {
  apiVersion: 2,
  allowedPaymentMethods: [{
    type: "CARD",
    parameters: {
      allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
      allowedCardNetworks: ["VISA", "MASTERCARD"]
    },
    tokenizationSpecification: {
      type: "PAYMENT_GATEWAY",
      parameters: {
        gateway: "moneyhash",
        gatewayMerchantId: googlePayNativeData.gateway_merchant_id
      }
    }
  }],
  merchantInfo: {
    merchantId: googlePayNativeData.merchant_id,
    merchantName: googlePayNativeData.merchant_name,
  },
  transactionInfo: {
    totalPrice: googlePayNativeData.amount,
    currencyCode: googlePayNativeData.currency_code,
    countryCode: googlePayNativeData.country_code
  }
};

// 3. Handle token from Google Pay
button.addEventListener("loadpaymentdata", async (event) => {
  const { paymentMethodData, email } = event.detail;
  const paymentToken = paymentMethodData.tokenizationData.token;
  const googlePayReceipt = {
    receipt: paymentToken,
    receiptBillingData: {
      email,
    },
  };
  
  await moneyHash.proceedWith({
    type: "method",
    id: "GOOGLE_PAY",
    intentId,
  });

  // Submit the Google Pay payment token
  const intentDetails = await moneyHash.submitPaymentReceipt({
    intentId,
    nativeReceiptData: googlePayReceipt,
  });

  console.log("Payment successful:", intentDetails);
});

Tokenization Specification & Integration Options

MoneyHash provides a tokenizationSpecification that allows merchants to process Google Pay™ transactions either via their own custom integration (Web / Android) or through MoneyHash’s SDK and hosted components.

{
  "type": "PAYMENT_GATEWAY",
  "parameters": {
    "gateway": "moneyhash",
    "gatewayMerchantId": "<your_moneyhash_account_id>"
  }
}

We support two options for integration:

Option #1: Custom Integration Using SDKs


Option #2: MoneyHash Hosted Page (Intent Embed)

If you prefer a faster setup, MoneyHash offers Hosted Payment Intent that can be embedded into Checkout Page.

  • Enable Google Pay in MoneyHash Dashboard.
  • Configure networks, auth methods, and country.
  • The Embed handles most of the setup automatically.
  • Token submission will be handled by Intent.

Dashboard Configuration

Below is an example of configuring Google Pay inside the MoneyHash Dashboard:


  • Allowed card networks – select supported brands (Visa, Mastercard, Amex, Discover, JCB, Mada, etc.).
  • Allowed auth methods – PAN_ONLY, CRYPTOGRAM_3DS.
  • Google Pay country – country where payments will be processed.
  • Underlying pay-in method – link to the correct provider.

Implementation Steps

Step 1: Install Google Pay SDK

Choose the implementation that best fits your project:

npm install @google-pay/button-element
npm install @google-pay/button-react
npm install @google-pay/button-angular
<script src="https://pay.google.com/gp/p/js/pay.js"></script>

Step 2: Get Available Payment Methods

First, retrieve the Google Pay configuration from MoneyHash:

// Get available payment methods including Google Pay data
const { expressMethods } = await moneyHash.getMethods({ currency: '<currency'>, amount: '<amount>');
const googlePayMethod = expressPayMethods.find(method => method.id === 'GOOGLE_PAY');
const googlePayNativeData = googlePayMethod?.nativePayData;
 

The googlePayNativeData object contains all the configuration you need:

  • gateway: Always "moneyhash"
  • gateway_merchant_id: Your MoneyHash Account ID
  • merchant_id: Google Pay merchant ID
  • merchant_name: Your business name
  • amount: Payment amount
  • currency_code: Currency code
  • country_code: Country code
{
    "currency_code": "<currency>",
    "country_code": "..",
    "amount": "<amount>",
    "gateway": "moneyhash",
    "gateway_merchant_id": "...",
    "merchant_id": "....",
    "merchant_name": "...",
    "method_id": "...",
    "allowed_card_networks": [
        "AMEX",
        "DISCOVER",
        "INTERAC",
        "JCB",
        "MASTERCARD",
        "VISA"
    ],
    "allowed_card_auth_methods": [
        "PAN_ONLY",
        "CRYPTOGRAM_3DS"
    ]
}

Step 3: Configure Payment Request

import "@google-pay/button-element";

const button = document.querySelector("google-pay-button");

button.paymentRequest = {
  apiVersion: 2,
  apiVersionMinor: 0,
  allowedPaymentMethods: [
    {
      type: "CARD",
      parameters: {
        allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
        allowedCardNetworks: ["MASTERCARD", "VISA", "AMEX", "DISCOVER", "JCB"],
        billingAddressRequired: true,
      },
      tokenizationSpecification: {
        type: "PAYMENT_GATEWAY",
        parameters: {
          gateway: 'moneyhash',  // MoneyHash gateway identifier
          gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
        },
      },
    },
  ],
  merchantInfo: {
    merchantId: googlePayNativeData.merchant_id,
    merchantName: googlePayNativeData.merchant_name,
  },
  transactionInfo: {
    totalPriceStatus: "FINAL",
    totalPriceLabel: "Total",
    totalPrice: `${googlePayNativeData.amount}`,
    currencyCode: googlePayNativeData.currency_code,
    countryCode: googlePayNativeData.country_code,
  },
  emailRequired: true, // Collect customer email
};
import GooglePayButton from '@google-pay/button-react';

function CheckoutForm() {
  return (
    <GooglePayButton
      environment="TEST" // Use "PRODUCTION" for live transactions
      paymentRequest={{
        apiVersion: 2,
        apiVersionMinor: 0,
        allowedPaymentMethods: [
          {
            type: 'CARD',
            parameters: {
              allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
              allowedCardNetworks: ["MASTERCARD", "VISA", "AMEX", "DISCOVER", "JCB"],
              billingAddressRequired: true,
            },
            tokenizationSpecification: {
              type: 'PAYMENT_GATEWAY',
              parameters: {
                gateway: 'moneyhash',  // MoneyHash gateway identifier
                gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
              },
            },
          },
        ],
        merchantInfo: {
          merchantId: googlePayNativeData.merchant_id,
          merchantName: googlePayNativeData.merchant_name,
        },
        transactionInfo: {
          totalPriceStatus: 'FINAL',
          totalPriceLabel: 'Total',
          totalPrice: `${googlePayNativeData.amount}`,
          currencyCode: googlePayNativeData.currency_code,
          countryCode: googlePayNativeData.country_code,
        },
        emailRequired: true,
      }}
      onLoadPaymentData={handlePaymentData}
      onCancel={handleCancel}
    />
  );
}

Step 4: Handle Payment Data

When a user completes the Google Pay flow, handle the payment data and submit it to MoneyHash:s

button.addEventListener("loadpaymentdata", async (event) => {
  const { paymentMethodData, email } = event.detail;
  const paymentToken = paymentMethodData.tokenizationData.token;
  
  const googlePayReceipt = {
    receipt: paymentToken,
    receiptBillingData: {
      email,
    },
  };

  try {
    // Select Google Pay as the payment method
    await moneyHash.proceedWith({
      type: "method",
      id: "GOOGLE_PAY",
      intentId,
    });

    // Submit the Google Pay payment token
    const intentDetails = await moneyHash.submitPaymentReceipt({
      intentId,
      nativeReceiptData: googlePayReceipt,
    });

    console.log("Payment successful:", intentDetails);
    // Handle successful payment
  } catch (error) {
    console.error("Payment failed:", error);
    // Handle payment failure
  }
});

button.addEventListener("cancel", () => {
  console.log("Google Pay sheet was closed by user");
});
const handlePaymentData = async (paymentRequest) => {
  const { paymentMethodData, email } = paymentRequest;
  const paymentToken = paymentMethodData.tokenizationData.token;
  
  const googlePayReceipt = {
    receipt: paymentToken,
    receiptBillingData: {
      email,
    },
  };

  try {
    await moneyHash.proceedWith({
      type: "method",
      id: "GOOGLE_PAY",
      intentId,
    });

    const intentDetails = await moneyHash.submitPaymentReceipt({
      intentId,
      nativeReceiptData: googlePayReceipt,
    });

    console.log("Payment successful:", intentDetails);
  } catch (error) {
    console.error("Payment failed:", error);
  }
};

const handleCancel = () => {
  console.log("Google Pay sheet was closed by user");
};

Complete Implementation Examples

Web Components Example

<!DOCTYPE html>
<html>
<head>
  <script type="module">
    import "@google-pay/button-element";
  </script>
</head>
<body>
  <google-pay-button environment="TEST"></google-pay-button>

  <script type="module">
    const button = document.querySelector("google-pay-button");
    
    // Configure payment request with MoneyHash parameters
    button.paymentRequest = {
      apiVersion: 2,
      apiVersionMinor: 0,
      allowedPaymentMethods: [
        {
          type: "CARD",
          parameters: {
            allowedAuthMethods: ["PAN_ONLY", "CRYPTOGRAM_3DS"],
            allowedCardNetworks: ["MASTERCARD", "VISA", "AMEX", "DISCOVER", "JCB"],
            billingAddressRequired: true,
          },
          tokenizationSpecification: {
            type: "PAYMENT_GATEWAY",
            parameters: {
              gateway: 'moneyhash',
              gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
            },
          },
        },
      ],
      merchantInfo: {
        merchantId: googlePayNativeData.merchant_id,
        merchantName: googlePayNativeData.merchant_name,
      },
      transactionInfo: {
        totalPriceStatus: "FINAL",
        totalPriceLabel: "Total",
        totalPrice: `${googlePayNativeData.amount}`,
        currencyCode: googlePayNativeData.currency_code,
        countryCode: googlePayNativeData.country_code,
      },
      emailRequired: true,
    };

    // Handle successful payment
    button.addEventListener("loadpaymentdata", async (event) => {
      const { paymentMethodData, email } = event.detail;
      const googlePayReceipt = {
        receipt: paymentMethodData.tokenizationData.token,
        receiptBillingData: { email },
      };

      await moneyHash.proceedWith({
        type: "method",
        id: "GOOGLE_PAY",
        intentId,
      });

      const result = await moneyHash.submitPaymentReceipt({
        intentId,
        nativeReceiptData: googlePayReceipt,
      });
      
      console.log("Payment completed:", result);
    });

    button.addEventListener("cancel", () => {
      console.log("Google Pay cancelled");
    });
  </script>
</body>
</html>
import React from 'react';
import GooglePayButton from '@google-pay/button-react';

function GooglePayCheckout({ googlePayNativeData, intentId, moneyHash }) {
  const handlePaymentSuccess = async (paymentRequest) => {
    const { paymentMethodData, email } = paymentRequest;
    
    try {
      const googlePayReceipt = {
        receipt: paymentMethodData.tokenizationData.token,
        receiptBillingData: { email },
      };

      await moneyHash.proceedWith({
        type: "method",
        id: "GOOGLE_PAY",
        intentId,
      });

      const result = await moneyHash.submitPaymentReceipt({
        intentId,
        nativeReceiptData: googlePayReceipt,
      });
      
      // Handle successful payment
      console.log("Payment successful:", result);
      
    } catch (error) {
      console.error("Payment failed:", error);
      // Handle error
    }
  };

  return (
    <GooglePayButton
      environment="TEST"
      paymentRequest={{
        apiVersion: 2,
        apiVersionMinor: 0,
        allowedPaymentMethods: [
          {
            type: 'CARD',
            parameters: {
              allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
              allowedCardNetworks: ["MASTERCARD", "VISA", "AMEX", "DISCOVER", "JCB"],
              billingAddressRequired: true,
            },
            tokenizationSpecification: {
              type: 'PAYMENT_GATEWAY',
              parameters: {
                gateway: 'moneyhash',
                gatewayMerchantId: googlePayNativeData.gateway_merchant_id,
              },
            },
          },
        ],
        merchantInfo: {
          merchantId: googlePayNativeData.merchant_id,
          merchantName: googlePayNativeData.merchant_name,
        },
        transactionInfo: {
          totalPriceStatus: 'FINAL',
          totalPriceLabel: 'Total',
          totalPrice: `${googlePayNativeData.amount}`,
          currencyCode: googlePayNativeData.currency_code,
          countryCode: googlePayNativeData.country_code,
        },
        emailRequired: true,
      }}
      onLoadPaymentData={handlePaymentSuccess}
      onCancel={() => console.log('Google Pay cancelled')}
    />
  );
}

export default GooglePayCheckout;

Implementation notes:

  • If you support 3DS for cards, you must define if its for PAN_ONLY, CRYPTOGRAM_3DS.

Configuration: This can be configured directly in the MoneyHash Dashboard (see “Google Pay allowed auth methods”).

  • Tokenization parameters
    You must define the required values in the tokenizationSpecification.
    Configuration: Values are handled automatically from the SDK response returned by MoneyHash (gateway: 'moneyhash', gatewayMerchantId: <account_id>). No manual setup is required in the dashboard.

  • Card networks
    List supported networks (Visa, Mastercard, Amex, Discover, JCB, Mada, etc.). See allowedCardNetworks.
    Configuration: Select supported networks directly in the MoneyHash Dashboard (see “Google Pay allowed card networks”).

  • Billing address requirements
    Specify if billing address must be submitted. See BillingAddressParameters.
    Configuration: MoneyHash requires collecting the email as part of the flow. Additional billing details (like address fields) are fully controlled and collected by the merchant in their checkout form, if needed.

  • Encrypted data submission
    Merchants must send the Google Pay encrypted token to MoneyHash.
    Configuration: This is done by submitting the token through the API:

    await moneyHash.submitPaymentReceipt({
      intentId,
      nativeReceiptData: googlePayReceipt,
    });
    
  • Configuration auth method, network


Testing

Test Environment

  • Use environment="TEST" in your Google Pay configuration
  • Use Google's test card numbers for testing
  • Ensure your domain is registered in Google Pay Console for testing

Test Cards

Google Pay provides test cards for different scenarios:

  • Visa: 4111111111111111
  • Mastercard: 5555555555554444
  • American Express: 378282246310005

Error Handling

Implement proper error handling for common scenarios:

try {
  await moneyHash.proceedWith({
    type: "method",
    id: "GOOGLE_PAY",
    intentId,
  });

  const result = await moneyHash.submitPaymentReceipt({
    intentId,
    nativeReceiptData: googlePayReceipt,
  });
  
} catch (error) {
  switch (error.code) {
    case 'PAYMENT_METHOD_NOT_AVAILABLE':
      // Handle when Google Pay is not available</i>
      break;
    case 'PAYMENT_CANCELLED':
      // Handle when user cancels payment</i>
      break;
    case 'PAYMENT_FAILED':
      // Handle payment processing failures</i>
      break;
    default:
      // Handle other errors</i>
      console.error('Payment error:', error);
  }
}

Best Practices

  1. Always use HTTPS - Google Pay requires secure connections
  2. Validate on server - Always validate payments server-side
  3. Handle errors gracefully - Provide clear feedback to users
  4. Test thoroughly - Use Google's test environment before going live
  5. Monitor transactions - Set up proper logging and monitoring
  6. Update regularly - Keep Google Pay SDK updated

Security Considerations

  • Never store Google Pay tokens - process them immediately
  • Validate all payment data server-side
  • Use proper CSP headers if using JavaScript API
  • Implement proper session management
  • Monitor for suspicious transaction patterns

Going Live

Before deploying to production:

  1. Switch environment to "PRODUCTION"
  2. Update your domain registration in Google Pay Console
  3. Test with real payment methods in a secure environment
  4. Ensure your MoneyHash account is configured for production
  5. Set up monitoring and alerting

API Reference

MoneyHash Methods

getAvailableMethods(intentId)

Retrieves available payment methods including Google Pay configuration.

proceedWith(options)

Selects Google Pay as the payment method for the intent.

submitPaymentReceipt(data)

Submits the Google Pay token and processes the payment.

Google Pay Native Data Structure

{
  gateway: 'moneyhash',
  gateway_merchant_id: 'your_moneyhash_account_id',
  merchant_id: 'google_pay_merchant_id',
  merchant_name: 'Your Business Name',
  amount: 10.00,
  currency_code: 'USD',
  country_code: 'US'
}

Support

For additional help with Google Pay integration: