PayFields: Tokenize an Extra Payment Method for an Existing Customer

Prev Next

You can use PayFields to tokenize a method of payment and associate it to an existing customer, adding multiple payment methods that are tokenized under a specific customer.

Important!

You need to populate the apiKey and merchant with the appropriate credentials from sandbox for the code to function properly.

Entire PayFields Code Snippet

<head>
    <script src="https://use.fontawesome.com/c24d3cbe35.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <title>PayFields - How to Tokenize a Payment for an existing Customer</title>
</head>

<body>
  <div class="container">
    <div class="row">
        <div class="col-sm-6">
            <p>Locate Customer by Email!</p>
            <input type="email" class="form-control" id="email" placeholder="Enter email . . ."/>
            <br>
            <button type="button" class="btn btn-sm btn-info text-white" id="getCustomer">Get Customer</button>
            <button type="button" class="btn btn-sm btn-warning text-white" id="getPayments">Get Existing Payments</button>
            <hr>
            <div id="customer_id"></div>
        </div>
    </div>
    <hr>
    <div class="row">
        <div class="col-sm-6">
            <div>
                <label for="name"><p>Card Holder</p></label>
                <div class="input-group g-brd-primary--focus">
                      <div id="name"></div>
                </div>
            </div>
        </div>

        <div class="col-sm-6">
            <div>
                <label for="number"><p>Card Number</p></label>
                <div class="input-group">
                    <div class="el">
                        <div id="number"></div>
                    </div>
                </div>
              </div>               
        </div>
    </div>

    <div class="row">
        <div class="col-sm-6">
            <div>
                <label for="expiration"><p>Expiration</p></label>
                <div class="input-group">
                    <div class="el" id="expiration"></div>
                </div>
              </div>
        </div>
        <div class="col-sm-6">
            <div>
                <label for="cvv"><p>CVV</p></label>
                <div class="input-group">
                    <div class="el" id="cvv"></div>
                </div>
              </div>
        </div>
    </div>

    <br>
    <button type="button" class="btn btn-sm btn-success text-white" id="submit">Add New Payment</button>
    <hr>
    </div>
</body>

<!-- 
    Depedencies
    - jQuery - REQUIRED
    - PayFields Script - REQUIRED 
    - Popper (Styles / Functionality for Bootstrap) NOT REQUIRED
    - Bootstrap (Styles / Functionality) NOT REQUIRED
-->
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https:test-api.payrix.com/payFieldsScript"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp+tA7hAShOK/B/fQ2" crossorigin="anonymous"></script>

<!--
    ===========================================================
    BEGIN PayFields logic
    ===========================================================
-->
<script>
    PayFields.config.apiKey = ''
    PayFields.config.merchant = ''

    // Query Selector to grab submit button element
    let submit = document.querySelector('#submit');
    PayFields.fields = [
                    {
                        type: 'number',
                        element: '#number'
                    },
                    {
                        type: 'cvv',
                        element: '#cvv'
                    },
                    {
                        type: 'name',
                        element: '#name'
                    },
                    {
                        type: 'expiration',
                        element: '#expiration'
                    },
                    // Create the iFrame for the customer_id so it is included in the 'fields' array within the PayFields object
                    {
                        type: 'customer_id',
                        element: '#customer_id'
                    }
                ];
    // Use event listener to call PayFields.submit()
    submit.addEventListener('click', function() {
        // Tokenzing an additional method of payment requires:
        // 1. amount to be set to 0
        // 2. mode to be set to token
        PayFields.config.amount = 0
        PayFields.config.txnType = 'auth'
        PayFields.config.mode = 'token'
        PayFields.submit();
    })
</script>
<!--
    ===========================================================
    END PayFields logic
    ===========================================================
-->

<!--
    ===========================================================
    BEGIN API Functionality - Javascript "Fetch"
    ===========================================================
