Using the Secure Fields Form

The Secure Fields Form is an HTML form that you can include in your site to collect a user’s card information.

When using the Secure Fields Form, PaymentsOS generates the card details input fields and handles the logic of grabbing the card information submitted by the user. This option further reduces your PCI scope compared to the JavaScript API, requiring you to be SAQ A compliant.

You can style the form as you desire. Here’s an example:

When card information is submitted through the Secure Fields Form, PaymentsOS returns a token representation of the card to your site. If you added additional fields to the form, then these fields are included in the token representation of the card as well. You must use the token when accepting payments.

Embedding the Secure Fields Form in a Checkout Page

The steps for embedding the Secure Fields Form in your checkout page are the following:

  1. Include the Secure Fields Javascript SDK in your checkout page. You can find the SDK at https://js.paymentsos.com/v3/latest/secure-fields.min.js.
<body>
  ...
  <script src="https://js.paymentsos.com/v3/latest/secure-fields.min.js"></script>
</body>
  1. Add a form with the input elements you want to show. The example below shows just three input fields: the card holder name, the credit card number and the card expiration date. Once you are familiar with the basic implementation steps, proceed to review the additional secure field types you can add.
<body>
  ...
    <form id="payment-form">
       <div class="field">
          <input id="cardholder-name" class="input empty" placeholder="John Doe" />
          <label>Name</label>
       </div>
       <div class="field">
          <div id="card-number" class="input empty"></div>
          <label>Card Number</label>
       </div>
       <div class="field">
          <div id="exp-date" class="input empty"></div>
          <label>Expiration Date</label>
       </div>
       <button type="submit" id="pay_button">Pay $25</button>
    </form>
 ...
</body>
  1. Now onto some vanilla Javascript. Create an instance of the secure fields by calling POS.fields(publicKey,options?). As the first argument, pass your public key from your Business Unit so that you can be authenticated. As the second argument, you can pass a list of custom fonts to be applied to the fields (this is optional).
/*
Create an instance of the secure fields. Pass the public key as the first argument. 
As the second argument, we'll pass a list of custom fonts to be applied to the fields (this is optional).
*/
const fonts = [
  {
    src: 'https://fonts.googleapis.com/css?family=Source+Code+Pro',
  }
]
const formElements = new POS.Fields("99346d84-5187-4221-9c16-dc51a8de27fa", {
  fonts
})
  1. Create an instance of each field you want to show in your form, by calling formElements.create(elementType,options?) with the type of field you want to instantiate and any additional options you want pass in. Then mount each field to the DOM.
/*
The placeholders object is just one example of an additional option you can pass when instantiating a field.
*/
const placeholders = {
    cardNumber: '1234 1234 1234 1234',
    expDate: 'MM / YY'
}

// Instantiate the fields you want to show and mount them to the DOM.
const cardNumber = formElements.create('cardNumber', {
    placeholders
})
cardNumber.mount('#card-number')

const expiry = formElements.create('creditCardExpiry', {
    placeholders
})
expiry.mount('#exp-date')

  1. Create a token by calling POS.createToken(elementType,additionalData) when the user submits the form, but not until we fetched the card holder’s name so that we can pass it in an additional data object to the POS.createToken(elementType,additionalData) call (the card holder name is a required field, so you cannot skip this step).
document.getElementById('payment-form').addEventListener('submit', async(event) => {
    event.preventDefault()
    const additionalData = {
        holder_name: document.getElementById('cardholder-name').value // This field is mandatory
    }
    const result = await POS.createToken(cardNumber, {
        additionalData,
        environment: 'test' // Set the PaymentsOS environment you're connecting to
    })
    console.log(`The response is ${JSON.stringify(result)}`)
})

