BR-DGE Hosted Fields

Hosted Fields enables you to outsource all of your cardholder data handling to BR-DGE, allowing your platform to qualify for the simplest PCI-DSS SAQ level.

Hosted Fields achieves this by collecting the most sensitive cardholder data using iFrames hosted by BR-DGE.

BR-DGE then converts the data into a token that can be safely handled by your servers, allowing you to maintain the simplest levels of PCI qualification. This means your customers' card data will never touch your servers.

The token generated by the hosted fields can then be used by your back-end services to generate a payment using the REST API Payments Endpoint.

Prerequisites

Before following this guide you should first ensure you have setup the main JavaScript client. Please follow the Comcarde JavaScript Client setup before continuing with this guide.
Once this has been completed you can add the Hosted Fields module to your webpage.

Using the Hosted Fields Module

Add the hosted fields module to your page

First, add the correct hosted-fields.min.js script to your checkout page. Using a HTML <script> tag.

🚧

The Production and Sandbox environments use different scripts. Ensure you source the correct script for each environment

<script src="https://assets.comcarde.com/web/v2/js/hosted-fields.min.js"></script>
<script src="https://sandbox-assets.comcarde.com/web/v2/js/hosted-fields.min.js"></script>

Creating Placeholder HTML Elements

So that the hosted-fields can be injected into your website you need to insert placeholder <div> elements with a special id into your checkout page.
You can then position these to fit in with your website design.

The hosted-fields module will find the elements based on their id, and inject the relevant <iframe>.

Hosted Fields will look for the <div> elements with the following id.

  • card-number
  • cvv
  • expiration-date

Create the <div> elements like below.

<div id="card-number"></div>
<div id="cvv"></div>
<div id="expiration-date"></div>

Additionally, you can provide labels for the hosted fields.

<label for="card-number">Card Number</label>
<div id="card-number"></div>

<label for="cvv">CVV</label>
<div id="cvv"></div>

<label for="expiration-date">Exp. Date</label>
<div id="expiration-date"></div>

Adding the Hosted Fields functionality to your page

After setting up your placeholder <div> and adding the Comcarde JavaScript Client you should have some JavaScript that looks similar to the below:

comcarde.client.create(
  {
    authorization: yourClientAPIKey, // Your Client API Key generated in the BR-DGE Portal
  },
  function (clientErr, clientInstance) {
    if (clientErr) {
      console.error(clientErr)
      return
    }

    // You will add the hosted fields functionality in here
    
  }
)

You now need to add the Hosted Fields specific functionality to the Comcarde JavaScript Client.

The following JavaScript example shows how you can achieve adding this functionality to your checkout page.

comcarde.client.create(
  {
    authorization: yourClientAPIKey, // Your Client API Key generated in the BR-DGE Portal
  },
  function (clientErr, clientInstance) {

    comcarde.hostedFields.create( // Create an instance of the Hosted Fields
      {
        client: clientInstance,
        styles: {
          /* 
          * Apply your styling options to the hosted fields
          * For more information on Hosted Fields styling, and the supported options
          * check out https://docs.br-dge.io/docs/hosted-fields-styling
          */     
        },
        fields: {
          number: {
            selector: '#card-number',
            placeholder: 'xxxx xxxx xxxx xxxx',
          },
          cvv: {
            selector: '#cvv',
            placeholder: 'xxx',
          },
          expirationDate: {
            selector: '#expiration-date',
            placeholder: 'MM/YYYY',
          },
        },
      },
      function (hostedFieldsErr, hostedFieldsInstance) {
        
        if (hostedFieldsErr) {
          console.error(hostedFieldsErr)
          return
        }

        hostedFieldsInstance.on('validityChange', function (event) {
          var field = event.fields[event.emittedBy]
          if (field.isValid) {
            // handle valid case
          } else if (field.isPotentiallyValid) {
            // handle potentially valid case
          } else {
            // handle invalid case
          }
        })

       /*
        * Hosted Fields can also listen on the following events
        */

        form.addEventListener(
          'submit',
          function (event) {
            event.preventDefault()

         /*
          * Cardholder name, issue number, and start date can optionally also be
          * passed to the tokenize operation. This data can safely be collected
          * via fields hosted by merchants without requiring more than PCI DSS SAQ A
          * accreditation.
          *
          * This can be useful if your BR-DGE account is configured with Payment
          * Service Provider connections that require cardholder names.
          */
            hostedFieldsInstance.tokenize(
              {
                cardholderName: 'John Smith',
                issueNumber: '01',
                startDate: '01/19',
              },
              function (tokenizeErr, payload) {
                if (tokenizeErr) {
                  console.error(tokenizeErr)
                  return
                }
                   /* 
                    * Calling the `tokenize` function will create a multi-use token
                    * that you can use in place of raw card data when making 
                    * a payment request to the /v1/payments API endpoint
                    * 
                    * https://docs.br-dge.io/reference/createpaymentusingpost
                    * 
                    * The `payload` object will match the response schema 
                    * for the /v1/payment-instruments API endpoint
                    * 
                    * https://docs.br-dge.io/reference/tokenizeinstrument
                    * 
                    * The multi-use token is the value returned in `payload.token`.
                    * You pass this token back to your server to make the payment request
                    */

                if (payload.metadata) {
                  var metadata = payload.metadata
                    /*
                    * When you tokenise a card using hosted fields
                    * BR-DGE will attempt to return metadata for this card. 
                    * 
                    * The structure of payload.metadata 
                    * will follow the `CardMetadata` schema from the BR-DGE REST API
                    * 
                    * See the BIN/IIN Lookup section of this guide 
                    * for more information on card metadata, how to extract it, 
                    * and the structure of the metadata response.
                    * 
                    */
                }
              }
            )
          },
          false
        )
      }
    )
  }
)

