PCI Vault Logo
Hosted PCD Forms

The most PCI compliant way to capture payment card data from a user or obtain payment card data stored in the vault is to store or retrieve it with a form that is not hosted by yourself, but by a PCI DSS Level 1 compliant vendor like PCI Vault. You can pull such a form into your own system or website by using an iframe or by opening the form in a separate browser window or tab.

These forms leverage PCI Vault's powerful capture endpoint and retrieval endpoint technology.

When using a hosted form to capture data and you would like to get the tokenization result from the form input via webhook, make sure to specify a webhook URL endpoint on the capture endpoint when you generate it.

PCI Vault's hosted forms range from very simple to very powerful. The simplest way to use a hosted form is by using one of PCI Vault's standard hosted forms.

Standard Hosted Form

The standard hosted form can be used as follows:

Capture

  1. Generate a capture endpoint, making sure to keep the unique_id and secret obtained from this step.
  2. Load the standard form using a URL with the unique_id and secret. For example, to use our standard payment card data hosted form, you can use https://api.pcivault.io/v1/capture/iframe/pcd?unique_id=your_unique_id_here&secret=your_secret_here

This URL can be used in the src attribute of an iframe or opened in a new browser tab. It should work out of the box, as long as you have a valid unique id and secret.

PCI Vault currently has 2 standard forms available for capture:

  1. For payment card data, use https://api.pcivault.io/v1/capture/iframe/pcd?unique_id=your_unique_id_here&secret=your_secret_here
  2. For bank accounts, use https://api.pcivault.io/v1/capture/iframe/ach?unique_id=your_unique_id_here&secret=your_secret_here

Retrieve

  1. Generate a retrieval endpoint, making sure to keep the unique_id and secret obtained from this step.
  2. Load the standard form using a URL with the unique_id, secret and the token-reference combination of the card data. For example, to use our standard payment card data hosted form, you can use https://api.pcivault.io/v1/retrieve/iframe/pcd?unique_id=your_unique_id_here&secret=your_secret_here&token=card_token_here&reference=card_reference_here

This URL can be used in the src attribute of an iframe or opened in a new browser tab. It should work out of the box, as long as you have a valid unique id and secret.

PCI Vault currently has 1 standard form available for retrieval:

  1. For payment card data, use https://api.pcivault.io/v1/retrieve/iframe/pcd?unique_id=your_unique_id_here&secret=your_secret_here&token=token_here&reference=reference_here

Configured Hosted From

PCI Vault also offers the abitlity to create a highly customisable form, where you can include your own JavaScript and CSS, allowing you to change the branding and behaviour.

The customisation options are as follows:

Attribute Description
form_type Type of form to be customized. pcd for payment card data or ach for bank account details. ("pcd" | "ach" | "custom")
mode How to render the form. standalone for a form with its own call to action or embedded for a form that can only be submitted programatically
form_id ID of the form. This ID must be unique on a system-wide level. If not specified, PCI Vault will generate one for you. (string)
css_links [1] Externally hosted CSS to modify the form appearance. (string)
js_links Externally hosted JavaScript to modify the form appearance and behavior. (string)
embedded_css [1] CSS to embed on the hosted form in a <style> attribute. (Base64 encoded string)
embedded_js JavaScript to embed on the hosted form in a <script> attribute. (Base64 encoded string)
force_keypad Force the use of a keypad with randomized buttons. (default: false) (boolean)
hide_card Toggle the rendered credit card animation on the pcd form. (default: false) (boolean)
disable_luhn Toggle card validation on the form. This works on the pcd form only. (default: false) (boolean)
strip_spaces Removes spaces from the credit card number. This works on the pcd form only. (default: false) (boolean)
field_options [2] Hides fields or disables validation on them. (object)
success_callback JavaScript function to call if the form has been submitted successfully. (Base64 encoded string)
error_callback JavaScript function to call if an error occurs on form submission. (Base64 encoded string)

When you generate such a form, it will have its own id and be publicly accessible. The process for creating and using such a form has 3 steps:

  1. Generate a capture endpoint, making sure to keep the unique_id and secret obtained from this step.
  2. Create your customised hosted form, making sure to keep the returned id value.
  3. Load the configured form using a URL with the form id and the capture endpoint unique_id and secret. For example: https://api.pcivault.io/v1/capture/iframe/form_id_here?unique_id=your_unique_id_here&secret=your_secret_here

When you access the form with the URL, you also have the following options that you can specify in the query string:

  • testing will cause the form to submit to api-stage.pcivault.io instead of api.pcivault.io if set to true.
  • title will set the page title if the form is displayed in a browser window or tab.
  • reference will load the form with the reference field (not visible to the user) already populated. This reference will be sent to the capture endpoint to allow easier retrieval.
  • Any other query string parameter will be added to an extra_data object, which will be submitted along with the form's data to PCI Vault.