Let’s piece it all together:

    <body>
      <div class="checkout-page">
          <form id="payment-form">
            <div class="field">
                <input id="cardholder-name" class="input empty" placeholder="John Doe" />
                <label>Name</label>
            </div>
            <div class="field">
                <div id="card-number" class="input empty"></div>
                <label>Card Number</label>
            </div>
            <div class="field">
                <div id="exp-date" class="input empty"></div>
                <label>Expiration Date</label>
            </div>
            <button type="submit" id="pay_button">Pay $25</button>
          </form>
      </div>
      <script src="https://js.paymentsos.com/v3/latest/secure-fields.min.js"></script>
      <script src="index.js"></script>
    </body>
  
    // This is our index.js file

    /*
    Create an instance of the secure fields. Pass the public key as the first argument. 
    As the second argument, we'll pass a list of custom fonts to be applied to the fields (this is optional).
    */
    const fonts = [
      {
        src: 'https://fonts.googleapis.com/css?family=Source+Code+Pro',
      }
    ]
    const formElements = new POS.Fields("99346d84-5187-4221-9c16-dc51a8de27fa", {
      fonts
    })


    /*
    Create an object holding additional options that you can pass to the constructor for instantiating 
    the credit card and card expiry fields.
    There are lots of other options available that you can pass to the constructor, 
    but to keep it simple we'll just show this one object in our example. 
    */
    const placeholders = {
        cardNumber: '1234 1234 1234 1234',
        expDate: 'MM / YY'
    }

    // Instantiate the fields you want to show and mount them to the DOM.
    const cardNumber = formElements.create('cardNumber', {
        placeholders
    })
    cardNumber.mount('#card-number')

    const expiry = formElements.create('creditCardExpiry', {
        placeholders
    })
    expiry.mount('#exp-date')

    /*
    Create a token when the user submits the form, but not until we fetched the card holder's name 
    so that we can pass it in an additional data object to the createToken call.
    */
    document.getElementById('payment-form').addEventListener('submit', async(event) => {
        event.preventDefault()
        const additionalData = {
            holder_name: document.getElementById('cardholder-name').value // This field is mandatory
        }
        const result = await POS.createToken(cardNumber, {
            additionalData,
            environment: 'test' // Set the PaymentsOS environment you're connecting to
        })
        console.log(`The response is ${JSON.stringify(result)}`)
    })
  

Secure Field Instantiation Options

When instantiating the secure fields using POS.fields(publicKey,options?), there are several options you can pass. These include a list of custom fonts, or the option to disable the luhn check done on a card number. For a list of available options, see the Secure Fields API reference.

Secure Field Types and Options

When walking you through the steps required to embed the Secure Fields Form in a checkout page, we settled for a bare-bones example that showed you how to instantiate the credit card number and the card expiration date fields. You’re not limited however to just those two field types. For an overview of all available types, see the Form Elements (Fields) reference.

Options for Instantiating Fields

Recall that you instantiate a field using formElements.create(elementType,options?). The second argument to this call is an object holding additional options, such as a placeholder for the card number:

const placeholders = {
    cardNumber: '1234 1234 1234 1234'
}

const cardNumber = formElements.create('cardNumber', {
    placeholders
})

There are more options you can choose from, however. For an overview of all available options, see the Form Elements (Fields) reference.

Validating User Input

The Secure Fields Form provides event listeners for events that are triggered when the value of an input field has been changed, if the field gets focus or if the field loses focus. They are called like so:

cardNumber.on('change', (event) => {
    console.log(event)
})

cardNumber.on('focus', (event) => {
    console.log(event)
})

cardNumber.on('blur', (event) => {
    console.log(event)
})

The event parameter of the callback function will return the following object (values are examples):

{
  bin: "510510", // the card's BIN
  complete: false, // wether the card data is inserted and valid
  brand: "visa", // only returned for card numbers
  empty: false, // whether the input field is empty
  error: undefined // an error object if an error occurred on input
}

If an error occurred, its object will look like this (values are examples):

{
  "cvv": "wrong length",
  "pan": "not luhn",
  "expiry": "passed"
}

Additional Methods

The are some additional methods that you can use on each type of input field (see the Form Elements (Fields) reference for a list of all available field types). Those methods are listed below.

Method Description
update(optionsObject) Updates the input field with the specified options. See the Form Elements (Fields) reference for a list of options you can pass.
clear() Clears the input field
destroy() Unmounts the input field from the DOM. You can call this method only once.

Styling the Secure Fields Form

You can style the secure fields by passing style or classes objects to the formElements.create(elementType,options?) call. The style object allows you to style the secure fields based on their state (valid input, no input or invalid input). The classes object allows you to apply custom classes to the div elements wrapping the input fields, giving you even more control over the styles that you can apply to the fields. Let’s take a look at both.

Applying Styles

Jump to the Style Objects Reference

The style object has nested objects, whose keys are the names of the input status (valid input, no input or invalid input) that a field can have. The exception is the nested base object; this object has styles that are inherited by the other objects. Here’s a basic example, with a base object and an invalid object holding styles to be applied if the user input is invalid:

const style = {
    base: {
        color: '#fff',
        fontWeight: 600,
        fontFamily: 'Quicksand, Open Sans, Segoe UI, sans-serif',
        fontSize: '16px',
        fontSmoothing: 'antialiased'
    },
    invalid: {
        color: '#FF0000'
    }
};

