Integration

Set up a secure form

Let's start! First and foremost, include the JS file in your application. You can just add <script> element to your application or use npm module to load the script:

With the introduction of PCI DSS version 4.0, a new requirement has been put forth to ensure the integrity of scripts that run on payment pages. Script Integrity is crucial in maintaining the security and trustworthiness of online payment systems, as any unauthorized modifications to these scripts could potentially lead to data breaches or fraudulent activities. To meet this requirement, organizations must implement mechanisms to verify the integrity of each script utilized on their payment pages. To get a hash of a specific version, visit this page.

<script type="text/javascript" src="https://js.verygoodvault.com/vgs-collect/3.2.2/vgs-collect.js" integrity="sha384-YXvleED0q049Gx5rqUHI/hOTud/jKaLiL757lVq26oVFAd9SjTDHBoOviWw6XmPo" crossorigin="anonymous"></script>

Then build a form. In your HTML code, create an empty wrapper element with a unique identifier. This element defines the place where the iframe would be inserted. The identifier doesn't have to be the same as in the example below; you can specify any attribute value that would fit your project naming convention.

Example:

<form id="cc-form">
  <div class="form-group">
    <label for="cc-number">Card number</label>
    <span id="cc-number">
      <!--VGS Collect.js iframe for card number field will be here!-->
    </span>
   </div>
 <!--Submit credit card form button-->
 <button type="submit">Submit</button>
</form>

To help you visualize the fields and get more usage and configuration examples check out our Storybook.

Alternatively, we provide components that can be used ina React application:

Form initialization

Use the following code to initialize the VGS Collect.js form and create the form instance. You can have multiple secure forms on the page. It's required to specify the organization vault id you would like to send data to and the environment of the chosen vault.

Example:

const form = VGSCollect.create('<VAULT_ID>', '<ENVIRONMENT>', (state) => {});

The form state object returned in the callback represents valuable information about each field. You can track validation errors, focus and blur states, and even more.

Create and setup form fields

You should initialize each field in a form using the code below. VGS Collect will create the iframe for each initialized field. The library provides multiple built-in types of inputs as well as native HTML types.

Built-in custom secure input types:

  • card-number

  • card-expiration-date

  • card-security-code

  • ssn

  • zip-code

Built-in native secure input types: text, checkbox, file, dropdown, password, textarea.

form.field('#space-for-my-field', {
  name: 'cc-number',
  type: 'card-number',
  successColor: '#3c763d',
  errorColor: '#a94442',
  placeholder: 'Card number',
  validations: ['required', 'validCardNumber'],
  autoComplete: 'cc-number',
  css: {
    'color': '#31708f',
    'line-height': '1.5rem',
    'font-size': '24px',
  }
});

Handling field loading state

Since Collect.js version 2.1.0, you can easily monitor the loading state of each field. We recommend disabling your "submit" button until all fields are loaded; otherwise, a user would be able to make a submit request, and it may lead to unexpected results.

const submitButton = document.getElementById('#submit-button');
submitButton.setAttribute('disabled', 'true');
const name = form.field('#space-for-my-field', {
    type: 'text',
    name: 'holder_name',
    validations: ['required'],
});
const code = form.field('#space-for-my-field', {
    type: 'text',
    name: 'code',
    validations: ['required'],
});

Promise.all([name.promise, code.promise]).then(function () {
    submitButton.removeAttribute('disabled');
})

You can always get the current loading status of the field using field.loadingState. Possible values: loading, loaded, failed.

Field validation

You can set up multiple validation rules based on your needs and requirements. Use errorMessages key in the form state to track down validation error messages for each field.

We do not change the error message text, so you can rely on it in order to overwrite the validation message the library provides.


form.field('#space-for-my-field', {
  name: 'cc-number',
  type: 'card-number',
  validations: ['required', 'validCardNumber'],
});\n
form.field('#space-for-my-field', {
  name: 'cc-cvc',
  type: 'card-security-code',
  validations: ['required', 'validCardSecurityCode']
});\n
form.field('#space-for-my-field', {
  name: 'cc-exp',
  type: 'card-expiration-date',
  validations: ['required', 'validCardExpirationDate']
});

Field update

You might need to dynamically change the configuration of an existing Field instance. For this use case, in Collect.js 2.5.0, we added Field.update method. Field.update accepts an object with the properties that should be updated.