Hosted Fields supports certain styling options. Please see Hosted Fields Styling for more details.

Hosted Fields Events

You can subscribe to Hosted Fields events using an event listener. This allows you to update the UI of your form based on the state of the fields. These events include:

Event NameDescription
focusEmitted when a field gains focus.
blurEmitted when a field loses focus.
emptyEmitted when a field transitions from having data to being empty.
notEmptyEmitted when a field transitions from being empty to having data.
cardTypeChangeEmitted when the possible card type has changed.
validityChangeEmitted when the validity of a field changes.

Example:

hostedFieldsInstance.on('validityChange', function (event) {
  console.log(event.emittedBy, 'validity')
})

hostedFieldsInstance.on('focus', function (event) {
  console.log(event.emittedBy, 'has been focused')
})

hostedFieldsInstance.on('blur', function (event) {
  console.log(event.emittedBy, 'has lost focus')
})

BIN/IIN Lookup

Hosted Fields supports on-the-fly Bank Identification Number (BIN) lookup.
When the first nine digits of a card number are entered into the card-number element, hosted fields will return metadata for the specified BIN.

The information returned follows the CardMetadata schema of the BR-DGE REST API.

"cardMetadata": {
  "cardBrand": "VISA",
  "issuer": "ACMEBANK",
  "type": "DEBIT",
  "category": "CLASSIC",
  "countryIsoA2": "GB",
  "commercial": true
}

Enable BIN Lookup

To enable BIN Lookup set the binLookup flag to true when initialising the Hosted Fields module:

comcarde.hostedFields.create({
  ...
  binLookup: true, // Enable BIN lookup
  ...
});

How to use the BIN lookup feature

Once enabled, configure a callback that will handle the card metadata object each time the first 9 digits of a card number is entered into the Hosted Fields.

The below example details how to setup the callback, and how you can extract specific values from the cardMetadata object.

hostedFieldsInstance.on('binLookup', (cardMetadata) => {

  var cardIssuer = cardMetadata.issuer
  var cardType = cardMetadata.type
  var cardCategory = cardMetadata.category
  var cardCountry = cardMetadata.countryIsoA2
  var isCommercialCard = cardMetadata.commercial

})

📘

For more information on the data returned in the BIN Lookup, please see the CardMetadata schema in the BR-DGE REST API.

Card on File

Card on File can further streamline your online checkout experience. We recommend reading about the BR-DGE Vault before continuing.

Creating a Card on File

Once Credentials On File Mandate requirements relating to cardholder consent have been met, the tokenize method can be configured to create a Card on File.
When calling the tokenize method with customerAgreedToSaveCard: true BR-DGE will create a multi-use token that you can store in place of raw card data for use in other transactions.

