Hosted Fields

Forter's Hosted Fields sit on the checkout page and intercept PCI sensative payment credentials.

Integration Steps

1. Install the SDK

Add the Hosted Fields SDK to your checkout page:

<script type="text/javascript" data-site-id="XXXXXXX" id="checkoutTools__script" src="https://sdk.checkouttools.com/v1.2/collect.js"> </script>

If using Content Security Policy (CSP), update your directives:

connect-src <https://sdk.checkouttools.com>  
frame-src <https://sdk.checkouttools.com>  
script-src <https://sdk.checkouttools.com>

2. Initialize the SDK

Generate a JWT token using the /client-key endpoint in the Tokenization API

Then, pass the token to the SDK when initializing:

const forterCollect = await window.checkoutTools.collect.init(
  {
    environment: 'sandbox',
    authToken: 'TOKEN.VALUE'
  }
);

3. Add Hosted Fields to the Checkout Page Form

Insert placeholder elements into your checkout page:

<form>  
  <div id="cc-holder"></div>    <!-- Name on card -->
  <div id="cc-number"></div>    <!-- Card number -->
  <div id="cc-exp"></div>       <!-- Expiration date -->
  <div id="cc-cvc"></div>       <!-- CVC -->
</form>

Initialize the Hosted Fields:

forterCollect.addFields({  
  'cc-holder': {
    type: 'CARD_HOLDER_NAME'
  },
  'cc-number': {
      type: 'CARD_NUMBER',
  },
  'cc-exp': {
    type: 'CARD_EXPIRATION_DATE',
  },
  'cc-cvc': {
    type: 'CARD_CVC',
  },
...
});

Required fields: CARD_NUMBER, CARD_HOLDER_NAME and CARD_EXPIRATION_DATE.

Each field ID must be unique and match its HTML container.


4. Submit the Form & Receive a Token

When the customer submits the form, call the submit() method to receive a single-use token.

const result = await forterCollect.submit();  
console.log(result)

Successful Response: (example)

{  
  "success": true,  
  "token": "ftr12d4e830283b647d4b3b2a3d65f02b8ab"  
}

JS SDK Reference

Init

Initializes the Forter Hosted Fields SDK.

Standard Initialization

init({environment, authToken}, [cb: (err, results)]) => Promise<void>

Description

Initialize the Forter Hosted Fields SDK.

Parameters

ParameterTypeRequiredDescription
environmentstringNoTokenization environment to use - "sandbox" | "production" (default: "sandbox")
authTokenstringYesAuthentication token retrieved from PCI Tokenization API

Example

const forterCollect = await checkoutTools.collect.init({
  environment: 'sandbox', 
  authToken: 'YOUR_AUTH_TOKEN'
});

Advanced Initialization

For more control over the SDK's behavior, you can provide additional configuration options and event handlers:

init({...options, ...eventHandlers}, [cb: (err, results)]) => Promise<void>

Description

This method returns a Promise that can be awaited and will surface any errors. Alternatively, you may provide an optional callback function which will be invoked asynchronously when the action completes.

Parameters

ParameterTypeRequiredDescription
optionsobjectYesConfiguration object
eventHandlersobjectNoObject containing event handler functions

Options

ParameterTypeRequiredDescription
environmentstringNoTokenization environment to use - "sandbox" | "production" (default: "sandbox")
authTokenstringYesAuthentication token retrieved from PCI Tokenization API
validationTriggerstringNoWhen to trigger fields validation.'ON_BLUR' | 'ON_CHANGE' (default: 'ON_BLUR')

eventHandlers

parameterTypeRequiredDescription
onLoad()NoTriggered when fields are loaded. Note: Only triggered on first load.
onError(errors: {[fieldName: string]: {message: string, errorCode:string} })NoTriggered on form validation errors
onEnterPress()NoTriggered when Enter key is pressed in any field
onEscapePress()NoTriggered when Escape key is pressed in any field
onSuccess()NoTriggered after successful form submission. Note: Consider showing a loading indicator until this event.
onValidityChange(fieldId:string, isValid:boolean, error?: {message: string, errorCode:string})NoTriggered when field validity changes
onCardBrandChange(cardBrand: string)NoTriggered when card brand is detected

Example

let formLoading = false;

const forterCollect = window.checkoutTools.collect.init({  
 onLoad() {  
   formLoading = true;  
 },  
 async onEnterPress() {  
   const tokenizeResult = await forterCollect.submit();  
   if (tokenizeResult.success) {  
     console.log('Form successfully submitted', tokenizeResult);  
   }  
 },  
 onError(errors){  
   console.log('Form submit error:', errors)  
 }  
});

