Take Payments

SqPaymentForm Setup Guide

Embed Square's payment form on your website to securely collect credit card and digit wallet information.

SqPaymentForm generates an encrypted payment token (known as a nonce) that you can use with with Square's Transactions API to process online payments. This document provides guidance for embedding the Square Payment Form object (SqPaymentForm) on a custom webpage.

Prerequisites

To use the Square Payment Form, the following must be true:

  • You have a Square account. You can create a Square account in minutes from the signup page if you don't already have one.
  • Your eCommerce site sells products/services in line with Square's Terms of Service.
  • Your eCommerce site is hosted on a system that supports server-side processing for HTML forms (e.g., PHP, Ruby, ASP, Java pages). Hosting solutions that only support HTML pages cannot use SqPaymentForm to process payments.
  • You are using HTTPS. Credit card and Masterpass payments may be tested with SqPaymentForm on localhost without using HTTPS, but you must use HTTPS on a verified domain with Apple Pay for Web.
  • Your site visitors are using the current version of a modern, standard web browser.
  • Site visitors running Internet Explorer must use IE 10 (or later).

If you plan to use SqPaymentForm on your own eCommerce site and have not enabled payment processing on your account (or you're not sure), visit squareup.com/activate before continuing.

Assumptions

This guide makes the following assumptions:

Step 1: Update the <head> section of your payment page

To include the SqPaymentForm library and implementation files, add the following references to your payment page:

<!-- link to the SqPaymentForm library -->
<script type="text/javascript" src="https://js.squareup.com/v2/paymentform">
</script>

<!-- link to the local SqPaymentForm initialization -->
<script type="text/javascript" src="path/to/sqpaymentform.js">
</script>

<!-- link to the custom styles for SqPaymentForm -->
<link rel="stylesheet" type="text/css" href="path/to/sqpaymentform.css">

Each of the references serves a specific purpose:

  • js.squareup.com/v2/paymentform — Square's canonical Javascript library for SqPaymentForm. The payment form will not work without this reference.
  • sqpaymentform.js — a local Javascript file you create in Step 3 to configure and initialize the SqPaymentForm object.
  • sqpaymentform.css — a local CSS file (stylesheet) you create in Step 4 to customize the look of the payment form.

Step 2: Add the HTML form to your payment page

Use the example HTML form below to create a minimal payment form on your payment page.

<div id="sq-ccbox">
  <!--
    You should replace the action attribute of the form with the path of
    the URL you want to POST the nonce to (for example, "/process-card")
  -->
  <form id="nonce-form" novalidate action="path/to/payment/processing/page" method="post">
    Pay with a Credit Card
    <table>
    <tbody>
      <tr>
        <td>Card Number:</td>
        <td><div id="sq-card-number"></div></td>
      </tr>
      <tr>
        <td>CVV:</td>
        <td><div id="sq-cvv"></div></td>
      </tr>
      <tr>
        <td>Expiration Date: </td>
        <td><div id="sq-expiration-date"></div></td>
      </tr>
      <tr>
        <td>Postal Code:</td>
        <td><div id="sq-postal-code"></div></td>
      </tr>
      <tr>
        <td colspan="2">
          <button id="sq-creditcard" class="button-credit-card" onclick="requestCardNonce(event)">
            Pay with card
          </button>
        </td>
      </tr>
    </tbody>
    </table>

    <!--
      After a nonce is generated it will be assigned to this hidden input field.
    -->
    <input type="hidden" id="card-nonce" name="nonce">
  </form>
</div>

<div id="sq-walletbox">
  Pay with a Digital Wallet
  <div id="sq-apple-pay-label" class="wallet-not-enabled">Apple Pay for Web not enabled</div>
  <!-- Placeholder for Apple Pay for Web button -->
  <button id="sq-apple-pay" class="button-apple-pay"></button>

  <div id="sq-masterpass-label" class="wallet-not-enabled">Masterpass not enabled</div>
  <!-- Placeholder for Masterpass button -->
  <button id="sq-masterpass" class="button-masterpass"></button>
</div>

Remember to update the action parameter with the path to your payment processing page.

In addition to the iframe placeholders and support elements, the HTML sample includes two HTML elements that structure the payment form:

  • sq-ccbox — collects HTML elements related to credit card payments.
  • sq-walletbox — collects HTML elements related to digital wallet payments.

These objects are provided to help you group the payment form elements and are completely optional.

Step 3: Implement the SqPaymentForm object and functions

The SqPaymentForm object relies on AJAX to generate the requested payment nonce. To implement the form, you must define, and customize, the expected callback functions, form triggers, and form styles.

Create a Javascript file, sqpaymentform.js, using the following coding template:

// Set the application ID
var applicationId = "";

// Set the location ID
var locationId = "";

/*
 * function: requestCardNonce
 *
 * requestCardNonce is triggered when the "Pay with credit card" button is
 * clicked
 *
 * Modifying this function is not required, but can be customized if you
 * wish to take additional action when the form button is clicked.
 */
function requestCardNonce(event) {

  // Don't submit the form until SqPaymentForm returns with a nonce
  event.preventDefault();

  // Request a nonce from the SqPaymentForm object
  paymentForm.requestCardNonce();
}

// Create and initialize a payment form object
var paymentForm = new SqPaymentForm({

  // Initialize the payment form elements
  applicationId: applicationId,
  locationId: locationId,
  inputClass: 'sq-input',

  // Customize the CSS for SqPaymentForm iframe elements
  inputStyles: [{
      fontSize: '.9em'
  }],

  // Initialize Apple Pay placeholder ID
  applePay: {
    elementId: 'sq-apple-pay'
  },

  // Initialize Masterpass placeholder ID
  masterpass: {
    elementId: 'sq-masterpass'
  },

  // Initialize the credit card placeholders
  cardNumber: {
    elementId: 'sq-card-number',
    placeholder: '•••• •••• •••• ••••'
  },
  cvv: {
    elementId: 'sq-cvv',
    placeholder: 'CVV'
  },
  expirationDate: {
    elementId: 'sq-expiration-date',
    placeholder: 'MM/YY'
  },
  postalCode: {
    elementId: 'sq-postal-code'
  },

  // SqPaymentForm callback functions
  callbacks: {

    /*
     * callback function: methodsSupported
     * Triggered when: the page is loaded.
     */
    methodsSupported: function (methods) {

      var applePayBtn = document.getElementById('sq-apple-pay');
      var applePayLabel = document.getElementById('sq-apple-pay-label');
      var masterpassBtn = document.getElementById('sq-masterpass');
      var masterpassLabel = document.getElementById('sq-masterpass-label');

      // Only show the button if Apple Pay for Web is enabled
      // Otherwise, display the wallet not enabled message.
      if (methods.applePay === true) {
        applePayBtn.style.display = 'inline-block';
        applePayLabel.style.display = 'none' ;
      }
      // Only show the button if Masterpass is enabled
      // Otherwise, display the wallet not enabled message.
      if (methods.masterpass === true) {
        masterpassBtn.style.display = 'inline-block';
        masterpassLabel.style.display = 'none';
      }
    },

    /*
     * callback function: createPaymentRequest
     * Triggered when: a digital wallet payment button is clicked.
     */
    createPaymentRequest: function () {

      var paymentRequestJson ;
      /* ADD CODE TO SET/CREATE paymentRequestJson */
      return paymentRequestJson ;
    },

    /*
     * callback function: validateShippingContact
     * Triggered when: a shipping address is selected/changed in a digital
     *                 wallet UI that supports address selection.
     */
    validateShippingContact: function (contact) {

      var validationErrorObj ;
      /* ADD CODE TO SET validationErrorObj IF ERRORS ARE FOUND */
      return validationErrorObj ;
    },

    /*
     * callback function: cardNonceResponseReceived
     * Triggered when: SqPaymentForm completes a card nonce request
     */
    cardNonceResponseReceived: function(errors, nonce, cardData, billingContact, shippingContact) {
      if (errors) {
        // Log errors from nonce generation to the Javascript console
        console.log("Encountered errors:");
        errors.forEach(function(error) {
          console.log('  ' + error.message);
        });

        return;
      }

      alert('Nonce received: ' + nonce); /* FOR TESTING ONLY */

      // Assign the nonce value to the hidden form field
      document.getElementById('card-nonce').value = nonce;

      // POST the nonce form to the payment processing page
      document.getElementById('nonce-form').submit();

    },

    /*
     * callback function: unsupportedBrowserDetected
     * Triggered when: the page loads and an unsupported browser is detected
     */
    unsupportedBrowserDetected: function() {
      /* PROVIDE FEEDBACK TO SITE VISITORS */
    },

    /*
     * callback function: inputEventReceived
     * Triggered when: visitors interact with SqPaymentForm iframe elements.
     */
    inputEventReceived: function(inputEvent) {
      switch (inputEvent.eventType) {
        case 'focusClassAdded':
          /* HANDLE AS DESIRED */
          break;
        case 'focusClassRemoved':
          /* HANDLE AS DESIRED */
          break;
        case 'errorClassAdded':
          /* HANDLE AS DESIRED */
          break;
        case 'errorClassRemoved':
          /* HANDLE AS DESIRED */
          break;
        case 'cardBrandChanged':
          /* HANDLE AS DESIRED */
          break;
        case 'postalCodeChanged':
          /* HANDLE AS DESIRED */
          break;
      }
    },

    /*
     * callback function: paymentFormLoaded
     * Triggered when: SqPaymentForm is fully loaded
     */
    paymentFormLoaded: function() {
      /* HANDLE AS DESIRED */
    }
  }
});

Step 4: Implement SqPaymentForm default styles

Create a stylesheet, sqpaymentform.css, using the following CSS template:

/* Define how SqPaymentForm iframes should look */
.sq-input {
  border: 1px solid rgb(223, 223, 223);
  outline-offset: -2px;
  margin-bottom: 5px;
  display: inline-block;
}

/* Define how SqPaymentForm iframes should look when they have focus */
.sq-input--focus {
  outline: 5px auto rgb(59, 153, 252);
}

/* Define how SqPaymentForm iframes should look when they contain invalid values */
.sq-input--error {
  outline: 5px auto rgb(255, 97, 97);
}

/* Customize the "Pay with Credit Card" button */
.button-credit-card {
  min-width: 200px;
  min-height: 20px;
  padding: 0;
  margin: 5px;
  line-height: 20px;
  box-shadow: 2px 2px 1px rgb(200, 200, 200);
  background: rgb(255, 255, 255);
  border-radius: 5px;
  border: 1px solid rgb(200, 200, 200);
  font-weight: bold;
  cursor:pointer;
}


/* Customize the "{{Wallet}} not enabled" message */
.wallet-not-enabled {
  min-width: 200px;
  min-height: 40px;
  max-height: 64px;
  padding: 0;
  margin: 10px;
  line-height: 40px;
  background: #eee;
  border-radius: 5px;
  font-weight: lighter;
  font-style: italic;
  font-family: inherit;
  display: block;
}

/* Customize the Apple Pay on the Web button */
.button-apple-pay {
  min-width: 200px;
  min-height: 40px;
  max-height: 64px;
  padding: 0;
  margin: 10px;
  background-image: -webkit-named-image(apple-pay-logo-white);
  background-color: black;
  background-size: 100% 60%;
  background-repeat: no-repeat;
  background-position: 50% 50%;
  border-radius: 5px;
  cursor:pointer;
  display: none;
}

/* Customize the Masterpass button */
.button-masterpass {
  min-width: 200px;
  min-height: 40px;
  max-height: 40px;
  padding: 0;
  margin: 10px;
  background-image: url(https://static.masterpass.com/dyn/img/btn/global/mp_chk_btn_147x034px.svg);
  background-color: black;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  background-position: 50% 50%;
  border-radius: 5px;
  border-color: rgb(255, 255, 255);
  cursor:pointer;
  display: none;
}

#sq-walletbox {
  float:left;
  margin:5px;
  padding:10px;
  text-align: center;
  vertical-align: top;
  font-weight: bold;
}

#sq-ccbox {
  float:left;
  margin:5px;
  padding:10px;
  text-align: center;
  vertical-align: top;
  font-weight: bold;
}