Embedded mode

The form can be rendered either in standalone mode (default) or embedded mode.

When creating a hosted form with mode: "embedded", the control of the form is handed over to the parent frame. The submit button is no longer rendered inside the iframe and the parent window needs to handle the triggering of the form programatically.

Communication between the parent window and the iframe is done using the window.postMessage() method, which is the standard, secure way to handle cross-origin communication.

Sending messages to the iframe

Messages sent to the iframe are Javascript objects e.g.

  {
    type: "action",
    name: "submit"
  }

Reset the form

To reset the state and inputs of the form, the parent window needs to post the message:

  {
    type: "action",
    name: "reset"
  }

Usage Example:

  const triggerReset = () => {
    const frame = document.getElementById("hosted-form");
    frame.contentWindow.postMessage({type: "action", name: "reset"}, "https://api-stage.pcivault.io");
  };

Submit the form

To submit the form, the parent window needs to post the message:

  {
    type: "action",
    name: "submit"
  }

Usage Example:

  const triggerReset = () => {
    const frame = document.getElementById("hosted-form");
    frame.contentWindow.postMessage({type: "action", name: "reset"}, "https://api-stage.pcivault.io");
  };

Receiving messages from the iframe

Your page can react on messages sent from inside the iframe in order to handle integration seamlessly. An example scenario would be when the iframe form is busy submitting, the button that triggered it in the parent window can be disabled and a loader shown to the user.

Messages received by the parent window are Javascript objects e.g.

  {
    type: "state",
    name: "loading",
    value: true
  }

Handle loading state change

When the iframe's form loading state changes, a message is received in the parent window:

  {
    type: "state",
    name: "loading",
    value: true
  }

Usage Example:

  window.addEventListener("message", (event) => {
    if (event.data?.type === "state" && event.data?.name === "loading") {
      const isLoading = event.data.value || false;

      console.log("Loading state changed to", isLoading);
      if (isLoading) {
        // show loader
      } else {
        // hide loader
      }
    }
  })

Handle form validity state change

When the iframe's form validity state changes, a message is received by the parent window:

  {
    type: "state",
    name: "valid",
    value: false
  }

Usage Example:

  window.addEventListener("message", (event) => {
    if (event.data?.type === "state" && event.data?.name === "valid") {
      const isValid = event.data.value || false;
      console.log("Valid state changed to", isValid);
      // show an error message
    }
  })

Custom Hosted Form

PCI Vault can also host a custom form for you. This allows you to build a completely custom form using JavaScript, but have the form be hosted by PCI Vault in our PCI DSS Level 1 compliant environment.

To create a form like this, you can follow the same steps as in creating a Configured Hosted Form, except that you must use custom for the form type. You can put your JavaScript in the embedded_js field, or you can host it externally and link it with the js_links field.

To render the form, your JavaScript needs to add a function called custom_form to the DOM window object.

    window.custom_form = (element, options) => {
        // construct capture form here
    };

This function can take in 2 arguments. The first argument will be a JavaScript reference to a div element on which the form can be mounted. The second argument will be an object in this format:

{
    "submit_secret": "the_secret_specified_in_the_link_query",
    "submit_url": "/v1/capture/unique_id_here",
    "mode": "standalone",
    "force_keypad": false,
    "hide_card": false,
    "disable_luhn": false,
    "strip_spaces": false,
    "field_options": {},
    "reference": "unique_reference",
    "extra_data": {},
    "testing": false
}

Take note that the submit_url will be always in the format /v1/capture/{unique_id}. Your JavaScript function will have to prepend "https://api.pcivault.io" or "https://api-stage.pcivault.io", depending on the testing flag being set to true or false respectively.

The code that calls the JavaScript method looks like this:

window["custom_form"](document.getElementById("mount_form_element"), properties)

Using this option requires some development work, but it is also the most flexible. The form can be written in almost any front-end JavaScript framework, as long as the framework gives you a way to add a function to the window object.

For an example of how this can be done with React and Vite, see Custom Form Example. This example also uses the following other libraries:

  • React Bootstrap (to build the UI)
  • Formik (for form validation)
  • Axios (to submit the data to the capture endpoint)

Footnotes

  1. PCI Vault forms contain HTML ids in most of the form elements.

    The default forms only use html classes to apply styles, meaning that any style applied to the id will override the default style.Styling the elements by id is the most reliable way to style the form according to your needs. 2

  2. The field options must be a JSON object where the keys are the field names, and the values are themselves JSON objects with validate and visible as keys and true/false as values. Unspecified field names will be both visible and validated. If a field is specified without validate or visible in the object, the missing value be set to true unless visible is false, in which case validate will be false also.