Google Pay

SDK

Last updated: Jul 30th, 4:03pm

Overview

This integration enables merchants to accept Google Pay payments through PayPal's infrastructure, combining Google Pay's streamlined UX with PayPal's robust payment processing. The implementation uses PayPal's v6 Web SDK to create a seamless checkout experience.

PayPal Developer Account Setup

1. Create PayPal Developer Account

2. Enable Google Pay in Sandbox

⚠️ Critical Step: Google Pay must be explicitly enabled in your PayPal sandbox account before integration.

Follow the PayPal Google Pay setup documentation to configure your sandbox account.



1. HTML foundation

1. HTML foundation

    1<!DOCTYPE html>
    2<html lang="en">
    3<head>
    4 <meta charset="UTF-8">
    5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6 <title>Google Pay Integration - PayPal</title>
    7</head>
    8<body>
    9 <div class="checkout-container">
    10 <h1>Secure Checkout</h1>
    11 <div id="googlepay-button-container"></div>
    12 </div>
    13
    14 <!-- Load Google Pay SDK first -->
    15 <script src="https://pay.google.com/gp/p/js/pay.js"></script>
    16
    17 <!-- Load PayPal SDK with onload callback -->
    18 <script
    19 async
    20 src="https://www.sandbox.paypal.com/web-sdk/v6/core"
    21 onload="initializePayPalSDK()">
    22 </script>
    23
    24 <script src="app.js"></script>
    25</body>
    26</html>

    2. PayPal SDK Initialization

    2. PayPal SDK Initialization

      1async function initializePayPalSDK() {
      2 try {
      3 // Obtain secure client token from your server
      4 const clientToken = await fetchClientToken();
      5
      6 // Create PayPal SDK instance with Google Pay support
      7 const paypalSDK = await window.paypal.createInstance({
      8 clientToken: clientToken,
      9 components: ["googlepay-payments"],
      10 pageType: "checkout"
      11 });
      12
      13 await setupGooglePayButton(paypalSDK);
      14 } catch (error) {
      15 console.error("PayPal SDK initialization failed:", error);
      16 handleInitializationError(error);
      17 }
      18}

      3. Google Pay Button Configuration

      3. Google Pay Button Configuration

        1async function setupGooglePayButton(paypalSDK) {
        2 // Create Google Pay session
        3 const googlePaySession = paypalSDK.createGooglePayOneTimePaymentSession();
        4 const purchaseAmount = "25.00"; // Your dynamic amount
        5
        6 try {
        7 // Initialize Google Pay client
        8 const googlePayClient = new google.payments.api.PaymentsClient({
        9 environment: "TEST", // Change to "PRODUCTION" for live
        10 paymentDataCallbacks: {
        11 onPaymentAuthorized: (paymentData) =>
        12 handlePaymentAuthorization(purchaseAmount, paymentData, googlePaySession)
        13 }
        14 });
        15
        16 // Get PayPal-generated Google Pay configuration
        17 const googlePayConfig = await googlePaySession.getGooglePayConfig();
        18
        19 // Verify Google Pay availability
        20 const readyToPayResponse = await googlePayClient.isReadyToPay({
        21 allowedPaymentMethods: googlePayConfig.allowedPaymentMethods,
        22 apiVersion: googlePayConfig.apiVersion,
        23 apiVersionMinor: googlePayConfig.apiVersionMinor
        24 });
        25
        26 if (readyToPayResponse.result) {
        27 renderGooglePayButton(googlePayClient, googlePayConfig, purchaseAmount);
        28 } else {
        29 showAlternativePaymentMethods();
        30 }
        31 } catch (error) {
        32 console.error("Google Pay setup failed:", error);
        33 handleGooglePayError(error);
        34 }
        35}

        4. Google Pay Button Rendering

        4. Google Pay Button Rendering

          1function renderGooglePayButton(googlePayClient, googlePayConfig, purchaseAmount) {
          2 const googlePayButton = googlePayClient.createButton({
          3 onClick: () => initiateGooglePayFlow(googlePayClient, googlePayConfig, purchaseAmount),
          4 allowedPaymentMethods: googlePayConfig.allowedPaymentMethods,
          5 buttonColor: 'black',
          6 buttonType: 'buy',
          7 buttonSizeMode: 'fill'
          8 });
          9
          10 const buttonContainer = document.getElementById("googlepay-button-container");
          11 buttonContainer.appendChild(googlePayButton);
          12}

          5. Payment Flow Initiation

          Payment Flow Initiation

            1async function initiateGooglePayFlow(googlePayClient, googlePayConfig, purchaseAmount) {
            2 try {
            3 const paymentDataRequest = buildPaymentDataRequest(purchaseAmount, googlePayConfig);
            4 await googlePayClient.loadPaymentData(paymentDataRequest);
            5 } catch (error) {
            6 if (error.statusCode === 'CANCELED') {
            7 console.log('User canceled Google Pay');
            8 } else {
            9 console.error('Google Pay error:', error);
            10 }
            11 }
            12}

            6. Payment Data Request Structure

            6. Payment Data Request Structure

              1function buildPaymentDataRequest(purchaseAmount, googlePayConfig) {
              2 const {
              3 allowedPaymentMethods,
              4 merchantInfo,
              5 apiVersion,
              6 apiVersionMinor,
              7 countryCode
              8 } = googlePayConfig;
              9
              10 return {
              11 apiVersion,
              12 apiVersionMinor,
              13 allowedPaymentMethods,
              14 merchantInfo,
              15 transactionInfo: buildTransactionInfo(purchaseAmount, countryCode),
              16 callbackIntents: ["PAYMENT_AUTHORIZATION"]
              17 };
              18}
              19
              20function buildTransactionInfo(purchaseAmount, countryCode) {
              21 const total = parseFloat(purchaseAmount);
              22 const subtotal = (total * 0.9).toFixed(2);
              23 const tax = (total * 0.1).toFixed(2);
              24
              25 return {
              26 displayItems: [
              27 {
              28 label: "Subtotal",
              29 type: "SUBTOTAL",
              30 price: subtotal
              31 },
              32 {
              33 label: "Tax",
              34 type: "TAX",
              35 price: tax
              36 }
              37 ],
              38 countryCode,
              39 currencyCode: "USD",
              40 totalPriceStatus: "FINAL",
              41 totalPrice: purchaseAmount,
              42 totalPriceLabel: "Total"
              43 };
              44}

              7. Payment Authorization Handler

              7. Payment Authorization Handler

                1async function handlePaymentAuthorization(purchaseAmount, paymentData, googlePaySession) {
                2 try {
                3 // Step 1: Create PayPal order
                4 const orderPayload = buildPayPalOrder(purchaseAmount);
                5 const orderId = await createPayPalOrder(orderPayload);
                6
                7 // Step 2: Confirm order with Google Pay data
                8 const confirmationResult = await googlePaySession.confirmOrder({
                9 orderId: orderId,
                10 paymentMethodData: paymentData.paymentMethodData
                11 });
                12
                13 // Step 3: Handle confirmation result
                14 if (confirmationResult.status !== "PAYER_ACTION_REQUIRED") {
                15 const captureResult = await capturePayPalOrder(orderId);
                16 console.log("Payment successful:", captureResult);
                17
                18 // Redirect to success page or show confirmation
                19 handlePaymentSuccess(captureResult);
                20 }
                21
                22 return { transactionState: "SUCCESS" };
                23 } catch (error) {
                24 console.error("Payment authorization failed:", error);
                25 return {
                26 transactionState: "ERROR",
                27 error: { message: error.message }
                28 };
                29 }
                30}

                8. PayPal Order Configuration

                8. PayPal Order Configuration

                  1function buildPayPalOrder(purchaseAmount) {
                  2 return {
                  3 intent: "CAPTURE",
                  4 purchase_units: [{
                  5 amount: {
                  6 currency_code: "USD",
                  7 value: purchaseAmount,
                  8 breakdown: {
                  9 item_total: {
                  10 currency_code: "USD",
                  11 value: purchaseAmount
                  12 }
                  13 }
                  14 }
                  15 }],
                  16 payment_source: {
                  17 google_pay: {
                  18 attributes: {
                  19 verification: {
                  20 method: "SCA_WHEN_REQUIRED"
                  21 }
                  22 }
                  23 }
                  24 }
                  25 };
                  26}

                  Server-side integration

                  Server-side integration

                  1. Client Token Endpoint

                  1. Client Token Endpoint

                    1app.get('/api/paypal/client-token', async (req, res) => {
                    2 try {
                    3 const accessToken = await getPayPalAccessToken();
                    4
                    5 const response = await fetch(`${PAYPAL_API_BASE}/v1/oauth2/token`, {
                    6 method: 'POST',
                    7 headers: {
                    8 'Authorization': `Bearer ${accessToken}`,
                    9 'Content-Type': 'application/json'
                    10 }
                    11 });
                    12
                    13 const data = await response.json();
                    14 res.json({ clientToken: data.access_token });
                    15 } catch (error) {
                    16 res.status(500).json({ error: 'Failed to generate client token' });
                    17 }
                    18});

                    2. Order Creation Endpoint

                    2. Order Creation Endpoint

                      1app.post('/api/paypal/orders', async (req, res) => {
                      2 try {
                      3 const accessToken = await getPayPalAccessToken();
                      4
                      5 const response = await fetch(`${PAYPAL_API_BASE}/v2/checkout/orders`, {
                      6 method: 'POST',
                      7 headers: {
                      8 'Authorization': `Bearer ${accessToken}`,
                      9 'Content-Type': 'application/json'
                      10 },
                      11 body: JSON.stringify(req.body)
                      12 });
                      13
                      14 const orderData = await response.json();
                      15 res.json({ id: orderData.id });
                      16 } catch (error) {
                      17 res.status(500).json({ error: 'Order creation failed' });
                      18 }
                      19});

                      3. Order Capture Endpoint

                      3. Order Capture Endpoint

                        1app.post('/api/paypal/orders/:orderId/capture', async (req, res) => {
                        2 try {
                        3 const { orderId } = req.params;
                        4 const accessToken = await getPayPalAccessToken();
                        5
                        6 const response = await fetch(`${PAYPAL_API_BASE}/v2/checkout/orders/${orderId}/capture`, {
                        7 method: 'POST',
                        8 headers: {
                        9 'Authorization': `Bearer ${accessToken}`,
                        10 'Content-Type': 'application/json'
                        11 }
                        12 });
                        13
                        14 const captureData = await response.json();
                        15 res.json(captureData);
                        16 } catch (error) {
                        17 res.status(500).json({ error: 'Order capture failed' });
                        18 }
                        19});