Skip to main content
Skip table of contents

Accept ACH Payments With PayFields

Example code and step-by-step instructions for building an ACH payment form using PayFields.

This page describes how to build an ACH payment form using PayFields:

  • Quickstart - Sample code and instructions for building a basic ACH payment form.

  • Implementation - Details about the PayFields ACH implementation.

Quickstart

Follow the steps below to create a basic ACH payment form that you can view in your web browser:

  1. Copy the code below into a text editor.

  2. Add your API key and merchant ID on lines 140 and 141.

  3. Save the file with a .html extension.

  4. Open the file in your web browser. The page will display the fields required to process an ACH transaction with PayFields.

Quickstart Code

Click to expand the PayFields ACH HTML sample.
HTML
<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">
    </link>
    <title>PayFields Script</title>
    <style>
        body {
            background-color: #ffffff
        }

        .form {
            background: #fff;
            padding-left: 3rem;
            width: 100%;
            height: 30rem;
            box-shadow: 5px 5px 8px rgba(0, 0, 0, 0.075);
        }

        .el {
            margin-bottom: -111px;
            margin-right: -109px;
        }
    </style>
</head>

<body>
    <div class="container-fluid">
        <div class="row">

            <br>

            <!-- Number will always be a required field - Create a div and hide it with DOM styling -->
            <div id="number"></div>

            <div class="form">
                <div class="row">
                    <div class="col-sm-6">
                        <div>
                            <label for="name">
                                <p>Name</p>
                            </label>
                            <a href="#" data-toggle="popover" title="Card Holder"
                                data-content="First and last name must be entered."><span><i
                                        class="fa fa-info-circle"></i></span></a>
                            <div class="input-group g-brd-primary--focus">
                                <div class="input-group-prepend">
                                    <span class="input-group-text rounded-0 g-bg-white g-color-gray-light-v1"><i
                                            class="fa fa-user"></i></span>
                                    <div class="el" id="name"></div>
                                </div>
                            </div>

                        </div>
                    </div>

                    <div class="col-sm-6">

                        <div>
                            <label for="number">
                                <p>Account Number</p>
                            </label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fa fa-credit-card"
                                            aria-hidden="true"></i></span>
                                    <div class="el">
                                        <div id="account_number"></div>
                                    </div>

                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row">

                    <div class="col-sm-6">
                        <br>
                        <div>
                            <label for="expiration">
                                <p>Account Type</p>
                            </label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fa fa-calendar"
                                            style="height: 1.25rem !important;" aria-hidden="true"></i></span>
                                    <div class="el" id="account_type" style="height: 2.75rem;"></div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="col-sm-6">
                        <br>
                        <div>
                            <label for="expiration">
                                <p>Routing</p>
                            </label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fa fa-calendar"
                                            aria-hidden="true"></i></span>
                                    <div class="el" id="routing"></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <br>
                <button type="button" id="btnACH" class="btn btn-info btn-sm">Make Payment</button>
            </div>
        </div>
    </div>
    </div>
    </div>
    </div>
</body>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"
    integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https:test-api.payrix.com/payFieldsScript"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
    integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous">
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.min.js"
    integrity="sha384-VHvPCCyXqtD5DqJeNxl2dtTyhF78xXNXdkwX1CZeRusQfRKp+tA7hAShOK/B/fQ2" crossorigin="anonymous">
</script>
<script>
    $("[data-toggle=popover]").popover();
</script>

<script>
    // Global Variables
    // ==========================================================================================
    let btnACH = document.querySelector("#btnACH")

    // PayFields congiration goes here - API Key and Merchant ID
    PayFields.config.apiKey = '082dc69e1abd111d34e14f291fc890c8'
    PayFields.config.merchant = 't1_mer_6203d7c60f36fe26057c693'
    // ==========================================================================================

    // ==========================================================================================
    // Set transaction amount
    PayFields.config.amount = 1000
    // Run a transaction
    PayFields.config.mode = 'txnToken'
    // This is an echeck sale
    PayFields.config.txnType = 'ecsale'
    // ==========================================================================================

    // PayFields styling via DOM styles
    // ==========================================================================================
    PayFields.customizations.style = {
        // Hide number div in the HTML
        ".number": {
            display: "none"
        },
        ".input": {
            border: "1px solid #ced4da",
            display: "block",
            width: "12rem",
            height: "34px",
            padding: "0.375rem-0.75rem",
            font: "12px Arial, Helvetica, sans-serif",
            fontSize: ".75rem",
            lineHeight: "1.5",
            borderRadius: "2px",
            backgroundColor: "#fff",
            boxShadow: "inset 0 1px 1px rgba(0, 0, 0, .075)",
            backgroundClip: "padding-box"
        },
        ".card-icon": {
            marginRight: "6rem",
            marginTop: ".25rem"
        }
    }
    // ==========================================================================================

    // On page load, the PayFields object must know payment_cvv and expiration are optional so divs will load correctly
    PayFields.customizations.optionalFields = ["#payment_cvv", "#expiration"];

    // Initiate all fields upon page load for PayFields
    // ==========================================================================================
    PayFields.fields = [{
            // Number must be present for PayField divs to load
            type: 'number',
            element: '#number'
        },
        {
            type: 'name',
            element: '#name'
        },
        {
            type: "routing",
            element: "#routing"
        },
        {
            type: "account_type",
            element: "#account_type",
        },
        {
            type: "account_number",
            element: "#account_number",
        }
    ];
    // ==========================================================================================

    // Make Payment button for ACH
    // ==========================================================================================
    btnACH.addEventListener('click', function () {

        // Making cvv number and expiration optional for credit / debit card if ACH only
        // The number element must be placed in the event listener (btnACH)
        PayFields.customizations.optionalFields = ["#number"];
        // Submit payment for ACH
        PayFields.submit()
    })
    // ==========================================================================================