You can also add pseudo-classes and pseudo-elements for even more granular control over how the elements are styled:

const style = {
    base: {
        color: '#fff',
        fontWeight: 600,
        fontFamily: 'Quicksand, Open Sans, Segoe UI, sans-serif',
        fontSize: '16px',
        fontSmoothing: 'antialiased',
        ':focus': {
            color: '#424770',
        },

        '::placeholder': {
            color: '#9BACC8',
        },

        ':focus::placeholder': {
            color: '#CFD7DF',
        },
    },
    invalid: {
        color: '#FF0000',
        ':focus': {
            color: '#FA755A',
        },
        '::placeholder': {
            color: '#FFCCA5',
        },
    }
};

When you’re done styling, pass the style object to the formElements.create(elementType,options?) call like so:

const cardNumber = formElements.create('cardNumber', {
    style,
    ...
})

Applying Custom Classes

Jump to the Classes Object Reference

The classes object allows you to apply custom classes to the div elements wrapping the input fields, according to the input status (valid input, no input, invalid input or has focus) that a field can have. The classes object’s keys are the names of each type of input status. In the example below, we apply the my-own-invalid-class class to the input field if the user enters some invalid input.

const classes = {
    invalid: 'my-own-invalid-class'
}

If you do not pass a classes object, then default class names are applied (see the Classes Object Reference for an overview of the default class names).

When you’re done styling, pass the classes object to the formElements.create(elementType,options?) call like so:

const cardNumber = formElements.create('cardNumber', {
    classes,
    ...
})

What’s next?

Now that you’ve collected your customer’s card information, proceed to accept a payment.

Using the Secure Fields Form Version 2

The Secure Fields Form is an HTML form that you can include in your site to collect a user’s card information. When using this option, PaymentsOS generates the card details input fields and handles the logic of grabbing the card information submitted by the user. This option further reduces your PCI scope compared to the JavaScript API, requiring you to be SAQ A compliant.

You can style the form as you desire. Here’s an example:

When card information is submitted through the Secure Fields Form, PaymentsOS returns a token representation of the card to your site. If you added additional fields to the form, then these fields are included in the token representation of the card as well. You must use the token when accepting payments.

Embedding the Secure Fields Form in your Site

To get started, include the Secure Fields Javascript SDK in your checkout page. You can find the SDK at https://js.paymentsos.com/v2/latest/secure-fields.min.js. Also provide your public key to authenticate yourself by calling POS.setPublicKey().

<body>
  <script language="JavaScript" type="text/javascript" src="https://js.paymentsos.com/v2/latest/secure-fields.min.js"></script>
  <script>POS.setPublicKey("99346d84-5186-4221-9c16-dc51a8de27fb");
  </script>
  ...
</body>

Now embed the Secure Fields form and set your environment (either “test” or “live”) by calling POS.setEnvironment(). Then display the form’s fields by calling POS.initSecureFields(). As a last step, attach a click event to the form that is invoked when the form is submitted. Pass the event a function that will send the card information to PaymentsOS, tokenize the information and return the token to your site.

<body>
  ...
  <!-- Embed the form after loading the Secure Fields Javascript SDK and setting your public key -->
  <form id="payment-form">
    <input type="text" id="cardholder-name" placeholder="John Doe" />
    <div id="card-secure-fields">
      <!-- The payment form will be displayed here -->
    </div>
    <button type=”submit”>Pay</button>
  </form>

  <!-- After embedding the form, set your environment, initialize the form's fields
   and send the data to PaymentsOS when the form is submitted -->
  <script>

    // Set your environment. Values are either "test" or "live".
    // If omitted, the test environment will be used.
    POS.setEnvironment("test");

    // Initialize the form's fields
    POS.initSecureFields('card-secure-fields');

    // Attach a click event to the form that is invoked when the
    // form is submitted. On submit, pass the card information to
    // PaymentsOS and receive the token representing the card
    // information in your site.
    document.getElementById('payment-form').addEventListener('submit', function(event) {
      event.preventDefault();
      const additionalData = {
        holder_name: document.getElementById('cardholder-name').value // This field is mandatory
      }
      POS.createToken(additionalData, function(result) {

        // Grab the token here

      });
    });
  </script>
</body>

Adding Additional Fields to the Form

Depending on the provider that you are transacting against, you may need to add additional fields to the form. These fields will then be included in the token representing the customer’s card.

To add an additional field, simply add it as an input field to the form. Then include its key and value in the additionalData object. The key must be identical to the attribute name required by the Create Token API.

