Skip to main content

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 identifier
  • PAGE_ROOT_URL: The base URL of the NGnair payment service
  • PAGE_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:

  1. onEvent: General purpose event handler for form interactions
  2. onToken: Processes the payment response, containing the payment ID
  3. 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:

  1. URL Generation: Creates a unique URL with:
    • Random hash for security
    • Custom form styling
    • Form labels configuration
  2. 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:

  1. Creates a responsive payment form
  2. Handles payment processing securely
  3. Provides a modern, dark-mode UI
Payment Integration Example
<!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:

Payment Response
{
"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:

  1. Labels: Customize form field labels
  2. Styling: Modify colors, fonts, spacing, and more
  3. Fonts: Include custom web fonts
  4. Responsive Design: Automatically adapts to different screen sizes

Best Practices

  1. Always verify the origin of incoming messages in the event listener
  2. Implement proper error handling for failed payments
  3. Use HTTPS in production environments
  4. Test the integration thoroughly in different browsers and devices
  5. Keep your merchant ID secure and never expose it in client-side code in production

Sample View

alt text

This is a dark mode sample to indicate the style customizability of the field