Card Payment Integration Guide
Overview
This guide walks you through integrating NGnair's secure card payment solution into your website. Our solution uses an iframe-based approach that handles card data securely, eliminating the need for PCI DSS compliance on your end.
How It Works
The integration works by embedding a secure payment form hosted by NGnair within an iframe on your website. This form handles all sensitive card data collection while providing a seamless user experience. When a payment is processed, you receive a payment ID that can be used for subsequent operations.
Integration Steps
Step 1: Setup Configuration
Initialize the essential configuration needed for the payment integration:
MERCHANTID: Your unique merchant identifierPAGE_ROOT_URL: The base URL of the NGnair payment servicePAGE_URL: The specific URL for the payment field iframe
const ENV_VARS = {
MERCHANTID: 'MID-840-025-2025-000035',
PAGE_ROOT_URL: 'http://local.ngnair.com:3001',
PAGE_URL: 'http://local.ngnair.com:3001/cardglp-field',
}
Step 2: Setup Event Handlers
The integration requires three main event handlers:
- onEvent: General purpose event handler for form interactions
- onToken: Processes the payment response, containing the payment ID
- Message Event Listener: Manages secure communication between the iframe and your website
// Token response handler
const onToken = (data) => {
console.log(data);
// Handles payment response with structure:
// {
// "paymentID": "PMT_da40ccf1-ecf8-42f0-aebd-e77faaae033e"
// }
};
// 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: Configure the Payment Form
The payment form configuration involves:
- URL Generation: Creates a unique URL with:
- Random hash for security
- Custom form styling
- Form labels configuration
- Custom Styling: Modern, responsive design with dark mode support
const getIFrameURL = () => {
const baseURL = ENV_VARS.PAGE_URL;
if (!baseURL) return '';
const hash = Math.random().toString(36).substring(7);
const settingsString = JSON.stringify({
labels: {
cardNumber: 'Number Card',
expiryDate: 'Expiry',
cvv: 'CVV',
},
styles: {
input: {
borderRadius: '5px',
borderColor: '#4B5563',
focusBorderColor: '#60A5FA',
padding: '12px',
marginBottom: '20px',
backgroundColor: '#000',
color: '#fff'
},
button: {
borderRadius: '5px',
borderColor: '#60A5FA',
textColor: '#60A5FA',
hoverBgColor: '#60A5FA',
hoverTextColor: '#1F2937',
padding: '12px',
margin: '10px',
fontSize: '17px',
backgroundColor: '#1F2937'
},
label: {
fontSize: '14px',
fontWeight: '500',
color: '#E5E7EB',
marginBottom: '8px'
},
font: {
family: "'Roboto Mono'",
style: "normal",
weight: "200",
display: "swap",
src: "url(https://fonts.gstatic.com/s/robotomono/v22/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_Xvq_ROW4.woff2) format('woff2')",
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
}
}
});
const url = new URL(baseURL);
url.searchParams.append('hash', hash);
url.searchParams.append('settings', settingsString);
url.searchParams.append('merchantID', ENV_VARS.MERCHANTID);
return url.toString();
}
Complete Implementation
Here's a full implementation that:
- Creates a responsive payment form
- Handles payment processing securely
- Provides a modern, dark-mode UI
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sample NGnair Payments Embedded Pay</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
html {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, sans-serif;
background-color: #111827;
}
</style>
<script>
const ENV_VARS = {
MERCHANTID: 'MID-840-025-2025-000035',
PAGE_ROOT_URL: 'http://local.ngnair.com:3001',
PAGE_URL: 'http://local.ngnair.com:3001/cardglp-field',
}
document.addEventListener('DOMContentLoaded', () => {
onLoad();
});
const onToken = (data) => {
console.log(data);
/* expect data like this
{
"paymentID": "PMT_da40ccf1-ecf8-42f0-aebd-e77faaae033e"
}
*/
};
const getIFrameURL = () => {
const baseURL = ENV_VARS.PAGE_URL;
if (!baseURL) {
return '';
}
const hash = Math.random().toString(36).substring(7);
const settingsString = JSON.stringify({
labels: {
cardNumber: 'Number Card',
expiryDate: 'Expiry',
cvv: 'CVV',
},
styles: {
input: {
borderRadius: '5px',
borderColor: '#4B5563',
focusBorderColor: '#60A5FA',
padding: '12px',
marginBottom: '20px',
backgroundColor: '#000',
color: '#fff'
},
button: {
borderRadius: '5px',
borderColor: '#60A5FA',
textColor: '#60A5FA',
hoverBgColor: '#60A5FA',
hoverTextColor: '#1F2937',
padding: '12px',
margin: '10px',
fontSize: '17px',
backgroundColor: '#1F2937'
},
label: {
fontSize: '14px',
fontWeight: '500',
color: '#E5E7EB',
marginBottom: '8px'
},
font: {
family: "'Roboto Mono'",
style: "normal",
weight: "200",
display: "swap",
src: "url(https://fonts.gstatic.com/s/robotomono/v22/L0xuDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_Xvq_ROW4.woff2) format('woff2')",
unicodeRange: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
}
}
});
const url = new URL(baseURL);
url.searchParams.append('hash', hash);
url.searchParams.append('settings', settingsString);
url.searchParams.append('merchantID', ENV_VARS.MERCHANTID);
return url.toString();
}
const setIFrameURL = () => {
const iframe = document.getElementById('payFrame');
iframe.src = getIFrameURL();
}
function onLoad() {
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();
}
function handleReset() {
setIFrameURL();
}
</script>
</head>
<body>
<div>
<iframe src="#" width="100%" height="350px" id="payFrame" class="p-4 bg-gray-900"></iframe>
</div>
</div>
</body>
</html>
Sample Payment Response
When a payment is successfully processed, you'll receive a response in this format:
{
"paymentID": "PMT_da40ccf1-ecf8-42f0-aebd-e77faaae033e"
}
The paymentID can be used in subsequent API calls to reference this payment transaction.
Customization Options
The payment form supports extensive customization through the settings parameter:
- Labels: Customize form field labels
- Styling: Modify colors, fonts, spacing, and more
- Fonts: Include custom web fonts
- Responsive Design: Automatically adapts to different screen sizes
Best Practices
- Always verify the origin of incoming messages in the event listener
- Implement proper error handling for failed payments
- Use HTTPS in production environments
- Test the integration thoroughly in different browsers and devices
- Keep your merchant ID secure and never expose it in client-side code in production
Sample View
This is a dark mode sample to indicate the style customizability of the field