List of properties that can be updated: validations placeholder ariaLabel options css hideValue autoComplete disabled readOnly showCardIcon

const cvvField = form.field("#cc-cvv", {
  type: 'card-security-code',
  name: 'cvc',
  hideValue: true
})

onCvvVisibilityChange((isVisible) => {
  cvvField.update({
    hideValue: !isVisible
  })
});

Events

The library provides the following event handling methods: .on(), .off(), .once().

Form event example:

const form = VGSCollect.create('<VAULT_ID>','<ENVIRONMENT>', function () {})

form.on('enterPress', (info: EnterPressData) => { submitForm(); })

Field event examples:

const field = form.field('#ssn', {
  type: 'ssn',
  name: 'ssn',
  validations: ['required', 'validSSN'],
});

field.on('focus', (event) => { console.log(event) });
field.off('focus', (event) => { console.log(event) });

field.on('blur', (event) => { console.log(event) });
field.off('blur', (event) => { console.log(event) });

Form submit

form.submit('/', {
  data: {
    customerEmail: '[email protected]',
  },
  headers: {
  'x-application': 'MyApplication 2.8.3',
  },
  }, function(status, response) {
    console.log("Response has been received", status, response);
  }, function(errors) {
      // errors object:
      //{
      //  <invalid field name>: {
      //    <field state>
      //  },
      //}
  }
);

VGS Collect.js and Cookies

If you would like to pass cookies to your server along with the request made from the Collect.js form, make sure you've done all the steps from the list below:

  • You can't share cookies across domains. You may share across subdomains. Matching rules for the domain require the cookie Domain to match the host to which the request is being made. Configure and use CNAME in your integration with Collect.js. Your application and API must have the same origin; otherwise, the browser will not attach them to the request. Custom Hostnames allow making a Vault accessible at a non-VGS domain name (for example, www.customdomain.com). So any requests made through VGS will now reflect your domain alias. Example: .myawesomesite.com - your application domain. .vgs.myawesomesite.com - CNAME configured and used as a request URL domain.

  • Add additional withCredentials: true property in the form.submit()configuration object which will indicate that the request should be made using credentials such as cookies or authorization headers: form.submit('/my-endpoint', { ..., withCredentials: true}, callback, errorCallback)

  • Make sure you have added SameSite=None and Secure attributes to the Set-Cookie header: Set-Cookie: flavor=choco; Domain=.myawesomesite.com; Secure; HttpOnly; SameSite=None

  • Please also check that the server responds with the Access-Control-Allow-Credentials header. Responding with this header true means that the server allows cookies (or other user credentials) to be included on cross-origin requests.

Custom request body

Let's assume you have configured a Collect.js form with two fields: card-number and card-cvv, but you want them to be nested under the card.details property in your request, and additionally send the cardholder's name. Here's how you can do it:

form.submit('/post', {
  data: (formValues) => {
    return {
      card: {
        cardholder: 'John',
        details: {
          card_number: formValues['card-number'],
          card_cvv: formValues['card-cvv'],
        }
      }
    }
  }
});
// JSON request body generated on the form submission:
// card: {
//  cardholder: 'John',
//  details: {
//    card_number: '4111111111111111',
//    card_cvv: '123'
//  }
//}

The argument in the callback has the following structure:

{
  <field_name_1>: { __type: 'vgs-key', key: '<filed_name_1>'},
  <field_name_2>: { __type: 'vgs-key', key: '<filed_name_2>'},
}

By indicating __type: 'vgs-key' library knows that we should replace this placeholder with a real form value.

Please use .index(i: number) method to access nth element of an array. Example: formValues.images.index(0)

Setup inbound route

To secure data via the VGS Collect.js form, you should create an inbound route for the fields you want to secure. You can follow our Getting Started guide to find information about how to set up an inbound route properly or add a new filter to an existing route.

VGS Collect with CNAME

Go to the Vault Settings on the Dashboard and add a Custom Hostname, then click on the Activate for SDKs button.

Custom hostnames

Once the CNAME is turned on, specify the custom hostname domain using .useCname() the method, and you're all set. Now, traffic will go through the defined CNAME.

Example:


const form = VGSCollect.create('<VAULT_ID>', '<ENVIRONMENT>', (state) => {})
                       .useCname('my-cname.com');
  

Last updated