Custom DIV for Google Pay

Background
Before starting this tutorial, make sure you understand the following topics from the Quick start section:

👍

Supported APM

When using the Google Pay alternative payment method, the integration into your web page for payment works a little differently than for other APMs.

To set up a custom DIV, follow these steps:

  1. Configure Your Account

    Contact Integrations Support to enable and then set up the desired Google Pay APM on your merchant account.

  2. Create Necessary Payment Flow Pages

    Generally, a merchant site has the following pages:

    • Shopping Cart
    • Confirm/Place Order
    • Checkout
    • Receipt
  3. Configure the Shopping Cart Page

    This page displays all items in the cart and has a button for going to the Checkout page.

    You can also offer alternative payment options (APMs), such as Google Pay, as buttons on the page. The purpose of having these buttons at the Shopping Cart level is to have greater conversion before the customer goes to the checkout page.

    a. Add an iframe for each APM you plan to offer to your shoppers. The ID for the iframe is optional (except for Apple Pay). Use it with your own CSS.

    Google Pay only: You must use a custom DIV instead of an iframe for Google Pay. So, add a DIV to your page where you want to show all the payment options.

    All other APMs: See the steps in Individual Iframe (Button URLs) for how to add those APMs to your page.

    <!- Using DIV for googlepay instead of iframe ->
    <div id="nexio-payment-page" class="nexio-payment-page" style="display:block; height: 100px;"></div>
    
    <iframe id='nexio-paypal-iframe'> <!- PayPal Iframe. ID only needed for your CSS. ->
    </iframe>
    <iframe id='[unique-iframe-id]'> <!- Any other APM iframe. ID only needed for your CSS. ->
    </iframe>
    <!- Add more iframes as needed. ->
    <!- Using DIV for googlepay instead of iframe ->
    <div id="nexio-payment-page" class="nexio-payment-page" style="display:block; height: 100px;"></div>
    

    b. To generate the Google Pay button, send a POST request to the Create APM one-time-use token endpoint.

    Include the required parameters (and any desired optional parameters) for the payment method. For information about the required and optional parameters, see the integration guide:

    curl -X POST https://api.nexiopaysandbox.com/apm/v3/token \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json' \
      -H 'Authorization: Basic [Base64_encoded_login]'
      -d '{
      "data": {
        "amount": 29.99,
        "currency": "USD",
        "customer": {
          "firstName": "Maria",
          "lastName": "Velasquez",
          "email": "[email protected]",
          "orderNumber": "210058A"
          "billToAddressOne": `${customerStreet}`,
          "billToCity": `${customerCity}`,
          "billToState": `${customerState}`,
          "billToPostal": `${customerPostal}`,
          "billToCountry": `${customerCountry}`
        }
      },
      "customerRedirectUrl": "https://[your-ecommerce-website]"
    }'
    

    A successful request returns an array of buttonIFrameUrls. This array is a list of all APMs currently enabled on your merchant account.

    Google Pay only: You will use the url for the APM in a script to get the content for the DIV, rather than to load an iframe.

    All other APMs: See the steps in Individual Iframe (Button URLs) for what to do with these URLs.

    {
      "expiration": "2018-09-18T15:43:05.664Z",
      "token": "830d36f6-a5e3-4455-9600-3a55b63e2fc2",
      "asyncTraceId": "830d36f6-a5e3-4455-9600-3a55b63e2fc2",
      "expressIFrameUrl": "https://www.api.nexiopaysandbox.com/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2",
      "redirectUrls": [...],
      "buttonIFrameUrls": [
        {
          "paymentMethod": "nihaoPayAliPay",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=nihaoPayAliPay"
        },
        {
          "paymentMethod": "nihaoPayWechatPay",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=nihaoPayWechatPay"
        },
        {
          "paymentMethod": "payPal",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=payPal"
        },
        {
          "paymentMethod": "braintreePayPal",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=braintreePayPal"
        },
        {
          "paymentMethod": "nihaoPayUnionPay",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=nihaoPayUnionPay"
        },
        {
          "paymentMethod": "applePayAuthNet",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=applePayAuthNet"
        },
        {
          "paymentMethod": "googlePayCyberSource",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=googlePayCyberSource"
        }
      ]
    }
    

    c. For Google Pay, you need to include the code for the page to take the URL and get the content to display in the DIV.

    <script>
        function getOneTimeUseToken() {
            fetch('http://localhost:3000/', { // Set to whatever your backend server is for getting the one-time-use token
                method: 'GET'
            }).then(function(response) {
                return response.json();
            }).then((objData) => {
                console.log('------->response Data', objData);
    
                var buttonUrlParams = {};
               
                if (objData.buttonIFrameUrls && objData.buttonIFrameUrls.length > 0) {
                    objData.buttonIFrameUrls.forEach(function(item) {
                        var iframeId = 'iframe_' + item.paymentMethod;
                        var iframe = document.getElementById(iframeId);
                        if (iframe) {
                            if (item.paymentMethod == "googlePayCyberSource" || item.paymentMethod == "googlePayAuthNet") {
                                console.log("Processing Google Pay");
                                fetch(item.url)
                                    .then(response => response.text())
                                    .then(htmlContent => {
                                        console.log("HTML content loaded");
                                        const container = document.getElementById('nexio-payment-page');
                                        const parser = new DOMParser();
                                        const doc = parser.parseFromString(htmlContent, 'text/html');
                                        container.innerHTML = ''; // Clear previous content
                                        container.appendChild(doc.body.firstChild); // Add new content
                                        const scripts = doc.querySelectorAll('script');
                                        scripts.forEach((script) => {
                                            if (!script.src) { // Only inline scripts
                                                const scriptElement = document.createElement('script');
                                                scriptElement.textContent = script.textContent;
                                                container.appendChild(scriptElement);
                                            }
                                        });
                                        // Load the Google Pay script only once
                                        if (!document.querySelector('script[src="https://pay.google.com/gp/p/js/pay.js"]')) {
                                            console.log("Loading Google Pay script");
                                            const googlePayScript = document.createElement('script');
                                            googlePayScript.src = 'https://pay.google.com/gp/p/js/pay.js';
                                            googlePayScript.async = true;
                                            googlePayScript.onload = () => {
                                                if (window.onGooglePayLoaded) {
                                                    window.onGooglePayLoaded(); // Pass apmValues here
                                                }
                                            };
                                            container.appendChild(googlePayScript);
                                        } else {
                                            // If Google Pay script is already loaded, trigger the event directly
                                            if (window.onGooglePayLoaded) {
                                                window.onGooglePayLoaded();
                                            }
                                        }
                                    })
                                    .catch(error => {
                                        console.error('Error loading HTML content:', error);
                                    });
                            }
                            iframe.src = item.url; // Set URL for any other APM iframes
                        } else {
                            console.log('Iframe not found for:', item.paymentMethod);
                        }
                    });
                } else {
                    console.log('No button iframe URLs available');
                }
            });
        }
    
        getOneTimeUseToken();
    </script>
    

    All other APMs: See the steps in Individual Iframe (Button URLs) for what to add each url to the src tag of each iframe you created in step 3a, if applicable.

    Now, when the page loads, the customer sees a button for each APM iframe and the Google Pay DIV you added to the page.

    d. When they click a button (on your own external button or the iframe button, depending on the page configuration) they are sent to the appropriate APM page to complete payment (either redirected to the page or a popup window opened).

    Apple Pay or Google Pay: The customer is not redirected. Rather, a popup window opens in which the shopper can complete payment.

    PayPal (with Braintree) only: A popup window opens for the customer to log in. After setting an address (can be passed in the one-time-use token request and displayed to the customer as a default option) and payment method, the customer clicks Agree and Continue. The customer gets redirected to the Confirm/Place Order page.

  4. Configure the Confirm/Place Order Page

    The Confirm/Place Order page is used to calculate taxes and shipping cost after gathering address information from the customer.

    This page is important for PayPal (with Braintree). For more information about this page, see Individual Iframe (Button URLs).

  5. Configure the Checkout Page

    The Checkout page gives the customer the opportunity to make address and payment information, and for the page to calculate and display tax and shipping cost.

    In addition to a Pay button, you can also offer alternative payment options (APMs), such as Google Pay, as buttons on the page so consumers have more options for payment. (For more information about creating a checkout page, see the steps in Creating a card checkout page with the iframe.)

    a. Add the DIV for Google Pay and an iframe for each APM you plan to offer to your shoppers. The ID for the iframe is optional (except for Apple Pay, where it is required). Use it with your own CSS.

    Google Pay only: You must use a custom DIV instead of an iframe for Google Pay. So, add a DIV to your page where you want to show all the payment options.

    All other APMs: See the steps in Individual Iframe (Button URLs) for how to add those APMs to your page.

    <!- Using DIV for googlepay instead of iframe ->
    <div id="nexio-payment-page" class="nexio-payment-page" style="display:block; height: 100px;"></div>
    
    <iframe id='nexio-paypal-iframe'> <!- PayPal Iframe. ID only needed for your CSS. ->
    </iframe>
    <iframe id='[unique-iframe-id]'> <!- Any other APM iframe. ID only needed for your CSS. ->
    </iframe>
    <!- Add more iframes as needed. ->
    <!- Using DIV for googlepay instead of iframe ->
    <div id="nexio-payment-page" class="nexio-payment-page" style="display:block; height: 100px;"></div>
    

    b. To generate the Google Pay button, send a POST request to the Create APM one-time-use token endpoint.

    Include the required parameters (and any desired optional parameters) for the payment method. For information about the required and optional parameters, see the integration guide:

    curl -X POST https://api.nexiopaysandbox.com/apm/v3/token \
      -H 'Content-Type: application/json' \
      -H 'Accept: application/json' \
      -H 'Authorization: Basic [Base64_encoded_login]'
      -d '{
      "data": {
        "amount": 29.99,
        "currency": "USD",
        "customer": {
          "firstName": "Maria",
          "lastName": "Velasquez",
          "email": "[email protected]",
          "orderNumber": "210058A"
          "billToAddressOne": "2147 West Silverlake Drive",
          "billToCity": "Scranton",
          "billToState": "PA",
          "billToPostal": "18503",
          "billToCountry": "US"
        }
      },
      "customerRedirectUrl": "https://[your-ecommerce-website]"
    }'
    

    A successful request returns an array of buttonIFrameUrls. This array is a list of all APMs currently enabled on your merchant account.

    Google Pay only: You will use the url for the APM in a script to get the content for the DIV, rather than to load an iframe.

    All other APMs: See the steps in Individual Iframe (Button URLs) for what to do with these URLs.

    {
      "expiration": "2018-09-18T15:43:05.664Z",
      "token": "830d36f6-a5e3-4455-9600-3a55b63e2fc2",
      "asyncTraceId": "830d36f6-a5e3-4455-9600-3a55b63e2fc2",
      "expressIFrameUrl": "https://www.api.nexiopaysandbox.com/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2",
      "redirectUrls": [...],
      "buttonIFrameUrls": [
        {
          "paymentMethod": "nihaoPayAliPay",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=nihaoPayAliPay"
        },
        {
          "paymentMethod": "nihaoPayWechatPay",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=nihaoPayWechatPay"
        },
        {
          "paymentMethod": "payPal",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=payPal"
        },
        {
          "paymentMethod": "braintreePayPal",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=braintreePayPal"
        },
        {
          "paymentMethod": "nihaoPayUnionPay",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=nihaoPayUnionPay"
        },
        {
          "paymentMethod": "applePayAuthNet",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=applePayAuthNet"
        },
        {
          "paymentMethod": "googlePayCyberSource",
          "url": "https://api.nexiopaysandbox.com/apm/v3?token=830d36f6-a5e3-4455-9600-3a55b63e2fc2&paymentMethod=googlePayCyberSource"
        }
      ]
    }
    

    c. For Google Pay, you need to include the code for the page to take the URL and get the content to display in the DIV.

    <script>
        function getOneTimeUseToken() {
            fetch('http://localhost:3000/', { // Set to whatever your backend server is for getting the one-time-use token
                method: 'GET'
            }).then(function(response) {
                return response.json();
            }).then((objData) => {
                console.log('------->response Data', objData);
    
                var buttonUrlParams = {};
               
                if (objData.buttonIFrameUrls && objData.buttonIFrameUrls.length > 0) {
                    objData.buttonIFrameUrls.forEach(function(item) {
                        var iframeId = 'iframe_' + item.paymentMethod;
                        var iframe = document.getElementById(iframeId);
                        if (iframe) {
                            if (item.paymentMethod == "googlePayCyberSource" || item.paymentMethod == "googlePayAuthNet") {
                                console.log("Processing Google Pay");
                                fetch(item.url)
                                    .then(response => response.text())
                                    .then(htmlContent => {
                                        console.log("HTML content loaded");
                                        const container = document.getElementById('nexio-payment-page');
                                        const parser = new DOMParser();
                                        const doc = parser.parseFromString(htmlContent, 'text/html');
                                        container.innerHTML = ''; // Clear previous content
                                        container.appendChild(doc.body.firstChild); // Add new content
                                        const scripts = doc.querySelectorAll('script');
                                        scripts.forEach((script) => {
                                            if (!script.src) { // Only inline scripts
                                                const scriptElement = document.createElement('script');
                                                scriptElement.textContent = script.textContent;
                                                container.appendChild(scriptElement);
                                            }
                                        });
                                        // Load the Google Pay script only once
                                        if (!document.querySelector('script[src="https://pay.google.com/gp/p/js/pay.js"]')) {
                                            console.log("Loading Google Pay script");
                                            const googlePayScript = document.createElement('script');
                                            googlePayScript.src = 'https://pay.google.com/gp/p/js/pay.js';
                                            googlePayScript.async = true;
                                            googlePayScript.onload = () => {
                                                if (window.onGooglePayLoaded) {
                                                    window.onGooglePayLoaded(); // Pass apmValues here
                                                }
                                            };
                                            container.appendChild(googlePayScript);
                                        } else {
                                            // If Google Pay script is already loaded, trigger the event directly
                                            if (window.onGooglePayLoaded) {
                                                window.onGooglePayLoaded();
                                            }
                                        }
                                    })
                                    .catch(error => {
                                        console.error('Error loading HTML content:', error);
                                    });
                            }
                            iframe.src = item.url; // Set URL for any other APM iframes
                        } else {
                            console.log('Iframe not found for:', item.paymentMethod);
                        }
                    });
                } else {
                    console.log('No button iframe URLs available');
                }
            });
        }
    
        getOneTimeUseToken();
    </script>
    

    All other APMs: See the steps in Individual Iframe (Button URLs) for what to add each url to the src tag of each iframe you created in step 3a, if applicable.

    Now, when the page loads, the customer sees a button for each APM iframe and the Google Pay DIV you added to the page.

    d. When they click a button (on your own external button or the iframe button, depending on the page configuration) they are sent to the appropriate APM page to complete payment (either redirected to the page or a popup window opened).

    Apple Pay or Google Pay: The customer is not be redirected. Rather, a popup window opens in which the shopper can complete payment.

    PayPal (with Braintree) only: A popup window opens for the customer to log in. After setting an address (can be passed in the one-time-use token request and displayed to the customer as a default option) and payment method, the customer clicks Agree and Continue. The customer gets redirected to the Confirm/Place Order page.

  6. Shopper Completes Payment

    This step varies slightly depending on the APM.

    • Voucher payments (Paynet and SPEI): Users are prompted to print or close the voucher page.

    • PayPal (with Braintree) only: If the customer checked out using PayPal (with Braintree) and saveRecurringToken was set to true in the one-time-use token request, then the response includes an apm.token parameter. For example:

      { "apm": { "token": "apm:f58kq4b5-h408-3a29-s07b-c384j3958fkw" } }
      
    • All other APMs: When a consumer clicks the APM button, a popup window opens (or they are redirected) to the appropriate APM page in which the consumer can complete payment.

      After the consumer completes payment, the popup window closes (if appropriate) and they are redirected back to the merchant website.

    • If you did not send the customerRedirectUrl in the request from step 3, the consumer is redirected to the checkout page. Nexio provides a response as event messages.

    • If you did send the customerRedirectUrl in the request from step 3, the customer is redirected to that URL. Nexio provides a response via query string parameters in the URL.

    If your merchant account is configured to receive webhooks, in addition to one of the above, Nexio provides responses as event messages to the webhook URLs that have been registered.

  7. Shopper Redirected

    After the shopper has completed payment (or payment has failed) Nexio's iframe requests to be closed and sends a message event or redirect URL with the payment information.

    • If the payment was successful, the message includes the status and payment ID. For information about status, see the Status workflows section for the specific payment method.
    • If the payment failed, the message includes the status and an error message. For information about handling errors, see Error handling.

    Use the message information to create a success (such as a receipt) or failure page for the shopper. You may also want to send a receipt to the shopper via email.

    Example URL query string parameters response (for customerRedirectUrl):

    https://your-ecommerce-website.example.com?status=pending&paymentId=eyJuYW1lIjoidXNhZXBheSIsInJlZk51bWJlciI6IjMxMDA5MDc4MTkiLCJtZXJjaGFudElkIjoiMTAwMDM5IiwicmFuZG9tIjoiMzEwMDkwNzgxOSIsImN1cnJlbmN5IjoiVVNEIn0&orderNumber=228c3778fe
    

    Example URL query string parameters response (for customerRedirectUrl) for a failed payment:

    https://your-ecommerce-website.example.com?status=pending&error=error_message
    

    Example event message response (for request without customerRedirectUrl or for webhook):

    {
      "id": "eyJuYW1lIjoicGF5UGFsIiwibWVyY2hhbnRJZCI6IjEwMDAzOSIsInJlZk51bWJlciI6IjlLQTI2NzUwSEs5NzM2OTNBIiwicmFuZG9tIjowLCJjdXJyZW5jeSI6InVzZCJ9",
      "merchantId": "100039",
      "transactionDate": "2020-06-29T18:54:01.087Z",
      "transactionStatus": "settled",
      "amount": 1.15,
      "transactionType": "sale",
      "currency": "USD",
      "gatewayResponse": {
        "result": 201,
        "refNumber": "9KA26750HK973693A",
        "gatewayName": "payPal",
        "message": 201
      },
      "data": {
        "amount": 1.15,
        "currency": "USD",
        "settlementCurrency": "USD",
        "customer": {
          "lastName": "Test",
          "shipToAddressOne": "123 Ship St",
          "shipToPhone": "5033335678",
          "orderNumber": "054204daf0f7456bac59a014e952fb33",
          "shipToCountry": "US",
          "shipToAddressTwo": "Warehouse 456",
          "billToState": "UT",
          "billToCity": "Testerville",
          "shipToPostal": "67890",
          "firstName": "Nexio",
          "shipToCity": "Shipperville",
          "billToAddressOne": "123 Test St",
          "billToCountry": "US",
          "billToPostal": "12345",
          "billToAddressTwo": "Suite 123",
          "billToPhone": "8015551234",
          "email": "[email protected]",
          "shipToState": "OR"
        }
      }
    }