The CSS classes define the default presentation of the payment form.

Step 5: Set your application and location ID

SqPaymentForm will not load properly unless the applicationId and locationId variables are set properly.

We recommend using sandbox IDs for testing and development. To get your sandbox IDs:

  1. Open your Application Dashboard.
  2. Click on the application you want to use for the payment form.
  3. On the Credentials tab of the application control panel, copy the Sandbox Application ID.
  4. On the Locations tab of the application control panel, copy one of the Location ID values from the list of Sandbox locations.

Now update sqpaymentform.js with the application and location IDs:

 1// Set the application ID
 2var applicationId = "";
 3
 4// Set the location ID
 5var locationId = "";
 6
 7// Create and initialize a payment form object
 8var paymentForm = new SqPaymentForm({
 9  ...
10});

Step 6: Test the payment form

The example HTML, Javascript, and CSS should run without modification once the application and location IDs are set. To confirm the form renders properly and verify nonce generation succeeds for credit cards, open your new payment page. You should see a minimal HTML page:

Basic setupform

If your page does not look similar to the screenshot above, follow the steps under Troubleshooting the payment form and try again.

Start by filling in the Pay with a Credit Card form with a credit card number that includes non-numeric characters (e.g., A53B759734545858). SqPaymentForm performs basic real-time validation on information entered in the iframe fields. The .sq-input--error CSS class will be applied to the "Card Number" field to highlight the error.