-->
<script>

    let customerIdForTokens = ''
    let APIKEY = ''

    // Get customer associated to a specific email address
     function getCustomer() {
        let customerEmail = document.querySelector('#email').value
        var myHeaders = new Headers();
        myHeaders.append("APIKEY", APIKEY);
        myHeaders.append("Content-Type", "application/json");
        myHeaders.append("search", `email[equals]=${customerEmail}`);

        var requestOptions = {
        method: 'GET',
        headers: myHeaders,
        redirect: 'follow'
        };

        fetch("https://test-api.payrix.com/customers", requestOptions)
        .then(response => response.json())
        .then(result => {
            customerIdForTokens = result.response.data[0].id
            if (result.response.data[0] !== undefined) {
                PayFields.fields = [
                    {
                        type: 'number',
                        element: '#number'
                    },
                    {
                        type: 'cvv',
                        element: '#cvv'
                    },
                    {
                        type: 'name',
                        element: '#name'
                    },
                    {
                        type: 'expiration',
                        element: '#expiration'
                    },
                    {
                        type: 'customer_id',
                        element: '#customer_id',
                        // pass a value (customer ID) to the customer_id key below
                        values: {
                            customer_id: result.response.data[0].id
                        }
                    }
                ];
                // PayFields.reload() will take in a parameter and in this case, we are passing the customer_id. PayFields.reload() refreshes / updates
                // the PayField and since we are calling it after the customer_id is inheriting a value from the fetch request, the value will
                // appear in the customer_id PayField. If you need to hide the div for customer_id, include the 'hidden' attribute in the div.
                PayFields.reload('customer_id')
            } else {
                console.log("Not a current customer")
            }
        })
        .catch(error => console.log(error));
    }

    function getPayments() {
        var myHeaders = new Headers();
        myHeaders.append("APIKEY", APIKEY);
        myHeaders.append("Content-Type", "application/json");
        // Find customer that matches the customer ID variable defined from the getCustomer() function
        myHeaders.append("search", `customer[equals]=${customerIdForTokens}`);

        var requestOptions = {
        method: 'GET',
        headers: myHeaders,
        redirect: 'follow'
        };

        // Expand the (hidden) payment object within the tokens endpoint
        fetch("https://test-api.payrix.com/tokens?expand[payment][]", requestOptions)
        .then(response => response.json())
        .then(result => {
            let payments = []
            for (let i = 0; i < result.response.data.length; i++) {
                // Push last 4 digits of each method of payment to the payments array
                payments.push(result.response.data[i].payment.number)
            }
            // Display payments array
            alert(`Each method of payment associated to this customer (last 4) - ${payments}`)
        })
        .catch(error => console.log(error));
    }

    let getCustomerButton = document.querySelector('#getCustomer')
    getCustomerButton.addEventListener('click', function() {
        getCustomer();
    })

    let getPaymentsButton = document.querySelector('#getPayments')
    getPaymentsButton.addEventListener('click', function() {
        getPayments()
    })

</script>
<!--
    ===========================================================
    END API Functionality - Javascript "Fetch"
    ===========================================================
-->

Two custom functions are getCustomer() and getPayments().

getCustomer()

The getCustomer() function is invoked with the following light blue button. It will take an email address and search against the /customers endpoint to locate the appropriate customer ID.

Input field for email with buttons to retrieve customer or payment information.

After an email is entered, and the blue button is clicked, a customer ID will be returned in the input text below.

Form to locate a customer by email with buttons for actions.

getPayments()

The getPayments() function will be invoked when the yellow button is clicked. This function is returning all of the tokens from the /tokens endpoint, and expanding objects within that endpoint to display the last 4 numbers associated with each token returned. In the below example, there is one token associated to this customer because only one set of last 4 numbers are returned in the alert.

Customer lookup interface displaying email and payment details.

One PayFields native function is PayFields.reload().

PayFields.reload()

PayFields has several built-in functions. reload() is one of them. PayFields.reload() can take one parameter. In this case, we are passing customer_id within the code, so PayFields knows to target the customer_id div in the HTML and reload it. The reason we need to reload the customer_id div is because we mounted this PayFields iFrame for the customer_id to the web page without any values. When we run a fetch request in JS to capture the customer_id associated to the email, we can then reload the PayFields instance for that specific div and populate it with the desired value.

Adding a new method of payment

Customer payment details including email, card holder, and card number information displayed.

End result - Total of 2 new method of payments on file

Customer payment details including email, card holder, expiration, and CVV information.