hostedFieldsInstance.tokenize({
   'customerAgreedToSaveCard': true,
   'customerId': ..., // Your unique identifier for this customer
   ...
}, function(tokenizeErr, payload) {
   /*
    *
    * The multi-use token is the value returned in `payload.token`. 
    * You pass this token back to your server to make the payment request
    * 
    * The full `payload` object will match the response schema 
    * for the /v1/payment-instruments API endpoint
    * 
    * https://docs.br-dge.io/reference/tokenizeinstrument
    * 
    */
  }
});

Using a Card on File

When using a Card on File in payments we recommend exchanging the multi-use token for a single-use token in your client application, then using the single-use token in payment requests.

This step is entirely optional, and you can make a payment request with a multi-use token if you wish.

Multi-Use Token to Single-Use Token

Call tokenizeSavedCard with the multi-use token associated to the card your customer selects. This will create a single-use token linked to the multi-use token.
You can then use this single use token in the payment request.

comcarde.client.create({
  authorization: yourClientAPIKey, // Your Client API Key generated in the BR-DGE Portal
}, function(clientErr, clientInstance) {
  ...
  comcarde.hostedFields.create({
    client: clientInstance,
    ...
  }, function(hostedFieldsErr, hostedFieldsInstance) {
    ...

      form.addEventListener('submit', function(event) {
      event.preventDefault();
      event.preventDefault();

      hostedFieldsInstance.tokenizeSavedCard({
        'token': YourCustomersMultiUseToken // The multi-use token associated to your customers card
      }, function(tokenizeErr, payload) {
       /*
        * The single-use token is the value returned in `payload.token`. 
        * You pass this token back to your server to make the payment request
        * 
        * The full `payload` object will match the response schema
        * for the /v1/payment-instruments API endpoint
        * 
        * https://docs.br-dge.io/reference/tokenizeinstrument
        * 
        */
      });
    }
  })
};
Multi-Use Token to Single-Use Token with CVV

For security reasons, we do not store card verification values (CVVs), but you can optionally collect CVVs and temporarily associate them with single-use tokens.

If you wish to collect CVVs, first add a div to contain a CVV field hosted by BR-DGE:

<label for="save-card-cvv">CVV</label>
<div id="save-card-cvv"></div>

Then configure the hosted fields module to collect CVVs, and call tokenizeSavedCard with the multi-use token for the saved card your customer selects:

comcarde.client.create({
  authorization: yourClientAPIKey, // Your Client API Key generated in the BR-DGE Portal
  }, function(clientErr, clientInstance) {
  ...
    comcarde.hostedFields.create({
      client: clientInstance,
      ...
      fields: {
      ...
        saveCardCvv: {
          selector: '#save-card-cvv',
          placeholder: 'xxx'
        }
      }
    }, function(hostedFieldsErr, hostedFieldsInstance) {
      ...
      
      form.addEventListener('submit', function(event) {
      event.preventDefault();

        hostedFieldsInstance.tokenizeSavedCard({
        'token': YourCustomersMultiUseToken // The multi-use token associated to your customers card
        }, function(tokenizeErr, payload) {
       /*
        * The single-use token is the value returned in `payload.token`. 
        * You pass this token back to your server to make the payment request
        * 
        * The full `payload` object will match the response schema 
        * for the /v1/payment-instruments API endpoint
        * 
        * https://docs.br-dge.io/reference/tokenizeinstrument
        * 
        */
        });
      }
    });
  });

Visa Installments

Visa Installments is an optional extension to our hosted fields module that allows issuers to offer installment plans to their cardholders.

🚧

Using Visa Installments requires that your retail channels are configured to support it.
Please get in contact with support to enable this feature.

At a high level this works by:

  1. A customer enters their card details
  2. If Visa Installments is enabled on your BR-DGE account and your customer uses a Visa card we may return an array of Visa Installment plans you can offer to your customer.
  3. Use the data provided within the visaInstallmentPlans array to build a UI to display different plan options to their customers.
  4. If your customer selects a plan and agrees to the terms and conditions you can call hostedFieldsInstance.tokenizeVisPlan to generate a token that can be used as a payment instrument in payment requests by your server.
  5. You will receive a settlement for the full amount similar to a card payment.
  6. The Installments agreement and the servicing of that agreement are between the issuer and their cardholder and does not involve the merchant.

Enable Visa Installments

Add additional configuration to your hostedFields configuration, comcarde.hostedFields.create should be extended with a visaInstallments object that contains an amount and currencyCode:

// Configure hostedFields
comcarde.hostedFields.create({
  ...
  visaInstallments: {
    amount: "10000", // example of the amount to be paid (in cents)
    currencyCode: "USD" // example of transaction's currency
  }
  ...
});

Tokenize your Customer's card

📘

Installment Plans will only be returned for eligible VISA customers.

Use our hosted fields tokenize functionality as you would normally. If the card is eligible you may receive an array of visaInstallmentPlans in the response to calling hostedFieldsInstance.tokenize.

Please get in contact with support for information on how to present Visa Installment plans to your customers.

Example array of visaInstallmentPlans:

[
  {
    "planId": "3fa...a6",
    "name": "Plan name",
    "type": "ISSUER_PROMOTION",
    "numberOfInstallments": 0,
    "installmentFrequency": "WEEKLY",
    "termsAndConditions": [
      {
        "url": "https://dev...sa.com/support",
        "version": 0,
        "text": "Sample terms and conditions text",
        "languageCode": "eng"
      }
    ],
    "promotionInfo": {
      "promotionCode": "A2",
      "promotionID": "MBANK12"
    },
    "costInfo": {
      "annualPercentageRate": 320,
      "feeInfo": [
        {
          "type": "CONSUMER",
          "ratePercentage": 150,
          "flatFee": 1000
        },
        {
          "type": "UPFRONT_FEES",
          "ratePercentage": 150
        }
      ],
      "totalPlanCost": 61299,
      "totalFees": 500,
      "totalUpfrontFees": 100,
      "totalRecurringFees": 20,
      "firstInstallment": {
        "installmentFee": 123112,
        "amount": 123112,
        "upfrontFee": 123112
      },
      "lastInstallment": {
        "installmentFee": 123112,
        "amount": 123112
      },
      "currency": "USD"
    }
  },
  {
    "planId": "f73676d0-999d-09b7-3581-1963c7c63d02",
    "name": "TestX",
    "type": "ISSUER_DEFAULT",
    "numberOfInstallments": 3,
    "installmentFrequency": "MONTHLY",
    "termsAndConditions": [
      {
        "url": "",
        "version": 6,
        "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        "languageCode": "eng"
      }
    ],
    "promotionInfo": {
      "promotionCode": "",
      "promotionID": ""
    },
    "costInfo": {
      "annualPercentageRate": 0,
      "feeInfo": [
        {
          "type": "CONSUMER",
          "ratePercentage": 0,
          "flatFee": 0
        },
        {
          "type": "CONSUMER_UPFRONT",
          "ratePercentage": 200,
          "flatFee": 0
        }
      ],
      "totalPlanCost": 12592,
      "totalFees": 247,
      "totalUpfrontFees": 247,
      "totalRecurringFees": 0,
      "firstInstallment": {
        "installmentFee": 0,
        "amount": 4115,
        "upfrontFee": 247
      },
      "lastInstallment": {
        "installmentFee": 0,
        "amount": 4115
      },
      "currency": "USD"
    }
  }
]

👍

For more information, please see the VisaInstallmentMatchedPlan schema in the BR-DGE REST API OpenAPI specification.

Tokenize Selected Installment Plan

Once the customer has selected and accepted the terms and conditions of an installment plan we then create a new token that can be used as by your server as a Payment Instrument in a payment request.

To do this we have extended hosted fields with a tokenizeVisPlan function, this should be called with:

  • The token from the original card tokenization
  • The selected planId
  • The version of the termsAndConditions that the customer has accepted
const token = '95ea954e-e02b-4275-a614-fe4ef55c510e' // Token from card tokenization
const planId = 'f73676d0-999d-09b7-3581-1963c7c63d02' // Visa Installment Plan ID
const termsAndConditionsVersionNumber = 6 // Version of accepted terms and conditions

hostedFieldsInstance.tokenizeVisPlan(
  { token, planId, termsAndConditionsVersionNumber },
  function (tokenizeErr, tokenizePayload) {
    if (tokenizeErr) {
      throw tokenizeErr
    }
    // send tokenizePayload.token to your server to be used as a tokenized payment
    // instrument in a payment request.
  }
)