Now fill in the Pay with a Credit Card form with test card information and click "Pay with Card":

  • Card Number: 4532759734545858
  • CVV: any three non-consecutive numbers
  • Expiration Date: any month and year in the future
  • Postal Code: 94103

An alert should appear that displays the nonce obtained by SqPaymentForm from Square's servers. If an alert doesn't appear, check the browser's Javascript console for information about the error encountered.

Step 7: Enable (or disable) digital wallet payments

SqPaymentForm supports nonce-generation for digital wallets. The sample code provided in this guide includes visual placeholders for the digital wallets to simplify development and testing.

The wallet placeholders should be removed by fully enabling (or disabling) the digital wallets before putting the payment form in production.

Enable digital wallet functionality

If you want to accept digital wallet payments, you will need to fully enable the functionality in line with the the wallet provider's requirements. See the wallet-specific guides below for guidance on configuring those payment options.

Disable functionality for specific wallets

If you want to disable digital wallet payments for a specific digital wallet, you will need to remove the associated HTML placeholder, SqPaymentForm parameter, and CSS objects. See the wallet-specific guides below for guidance on disabling digital wallet functionality.

Completely disable digital wallet functionality

If you want to disable ALL digital wallet payments:

1. Follow the wallet-specific instructions to disable each individual wallet:

2. Remove the entire sq-walletbox HTML block from your payment page:

<div id="sq-walletbox">
  ...
</div>

3. Disable the createPaymentRequest callback function in sqpaymentform.js:

/*
 * callback function: createPaymentRequest
 * Triggered when: a digital wallet payment button is clicked.
 *
 * createPaymentRequest: function () {},
 */

4. Disable the validateShippingContact callback function in sqpaymentform.js:

/*
 * callback function: validateShippingContact
 * Triggered when: a shipping address is selected/changed in a digital
 *                 wallet UI that supports address selection.
 *
 * validateShippingContact: function (contact) {}
 */

Optional: Remove the postal code requirement

For merchants based outside those locations, the postal code requirement can be removed by setting the postalCode element to false in the object configuration:

 1// Create and initialize a payment form object
 2var paymentForm = new SqPaymentForm({
 3
 4  ...
 5
 6  postalCode: false,
 7
 8  // SqPaymentForm callback functions
 9  callbacks: {
10    ...
11  }
12});

Optional: Customize cardNonceResponseReceived()

The cardNonceResponseReceived callback function includes an errors parameter that provides information about why nonce generation may have failed. We strongly recommend customizing cardNonceResponseReceived to provide feedback to customers about why their payment cannot be processed based on the provided error code.

For more information on the errors parameter and possible error codes, see the errors, see the SqPaymentForm Overview.

Optional: Customize validateShippingContact()

The validateShippingContact callback function includes a contact parameter that provides information about the shipping address selected through a supported digital wallet UI. We strongly recommend customizing validateShippingContact to confirm the shipping information is valid and provide feedback to customers about why the merchant may be unable to ship to the provided address.

For more information on the contact parameter and the required format for shipping address validation errors, see the validateShippingContact section of the SqPaymentForm Overview.

Optional: Customize unsupportedBrowserDetected()

If SqPaymentForm does not support a client's browser, it calls unsupportedBrowserDetected during initialization. We strongly recommend customizing unsupportedBrowserDetected to provide feedback when a visitor's browser is not supported that encourages them to update their browser.

Optional: Detect Unsupported Browsers early

Unsupported browsers may be detected before instantiating SqPaymentForm with the SqPaymentForm.isSupportedBrowser() method:

if (SqPaymentForm.isSupportedBrowser()) {
  var paymentForm = new SqPaymentForm({ ... });
} else {
  // browser not supported
}

Optional: Customize paymentFormLoaded()

The paymentFormLoaded callback function can be used to populate the postal code element or take other actions unrelated to the payment form once the form is fully loaded.

Use paymentForm.setPostalCode to set the postal code based on information previously entered (e.g., from a billing address). For example:

 1  // SqPaymentForm callback functions
 2  callbacks: {
 3
 4    ...
 5
 6    /*
 7     * callback function: paymentFormLoaded
 8     * Triggered when: SqPaymentForm is fully loaded
 9     */
10    paymentFormLoaded: function() {
11      paymentForm.setPostalCode("POSTAL CODE FROM SHIPPING");
12    }
13  }
14});

Setting postalCode programmatically will make entering payment information more convenient for your customers.

Calling paymentForm.setPostalCode outside paymentFormLoaded will fail, even if the form has fully loaded. A successful call to paymentForm.setPostalCode also triggers the postalCodeChanged input event in the inputEvenReceived callback function.