Fields

Adds one or more Hosted Fields to the form.

Add Fields

addFields(fieldsDefinition, [cb: (err, results)]) => Promise<Void>

Description

Add one or more Hosted Fields to the form

Notes:

  • This method returns a promise that resolves when all Hosted Fields have finished loading and are ready for use. (See also: onLoad() event.
  • Alternatively, this method accepts an optional callback function which is invoked asynchronously once the action is completed.

Parameters

ParameterTypeRequiredDescription
fieldsDefinitionYes

Update Fields

updateFields(fieldsDefinition, [cb: (err, results)]) => Promise<Void>

Description

Update one or more Hosted Fields in the form.

Notes:

  • This method returns a promise that resolves when all Hosted Fields have finished loading and are ready for use. (See also: onLoad() event.
  • Alternatively, this method accepts an optional callback function which is invoked asynchronously once the action is completed.

Parameters

ParameterTypeRequiredDescription
fieldsDefinitionYes

Submit

submit(cb: (err, results)) => Promise<{status: boolean, token:string, errors?: Array<{message: string, errorCode:string}>}>

Description

Once the customer finishes entering all the relevant fields in the payment form, this method will submit them securely to be stored by Forter.

Notes:

  • This method returns a Promise object that can be awaited to receive the tokenized fields. It will return the tokenized payload if successful, or the field errors if the form is still in an invalid state.
  • Alternatively, this method accepts an optional callback function which is invoked asynchronously once the action is completed.
  • The asynchronous result of this function is a single token string, that can later be unpacked in the server side to the individual fields, or sent as is to a third party using the Forter Detokenization Proxy.
  • A successful tokenization does not execute a transaction or validation. In order to verify the payment method, you will need to invoke a purchase or authorization from your secure, server-side environment.

Reset Fields

reset(fieldName?: string, cb?: (err, results)) => Promise<Void>

Description

Reset all fields or a specific field in the form. If a field name is not provided, all of the fields will be reset.

Notes:

  • This method returns a Promise object that can be awaited.
  • Alternatively, this method accepts an optional callback function which is invoked asynchronously once the action is completed.

Parameters

ParameterTypeRequiredDescription
fieldNamestringNo

Focus

focus(fieldName?: string) => void

Description

Focus on a specific field in the form.

Parameters

ParameterTypeRequiredDescription
fieldNamestringNo

Styling

Forter Hosted Fields can mostly be styled using standard CSS rules and techniques. When customizing your field's styles, the required techniques will differ when styling the container element itself (i.e., the form control), or the input element. This separation is required because the wrapping container element is hosted on your page, and the input in another, secured, web app.

Container elements

Simply target the container elements you’ve created in HTML using the same CSS rules you apply to your other, non-hosted, form controls. This applies to macro layout like width, height, and spacing, and styling like border and box-shadow.

  1. <form>
        <label>
            Name on card
           <div id="card-holder-name" style="border: solid 1px red; height: 40px" />
        </label>
    </form>

Note: Even if your other inputs calculate their own height, Forter Hosted fields require an explicit ‘height’ to be set on the container element.

State classes

The following CSS rules are automatically added to the container element, which match the internal style “form states” mentioned above.

  1. forter-hosted-fields-focus
  2. forter-hosted-fields-valid
  3. forter-hosted-fields-invalid
  4. forter-hosted-fields-empty
  5. forter-hosted-fields-touched
  6. forter-hosted-fields-empty
  7. forter-hosted-fields-dirty

Simply reference these classes in your stylesheets as normal:

{
  .card-holder-name.forter-hosted-fields-focus {
    border: solid 2px blue;
  }
}

Input elements

In case advanced styling rules are required for the input elements themselves, additional css rules can be passed in to the javascript SDK object using the style configuration option.

Two types of styles can be used:

  1. A string containing an existing CSS class you may have already defined on your page used to style input elements. All CSS rules will be copied from this existing class and applied to the Hosted Field input element.
    await sdk.addFields({
      'card-number': {
        type: 'CARD_NUMBER',
        style: '.existing-form-input-class'  
      },
    });
  2. A configuration object containing custom css definitions. Accepted keys in this object are:
    1. input - Standard css properties that will be applied to the internal input element (See below for supported properties)
    2. Pseudo-classes (eg. :hover, :focus) - Nest additional rules for every html state
    3. Form state classes: Specific css classes are automatically applied to every Hosted Field, depending on its state. Every class can be styled using specific css properties.
      1. Supported state classes:
        .invalid - Field has failed validation. .empty - Field doesn't have a value. .touched - Applied forever once the field’s first ‘blur’ event has triggered, or first keystroke when the validationTrigger option is set to ON_CHANGE .dirty - Applied forever once the field’s value has changed for the first time. :focus - Field is currently focused Media queries - (These apply to the iframe dimensions) - define a rule in pixels and nest additional rules of the other formats inside
      2. Allowed CSS Properties (browser specific variants will also work): "appearance", "box-shadow", "color", "direction", "font", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-weight", "letter-spacing", "line-height", "margin", "margin-top", "margin-right", "margin-bottom", "margin-left", "opacity", "outline", "padding", "padding-top", "padding-right", "padding-bottom", "padding-left", "text-align", "text-shadow", "transition", "tap-highlight-color", "tap-highlight-color"
 
await sdk.addFields({
  'card-number': {
    type: 'CARD_NUMBER',
    style: {  
      'input': {  
       'color': 'black',  
       'padding': '10px 5px',  
      }  
      ':focus': {  
        'border-color': 'blue',  
      },  
      '.touched': {  
        'color: 'green',  
      },  
      '.touched.error': {  
        'color: 'orange',  
        'text-decorations': 'underline',  
      },  
      '@media screen and (max-width: 600px)': {  
         'input': {  
           'font-size': '10px'  
        }  
      },
    },
  }
});

Example: Full Credit Card Details Form

We’ll create a common form containing fields for collecting a credit card’s number, security code and expiration date, along with the customer’s name.

First create the HTML scaffolding - a form with placeholders elements that will late be replaced with Forter Hosted Fields


<body>
<form id="payment-form">
 <label>
   Name on card
   <div id="card-holder-name" />
 </label>
 <label>
   Card
   <div id="card-number" />
 </label>
 <label>
   CVC
   <div id="card-cvc" />
 </label>
 <label>
   Expiration date
   <div id="card-expiration" />
 </label>
</form>
</body>

Next, in a Javascript tag copy and paste the following

const forterCollect = await checkoutTools.collect.init();

const commonStyles = {  
  ":focus": {  
    color: "orange",  
  },  
  ".touched": {  
    color: "green",  
  },  
  ".touched.error": {  
    color: "red",  
    "text-decorations": "underline",  
  },  
};

forterCollect.addFields({  
  "card-holder-name": {  
    type: "TEXT",  
    placeholder: "Name on card",  
    style: commonStyles,  
  },  
  "card-number": {  
    type: "CARD_NUMBER",  
    placeholder: "1111-2222-3333-4444",  
    onFocus() {  
      // TODO: handle focus  
    },  
    style: commonStyles,  
  },  
  "card-cvc": {  
    type: "CARD_CVC",  
    onError(errorMessage) {  
      console.error("Error in field card-cvv", errorMessage);  
    },  
    style: {  
      ...commonStyles,  
      display: "inline-box",  
    },  
  },  
  "card-expiration": {  
    type: "CARD_EXPIRATION_DATE",  
    style: commonStyles,  
  },  
});

Finally, wire up the form’s ‘submit’ event to Forter’s ‘submit’ method in order to securely store the Form’s state

document  
 .getElementById("#payment-form")  
 .addEventListener("submit", function (e) {  
   e.preventDefault();

   // Callback based method:  
   forterCollect.submit(function (err, results) {  
     if (err) {  
       console.error("error submitting payment form", err);  
       return;  
     }

     console.log("payment form submitted successfully!", results);

     // Combine the tokenized fields along with other non-sensitive fields that may exist in the form, and submit them to your backend server for further processing.
     backend.submitPaymentForm({ fields: { ...ownFields, ...results } });

   });

   // or alternatively, ESNext promise based method:  
   forterCollect  
     .submit()  
     .then((results) => {  
       if (results.success) {  
         console.log("Form successfully submitted", tokenizeResult);  
       }  
       console.log("payment form submitted successfully!", results);  
       backend.submitPaymentForm({ fields: { ...ownFields, ...results } });  
     })  
     .catch((e) => {  
       console.error("error submitting payment form", e);  
     });  
 });

Example: Re-collecting CVC

The Hosted Fields sdk supports the collection of just the CVC. This is useful in repeat transactions, along with a multi-use token in order to reduce the risk of a fraud-decline.

See the Detokenization proxy docs for more information on how to use the resulting token.

const forterCollect = await checkoutTools.collect.init();

forterCollect.addFields({  
  "card-cvc": {  
    type: "CARD_CVC",  
    onError(errorMessage) {  
      console.error("Error in field card-cvv", errorMessage);  
    },  
  },  
});