</script>

Implementation

The sections provide details about how the ACH Quickstart page is built:

  • Include the JavaScript libraries - Include the PayFields and jQuery libraries in the page.

  • Build the PayFields script block - Authenticate your application, configure the PayFields options, create a submit button, and execute the transaction.

  • Add the fields to the payment page - Add <div> elements that will contain the fields and assign the correct ID.

  • Handle the response - Add JavaScript functions to your page that run when PayFields returns the transaction results.

Include the JavaScript libraries

PayFields requires the PayFields and the most recent jQuery JavaScript libraries. Add the following code to any page that will use the PayFields scripts:

HTML
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
    integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https:test-api.payrix.com/payFieldsScript"></script>

If jQuery conflicts with other global variables used in the application, you may use the noConflict feature by setting PayFields.jQuery = jQuery.noConflict(), which will ensure that jQuery will not set any global variables.

See lines 121 through 123 of the Quickstart code for context.

The Quickstart example also includes Bootstrap and popper.js to create the user interface.

Build the PayFields Script Block

The PayFields script block performs the following functions:

  • Authentication - Sets the apiKey and merchant ID values with the PayFields.config.apiKey and PayFields.config.merchant.

  • Configuration - Defines the type, mode, and a default amount for transactions. Identifies optional fields to ensure that PayFields works as expected.

  • Customization - Sets the styles that will be applied to the form elements.

  • Initialization - Defines the fields that will be used on the page and sets their IDs.

  • Execution - Creates a submit button and attaches an event listener, and runs the PayFields.submit(); function to send the payment.

Click here to expand an example of the entire PayFields script block for ACH transactions.
HTML
<script>
    // Global Variables
    // ==========================================================================================
    let btnACH = document.querySelector("#btnACH")

    // PayFields congiration goes here - API Key and Merchant ID
    PayFields.config.apiKey = 'Your API Key'
    PayFields.config.merchant = 'Your Merchant ID'
    // ==========================================================================================

    // ==========================================================================================
    // Set transaction amount
    PayFields.config.amount = 1000
    // Tokenize bank account
    PayFields.config.mode = 'txn';
    // This is an echeck sale
    PayFields.config.txnType = 'ecsale'
    // ==========================================================================================

    // PayFields styling via DOM styles
    // ==========================================================================================
    PayFields.customizations.style = {
        // Hide number div in the HTML
        ".number": {
            display: "none"
        },
        ".input": {
            border: "1px solid #ced4da",
            display: "block",
            width: "12rem",
            height: "34px",
            padding: "0.375rem-0.75rem",
            font: "12px Arial, Helvetica, sans-serif",
            fontSize: ".75rem",
            lineHeight: "1.5",
            borderRadius: "2px",
            backgroundColor: "#fff",
            boxShadow: "inset 0 1px 1px rgba(0, 0, 0, .075)",
            backgroundClip: "padding-box"
        },
        ".card-icon": {
            marginRight: "6rem",
            marginTop: ".25rem"
        }
    }
    // ==========================================================================================

    // On page load, the PayFields object must know payment_cvv and expiration are optional so divs will load correctly
    PayFields.customizations.optionalFields = ["#payment_cvv", "#expiration"];

    // Initiate all fields upon page load for PayFields
    // ==========================================================================================
    PayFields.fields = [{
            // Number must be present for PayField divs to load
            type: 'number',
            element: '#number'
        },
        {
            type: 'name',
            element: '#name'
        },
        {
            type: "routing",
            element: "#routing"
        },
        {
            type: "account_type",
            element: "#account_type",
        },
        {
            type: "account_number",
            element: "#account_number",
        }
    ];
    // ==========================================================================================

    // Make Payment button for ACH
    // ==========================================================================================
    btnACH.addEventListener('click', function () {

        // Making cvv number and expiration optional for credit / debit card if ACH only
        // The number element must be placed in the event listener (btnACH)
        PayFields.customizations.optionalFields = ["#number"];
        // Submit payment for ACH
        PayFields.submit()
    })
    // ==========================================================================================