Here’s an example of adding number and type fields that define a user’s identity card.

<!-- Here's our payment form-->
<form id="payment-form">
  ...
  <input type="text" id="cardholder-name" placeholder="John Doe" />

  <!-- Add the additional fields as input fields to the form -->
  <input type="text" id="idnumber" placeholder="ID Number" />
  <input type="text" id="idtype" placeholder="Passport, Driver's License" />
  <div id="card-secure-fields">
    <!-- This is where the payment form will be displayed -->
  </div>
  <button type=”submit”>Pay</button>
</form>

<script>
  // Initialize the form’s fields
  POS.initSecureFields('card-secure-fields');

  document.getElementById('payment-form').addEventListener('submit', function(event) {
        event.preventDefault();
        const additionalData = {
          holder_name: document.getElementById('cardholder-name').value,

          // Add the additional field here. In this example, we are adding
          // identity document fields. Notice that the key is identity_document and that the value
          // is of type object.
          identity_document: {
            number: document.getElementById('idnumber').value,
            type: document.getElementById('idtype').value
          }
          POS.createToken(additionalData, function(result) {

            // Grab the token here

          });
        });
</script>

Configuring Form Options

You can configure a number of options that change the form’s behavior and appearance. For example, you can disable the security code input field or disable the Luhn check for validating a card’s number. You configure these options by calling the relevant method before initializing the form’s fields. Here’s an example:

<script>
...
// Disable the security number field
POS.disableSecurityNumber();
// Now initialize the fields
POS.initSecureFields('card-secure-fields');
</script>

The following table lists the options you can configure:

Option Set by calling:
Disable card formatting. This options disables auto-formatting of the credit card number into groups of digits. POS.disableCardFormatter();
Disable the card image field. This option prevents the card’s image from appearing. POS.disableCardImage();
Disable the security number (cvv, cvc etc.) field. When you set this option, the security number input field will not appear on the form. POS.disableSecurityNumber();
Disable the Luhn check for validating a card’s number. POS.disableLuhnValidation();
Set the card number’s input field placeholder text. Default placeholder text is “card number”. POS.setCardNumberPlaceholder("Your Text");
Set the expiration date’s input field placeholder text. Default placeholder text is “mm / yy”. POS.setExpirationDatePlaceholder("Date Format");
Set the fields' display direction from right to left. POS.setDirectionRtl();
Set the security code’s input field placeholder text. Default placeholder text is “CVV”. POS.setSecurityNumberPlaceholder("security code name");

Customizing the Form’s Look and Feel

Customizing the form’s look and feel is easy. Simply add a style constant in which you define the styles for the form’s input fields. Make sure to use camelCase for the style attributes (and not kebab-case, as you are accustomed to when writing css).

Here’s an example. Notice that the base attributes are common to all input fields. You need to call POS.setStyle() for your changes to take effect.

<script>

  // Make sure to use camelCase for the style attributes

  const style = {
    base: { // Common to all input fields
      color: 'green',
      fontWeight: 400,
      fontSize: '13px',

      // Here you can style the span element that wraps the secure fields.
      // The default values are shown below.
      secureFields: {
        position: absolute,
        top:0
      }

      // The Primary Account Number (PAN) field is always included in the form.
      // You can style it here.
      pan: {
        fontSize: '13px'
      },

      // The expirationDate field is always included in the form.
      // You can style it here.
      expirationDate: {
        color: 'blue',
        fontSize: '13px',
        // width: '70px'
      },

      // Unless you disable the cvv field, it will be included in the form.
      // You can style it here.
      cvv: {
        color: 'red',
        fontSize: '13px',
      }
    }
  };

  // Done styling? Let us know, so that we can apply your changes.
  POS.setStyle(style);

  // Make sure to initialize the fields after setting your styles
  POS.initSecureFields('card-secure-fields');
  ...
</script>

Validation Errors

The Secure Fields Form validates that the user provided a card holder name, as well as a valid card number (if Luhn validation is enabled) and a valid card expiration date. If validation fails for one of these, an object is returned with a category value of client_validation_error, a description indicating why the validation failed as well as more_info with additional information about the error.

Depending on the error, one of the following objects may be returned:

{
  category: "client_validation_error", 
  description: "Invalid PAN", 
  more_info: "Card number did not pass luhn validation"
}
{
  category: "client_validation_error", 
  description: "Invalid expiration date", 
  more_info: "expiration date have passed"
}
{
  category: "client_validation_error", 
  description: "Missing required parameters", 
  more_info: "holder_name field is mandatory"
}
Last modified August 27, 2023