Bank Info Tokenization Guide
Overview
Compared to Card's PCI DSS compliance requirements, bank information such as account numbers and routing numbers are not as sensitive. However, it is still recommended to use our tokenization service to securely store and process bank data. This guide will walk you through the process of tokenizing bank information.
How Tokenization Works for Bank Info
For bank info, we will tokenize and encrypt the bank info of the users on the client side and send it to our servers. The information should be encrypted on-transit and at-rest. The tokenized bank info will be stored in our servers and can be used for future transactions.
Steps to Tokenize a Bank Info
Step 1: Setup Variables
This step initializes the essential configuration needed for the tokenization process:
TOKEN: Your public key for authenticationPAGE_ROOT_URL: The base URL of the payment servicePAGE_URL: The specific URL for the payment field iframe
const ENV_VARS = {
TOKEN: 'a743ca68-a550-47a2-b171-adde1840c31e', // Public Key
PAGE_ROOT_URL: 'https://demo.ngnair.com',
PAGE_URL: 'https://demo.ngnair.com/ach-field',
}
Step 2: Setup Event Listeners
Three critical event handlers are implemented:
- onEvent: General purpose event handler for monitoring form interactions
- onToken: Processes the tokenization response, storing:
- accountNumber: The bank account number tokenized
- routingNumber: The bank routing number
- accountType: The bank account type (checking/savings)
- holderType: The account holder type (personal/business)
- Message Event Listener: Manages communication between iframe and parent window
// Generic event handler
const onEvent = (event, data) => {
console.log(event, data);
}
// Token event handler
const onToken = (data) => {
console.log(data);
if (data.accountNumber) {
APP_STATE.accountNumber = token.accountNumber;
APP_STATE.routingNumber = token.routingNumber;
APP_STATE.accountType = token.accountType;
APP_STATE.holderType = token.holderType;
}
};
// Setup message listener
document.addEventListener('DOMContentLoaded', () => {
window.addEventListener("message", function(event) {
if (event.origin !== ENV_VARS.PAGE_ROOT_URL) return;
const eventType = event.data.type;
const data = event.data.data;
switch (eventType) {
case 'event': onEvent(data.event, data.data); break;
case 'token': onToken(data); break;
case 'error': onEvent(data); break;
}
});
setIFrameURL();
});
Step 3: Create and Configure iFrame
The iFrame setup involves:
- URL Generation: Creates a unique URL with:
- Random hash for security
- Custom form labels configuration
- Optional fields settings
- Custom CSS styling
- iFrame Implementation: Embeds the payment form in your page
const getIFrameURL = () => {
const baseURL = ENV_VARS.PAGE_URL;
if (!baseURL) return '';
const hash = Math.random().toString(36).substring(7);
// Customize form labels and optional fields
const settingsString = JSON.stringify({
labels: {
// these are all optionals
accountNumber: 'Account Number',
routingNumber: 'Routing Number',
accountType: 'Account Type',
holderType: 'Holder Type',
},
});
// Custom CSS for the form
const cssString = `
#ach-parent {
background-color: gray;
}
#accountNumber {
color: red;
}
`;
const url = new URL(baseURL);
url.searchParams.append('hash', hash);
url.searchParams.append('settings', settingsString);
url.searchParams.append('css', cssString);
return url.toString();
}
const setIFrameURL = () => {
const iframe = document.getElementById('payFrame');
iframe.src = getIFrameURL();
}
Sample View

Sample Token Response
This is a sample data as received from the onToken function:
{
"accountNumber": "eyJlbmNyeXB0ZWQiOiJhN2VkYjFjMWM2MjVhYmNhMmRjYjYyNTEyMmM4NjBhNiIsImVwaGVtZXJhbFB1YmxpY0tleSI6IjA0NzQzNGNhMzRjZjI0Mzg0YTg4OTMxYmEwNzE2NGJlMzhjZjVmMThiOWNkNDFmNjE5MDZhYzMzYTg2ZWNjZDY0OTJjYmJkMzhjMDNiNzk5NGIwMjFmMTdlNDk4M2U2ZWRiZGFjYmY0NjA0YTNiMzQzOGYyMjUyZTFkNjg5NDk0YWQiLCJhdXRoVGFnIjoiZWUyM2YzYzk5YWExYTgxNzk4ODdjZmM2ODc1YmU5N2UiLCJzYWx0IjoiMjM4MjExMmRkYWMyMGQxOTc0ZDczMTg3ZWYyMWE0NmJlOGE5ODY1ZjBlZWI1Y2ZiMjQxNTc5MzMyOGIyZTU5MyJ9", // JWT tokenized of the account number including other fields
"routingNumber": "111111111",
"accountType": "CHECKING",
"holderType": "PERSONAL"
}
All of the tokeni response fields are important for use when processing payments.
Complete Implementation Example
Here's a full HTML implementation combining all the steps:
<!DOCTYPE html>
<html>
<head>
<title>Bank Info Tokenization Example</title>
</head>
<body>
<div id="payment-container">
<iframe id="payFrame" frameborder="0" width="100%" height="250px"></iframe>
</div>
<script>
// Environment configuration
const ENV_VARS = {
TOKEN: 'a743ca68-a550-47a2-b171-adde1840c31e',
PAGE_ROOT_URL: 'https://demo.ngnair.com',
PAGE_URL: 'https://demo.ngnair.com/ach-field',
};
// Application state
const APP_STATE = {
accountNumber: null,
routingNumber: null,
accountType: null,
holderType: null
};
// Event handlers
const onEvent = (event, data) => {
console.log('Form Event:', event, data);
};
const onToken = (data) => {
console.log('Received Token:', data);
if (data.accountNumber) {
APP_STATE.accountNumber = data.accountNumber;
APP_STATE.routingNumber = data.routingNumber;
APP_STATE.accountType = data.accountType;
APP_STATE.holderType = data.holderType;
console.log('Token stored in APP_STATE:', APP_STATE);
}
};
// iFrame URL generator
const getIFrameURL = () => {
const baseURL = ENV_VARS.PAGE_URL;
if (!baseURL) return '';
const hash = Math.random().toString(36).substring(7);
const settings = {
labels: {
accountNumber: 'Account Number',
routingNumber: 'Routing Number',
accountType: 'Account Type',
holderType: 'Holder Type'
}
};
const cssString = `
#ach-parent {
background-color: gray;
}
#accountNumber {
color: red;
}
`;
const url = new URL(baseURL);
url.searchParams.append('hash', hash);
url.searchParams.append('settings', JSON.stringify(settings));
url.searchParams.append('css', cssString);
return url.toString();
};
// Initialize iFrame
const setIFrameURL = () => {
const iframe = document.getElementById('payFrame');
iframe.src = getIFrameURL();
};
// Setup event listeners
document.addEventListener('DOMContentLoaded', () => {
window.addEventListener("message", function(event) {
if (event.origin !== ENV_VARS.PAGE_ROOT_URL) return;
const eventType = event.data.type;
const data = event.data.data;
switch (eventType) {
case 'event': onEvent(data.event, data.data); break;
case 'token': onToken(data); break;
case 'error': onEvent(data); break;
}
});
setIFrameURL();
});
</script>
</body>
</html>