NOTE: To preserve PCI compliance and ensure credit card information is collected securely, you cannot programmatically populate payment form fields other than the postal code.

For more information on possible input event types, see the SqPaymentForm Overview.

Optional: Customize SqPaymentForm styles

SqPaymentForm input fields are embedded in iframes. Styles for the rendered payment form are specified in two ways:

 1  // Initialize the payment form elements
 2  applicationId: applicationId,
 3  locationId: locationId,
 4  inputClass: 'CSS-CLASS-NAME',
 5
 6  // Customize the CSS for SqPaymentForm iframe elements
 7  inputStyles: [{
 8      INPUTSTYLE OBJECT
 9  }],

Exterior Styles

Styles for the exterior of each text input (e.g., border, margins, element width) are defined in the SqPaymentForm stylesheet (sqpaymentform.css) and assigned in two ways:

  • placeholder IDs — SqPaymentForm will respect normal CSS inheritance for styles defined using a DOM object ID (e.g., #sq-card-number).
  • inputClassSqPaymentForm explicitly applies the configured CSS class to all text input fields.

SqPaymentForm also applies classes when it detects a onFocus event or encounters a validation error. The appropriate CSS class is derived from the name provided for inputClass:

  • When a text input has focus, SqPaymentForm applies the {{CSS-CLASS-NAME}}--focus class to the iframe.
  • When a text input has basic validation errors (e.g., the form is submitted with incomplete data), SqPaymentForm applies the {{CSS-CLASS-NAME}}--error class to the iframe.

You can create CSS rules for these class names to highlight inputs that have focus and/or validation errors.

Interior Styles

Styles for the interior of each text input (e.g., font family, background color) are defined as InputStyle objects for the inputStyles parameter of the SqPaymentForm object. For example:

inputStyles: [

  // Because this object provides no value for mediaMaxWidth or mediaMinWidth,
  // these styles apply for screens of all sizes, unless overridden by another
  // input style below.
  {
    fontSize: '24px',
    padding: '3px'
  },

  // These styles are applied to inputs ONLY when the screen width is 400px
  // or smaller. Note that because it doesn't specify a value for padding,
  // the padding value in the previous object is preserved.
  {
    mediaMaxWidth: '400px',
    fontSize: '18px',
  }
],

For more information on InputStyle objects and how they are applied to SqPaymentForm elements, see the SqPaymentForm Overview.

Optional: Programmatically focusing form fields

Once the payment form is loaded, you can use paymentForm.focus('FIELD') to focus a particular field. For example, you might want to automatically focus the card number field as soon as the form is ready:

  callbacks: {
    ...
    /*
     * callback function: paymentFormLoaded
     * Triggered when: SqPaymentForm is fully loaded
     */
    paymentFormLoaded: function() {
      paymentForm.focus("cardNumber");
    }
  }
});

You can call .focus() on cardNumber, cvv, expirationDate, and postalCode. Calling .focus() on any other form field will return an error.

Troubleshooting

A. SqPaymentForm will not generate form fields on a multi-page web application

In most cases, SqPaymentForm automatically generates form fields on your webpage when you initialize it. If the payment form isn't loading properly, confirm you have properly set the application and location IDs:

 1// Set the application ID
 2var applicationId = "";
 3
 4// Set the location ID
 5var locationId = "";
 6
 7// Create and initialize a payment form object
 8var paymentForm = new SqPaymentForm({
 9  ...
10});

If you have set the application ID and location ID but the form still isn't loading properly, verify your application ID is correct. The Application Dashboard provides two sandbox credentials, a Sandbox Application ID and a Sandbox Access Token. These values are not interchangeable, so make sure you are using a valid sandbox application ID.

B. SqPaymentForm will not generate form fields on a single-page web application

By default, SqPaymentForm automatically generates its fields when it detects a DOMContentLoaded event. This event may not be triggered in single-page web applications when the form is initialized long after the DOMContentLoaded event has fired.

To manage the payment form initialization manually, set the autoBuild configuration option to false, and add the following function call to the page where you want to initialize the payment form:

paymentForm.build();

Calling paymentForm.build() when SqPaymentForm has already rendered the iframe fields will log an error to the Javascript console.

C. SqPaymentForm listeners persisting on a single-page web application

The SqPaymentForm object registers multiple event listeners on your webpage. These listeners go away when control is passed to a new page, but if you have a single-page web application, those listeners might remain longer than you want.

To manually remove the listeners from your webpage, add the following function call where you want to clean up after the payment form:

paymentForm.destroy();
Prev
< SqPaymentForm Overview
Next
Transactions API Overview >

Ask for help on Stack Overflow or join our Slack channel