</script>

The sections below define the functions of the script block in more detail.

Authentication

Use the PayFields.config functions shown below to set your API Key and Merchant ID:

HTML
// PayFields congiration goes here - API Key and Merchant ID
PayFields.config.apiKey = 'Your API Key'
PayFields.config.merchant = 'Your merchant ID'
// ==========================================================================================

Configure the PayFields Options

Configure the PayFields options in your script block as shown below:

HTML
// ==========================================================================================
// Set transaction amount
PayFields.config.amount = 1000
// Tokenize Bank Account
PayFields.config.mode = 'txnToken';
// This is an echeck sale
PayFields.config.txnType = 'ecsale'
// ========================================================================================== 

For ACH payments, the txnType must be set to `ecsale`.

You should create an entirely separate payment page for ACH transactions.

Note: If you use the same PayFields payment page for credit card and ACH transactions, the fields populated first will override the other transaction type.

HTML
// On page load, the PayFields object must know payment_cvv and expiration are optional so divs will load correctly
PayFields.customizations.optionalFields = ["#payment_cvv", "#expiration"];

Customization

Set the styles that determine the appearance of the payment form:

CODE
// PayFields styling via DOM styles
// ==========================================================================================
PayFields.customizations.style = {
    // Hide number div in the HTML
    ".number": {
        display: "none"
    },
    ".input": {
        border: "1px solid #ced4da",
        display: "block",
        width: "12rem",
        height: "34px",
        padding: "0.375rem-0.75rem",
        font: "12px Arial, Helvetica, sans-serif",
        fontSize: ".75rem",
        lineHeight: "1.5",
        borderRadius: "2px",
        backgroundColor: "#fff",
        boxShadow: "inset 0 1px 1px rgba(0, 0, 0, .075)",
        backgroundClip: "padding-box"
    },
    ".card-icon": {
        marginRight: "6rem",
        marginTop: ".25rem"
    }
}
// ==========================================================================================

Initialization

Define the fields that will be used on the form and set their IDs. For ACH transactions, use the following fields:

  • number - The credit card number field. This field is required for PayFields DIVs to load, but you will not send a value for this field.

  • name - The accountholder’s name.

  • routing - The routing number of the accountholder’s bank.

  • account_type - Defines whether the account is a checking or savings account.

  • account_number - The bank account number.

The code below shows an example of the initialization:

CODE
// Initiate all fields upon page load for PayFields
// ==========================================================================================
PayFields.fields = [{
        // Number must be present for PayField divs to load
        type: 'number',
        element: '#number'
    },
    {
        type: 'name',
        element: '#name'
    },
    {
        type: "routing",
        element: "#routing"
    },
    {
        type: "account_type",
        element: "#account_type",
    },
    {
        type: "account_number",
        element: "#account_number",
    }
];
// ==========================================================================================

Execution

Use the let keyword to identify the button that a customer will use to submit a payment:

CODE
// Global Variables
// ==========================================================================================
let btnACH = document.querySelector("#btnACH")

Then add an event listener that calls the PayFields.submit() function when the button is clicked:

CODE
// Make Payment button for ACH
// ==========================================================================================
btnACH.addEventListener('click', function () {

    // Making cvv number and expiration optional for credit / debit card if ACH only
    // The number element must be placed in the event listener (btnACH)
    PayFields.customizations.optionalFields = ["#number"];
    // Submit payment for ACH
    PayFields.submit()
})
// ==========================================================================================

You must set the number field to optional in the event listener. This ensures that PayFields will not expect a card number, but that the form will be displayed as expected.

Add the fields to the payment page

Add the form fields to the <body> of your page by creating <div> elements and assigning the id values that you defined in the previous step. For example, the code below creates a <div> for the name element:

CODE
<div id="#name"></div>
Click here to expand an example of the page body, which includes DIVs for each PayFields ACH element.
HTML
<body>
    <div class="container-fluid">
        <div class="row">

            <br>

            <!-- Number will always be a required field - Create a div and hide it with DOM styling -->
            <div id="number"></div>

            <div class="form">
                <div class="row">
                    <div class="col-sm-6">
                        <div>
                            <label for="name">
                                <p>Name</p>
                            </label>
                            <a href="#" data-toggle="popover" title="Card Holder"
                                data-content="First and last name must be entered."><span><i
                                        class="fa fa-info-circle"></i></span></a>
                            <div class="input-group g-brd-primary--focus">
                                <div class="input-group-prepend">
                                    <span class="input-group-text rounded-0 g-bg-white g-color-gray-light-v1"><i
                                            class="fa fa-user"></i></span>
                                    <div class="el" id="name"></div>
                                </div>
                            </div>

                        </div>
                    </div>

                    <div class="col-sm-6">

                        <div>
                            <label for="number">
                                <p>Account Number</p>
                            </label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fa fa-credit-card"
                                            aria-hidden="true"></i></span>
                                    <div class="el">
                                        <div id="account_number"></div>
                                    </div>

                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row">

                    <div class="col-sm-6">
                        <br>
                        <div>
                            <label for="expiration">
                                <p>Account Type</p>
                            </label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fa fa-calendar"
                                            style="height: 1.25rem !important;" aria-hidden="true"></i></span>
                                    <div class="el" id="account_type" style="height: 2.75rem;"></div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="col-sm-6">
                        <br>
                        <div>
                            <label for="expiration">
                                <p>Routing</p>
                            </label>
                            <div class="input-group">
                                <div class="input-group-prepend">
                                    <span class="input-group-text"><i class="fa fa-calendar"
                                            aria-hidden="true"></i></span>
                                    <div class="el" id="routing"></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <br>
                <button type="button" id="btnACH" class="btn btn-info btn-sm">Make Payment</button>
            </div>
        </div>
    </div>
    </div>
    </div>
    </div>
</body>

PayFields will display the fields on the payment page inside each <div> element and apply the appropriate styles based on the id. Be sure to also create a <button> element with the ID that you set in the configuration step.

When the customer is finished entering data and clicks the submit button, the event listener will call the PayFields.submit(); function to send the payment information to Payrix for processing.

Handle the response

Payrix returns the results of the transaction using one of the following callback function:

  • PayFields.onSuccess = (response) => {} - Runs when the API responds with a successful transaction or token.

  • PayFields.onValidationFailure = () => {} - Runs when PayField validation fails before creating the API call.

  • PayFields.onFailure = (response) => {} - Runs when the API responds with a failed transaction or token.

  • PayFields.onFinish = (response) => {} - Runs when the API responds.

  • PayFields.onRestore = () => {} - Runs when the restore action is run.

Fill in each function body to define the behavior of the application for each possible type of response.

PayFields Actions

The table below defines all of the actions supported by the PayFields JavaScript library:

Action

Description

PayFields.submit();

Submits the PayFields data to Payrix.

PayFields.swipePopup();

Opens the card swipe popup.

PayFields.clearFields();

Clears all the values from the fields.

PayFields.clearFields(["number", "cvv"]);

Clears the values from the specified fields.

PayFields.appendTo("number", "#newElement");

Moves the field to a new DIV.

PayFields.reload();

Reappends the PayField with all existing values to the DIV only if the DIV has been removed.

PayFields.restore();

Restores the values if PayFields is moved to a new DIV.

PayFields.button = { element: "#submit", value: "Click to Submit" };

Displays a button in the specified element for submitting field data to Payrix .

PayFields.swipeButton = { element: "#swipe", value: "Click to Swipe"};

Displays a button in the specified element for opening the card swipe popup.

PayFields.onSuccess = (response) => {};

Callback function that runs when the API responds with a successful transaction or token.

PayFields.onValidationFailure = () => {};

Callback function that runs when validation fails before creating the API call.

PayFields.onFailure = (response) => {};

Callback function that runs when the API responds with a failed transaction or token.

PayFields.onFinish = (response) => {};

Callback function that runs when the API responds.

PayFields.onRestore = () => {};

Callback function that runs when the restore action is run.

PayFields.config.order = {order number};

Sets an order number for Level II/III processing.

PayFields.config.tax = {tax number};

Sets a tax ID number for Level II/III processing.

PayFields.config.dicount = {discount number};

Sets a discount value for Level II/III processing.

PayFields.config.shipping = {shipping number};

Sets a shipping number for Level II/III processing.

PayFields.config.duty = {duty number};

Sets an duty value for Level II/III processing.

PayFields.config.items = {items Object};

Adds an array of items to the order for Level II/III processing.

PayFields.config.billingAddress = {Billing Object};

Sets known values of the cardholders billing address without displaying them on the payment page.

PayFields.config.additionalData = {Additional Object};

Adds additional data to the order for Level II/III processing.

PayFields.config.invoiceResult = {Invoice Object};

Adds an invoice object to the order for Level II/III processing.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.