Interswitch Card Payments API — process card transactions directly via API, handle 3D Secure (Visa/Mastercard), Hosted Fields for PCI compliance, and Google Pay. Use this skill whenever building a custom card payment flow, implementing 3D Secure authentication, using Hosted Fields for PCI-compliant card collection, integrating Google Pay, or processing direct card charges. Also use when you see references to authData, 3DSecure, OTP validation, Hosted Fields, payment-api endpoint, or card PIN/OTP submission.
Process card payments directly via the Interswitch API with 3D Secure support, Hosted Fields, and Google Pay integration.
authData| Parameter | Value |
|---|---|
| Client ID | IKIA3B827951EA3EC2E193C51DA1D22988F055FD27DE |
| Secret Key | ajkdpGiF6PHVrwK |
| Merchant Code | MX21696 |
| Pay Item ID | 4177785 |
Card details must be encrypted before transmission. The is a concatenation of card PAN, PIN, expiry, and CVV encrypted with the Interswitch modulus/exponent:
authDataimport crypto from 'crypto';
interface CardDetails {
pan: string; // Card number (no spaces)
pin: string; // 4-digit PIN
expiryDate: string; // YYMM format
cvv: string; // CVV/CVC
}
function generateAuthData(card: CardDetails): string {
// Concatenate: 1PAN + 0PIN + EXPIRY + CVV (with length-prefixed fields)
const cardData = `1${card.pan}0${card.pin}${card.expiryDate}${card.cvv}`;
// Use Interswitch's public key for encryption
// Get the actual modulus and exponent from Interswitch documentation
const publicKey = crypto.createPublicKey({
key: {
kty: 'RSA',
n: '<INTERSWITCH_MODULUS_BASE64URL>',
e: 'AQAB', // 65537
},
format: 'jwk',
});
const encrypted = crypto.publicEncrypt(
{ key: publicKey, padding: crypto.constants.RSA_PKCS1_PADDING },
Buffer.from(cardData)
);
return encrypted.toString('base64');
}
interface CardPaymentRequest {
customerId: string;
amount: string; // In minor currency (kobo)
currency: string; // '566' for NGN
transactionRef: string;
authData: string; // Encrypted card data
}
interface CardPaymentResponse {
amount: string;
responseCode: string;
responseDescription: string;
paymentId: string;
transactionRef: string;
remittanceAmount: string;
eciFlag?: string;
message?: string;
}
async function initiateCardPayment(
payment: CardPaymentRequest
): Promise<CardPaymentResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${getConfig().collectionsBaseUrl}/collections/api/v1/pay`,
{
method: 'POST',
headers,
body: JSON.stringify(payment),
}
);
return response.json();
}
If responseCode is T0 (OTP required):
interface OTPValidationRequest {
paymentId: string;
transactionRef: string;
otp: string;
}
async function validateOTP(
request: OTPValidationRequest
): Promise<CardPaymentResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${getConfig().collectionsBaseUrl}/collections/api/v1/pay/validate`,
{
method: 'POST',
headers,
body: JSON.stringify(request),
}
);
return response.json();
}
For Visa/Mastercard 3D Secure:
// Step 1: Initiate payment — if 3DS required, response includes:
// - responseCode: 'Z9' or 'S0'
// - eciFlag with redirect info
interface ThreeDSecureResponse {
responseCode: string;
redirectUrl: string; // Redirect customer to this URL
transactionId: string;
md: string; // Merchant Data for callback
}
// Step 2: Customer completes 3DS on bank's page
// Step 3: Bank redirects back to your callback URL
// Step 4: Complete the transaction
async function complete3DSTransaction(
paymentId: string,
transactionRef: string,
eciFlag: string
): Promise<CardPaymentResponse> {
const headers = await getAuthHeaders();
const response = await fetch(
`${getConfig().collectionsBaseUrl}/collections/api/v1/pay/validate`,
{
method: 'POST',
headers,
body: JSON.stringify({ paymentId, transactionRef, eciFlag }),
}
);
return response.json();
}
Hosted Fields let you collect card data securely without handling raw card numbers. Interswitch hosts the input fields in iframes:
<!-- Include Hosted Fields SDK -->
<script src="https://newwebpay.qa.interswitchng.com/hosted-fields.js"></script>
<div id="card-number"></div>
<div id="card-expiry"></div>
<div id="card-cvv"></div>
<div id="card-pin"></div>
<button id="submit-payment">Pay</button>
<script>
const hostedFields = window.interswitchHostedFields({
merchantCode: 'MX6072',
payItemId: '9405967',
transactionRef: 'TXN_' + Date.now(),
amount: 10000,
currency: 566,
mode: 'TEST',
fields: {
cardNumber: { selector: '#card-number', placeholder: 'Card Number' },
expirationDate: { selector: '#card-expiry', placeholder: 'MM/YY' },
cvv: { selector: '#card-cvv', placeholder: 'CVV' },
pin: { selector: '#card-pin', placeholder: 'PIN' },
},
onComplete: function (response) {
console.log(response);
},
});
document.getElementById('submit-payment').addEventListener('click', () => {
hostedFields.submit();
});
</script>
// Step 1: Check Google Pay availability
const paymentsClient = new google.payments.api.PaymentsClient({
environment: 'TEST', // or 'PRODUCTION'
});
const isReadyToPayRequest = {
apiVersion: 2,
apiVersionMinor: 0,
allowedPaymentMethods: [{
type: 'CARD',
parameters: {
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
allowedCardNetworks: ['VISA', 'MASTERCARD'],
},
tokenizationSpecification: {
type: 'PAYMENT_GATEWAY',
parameters: {
gateway: 'interswitch',
gatewayMerchantId: 'MX6072',
},
},
}],
};
// Step 2: Request payment
const paymentDataRequest = {
...isReadyToPayRequest,
transactionInfo: {
totalPriceStatus: 'FINAL',
totalPrice: '100.00',
currencyCode: 'NGN',
},
merchantInfo: { merchantName: 'Your Store' },
};
const paymentData = await paymentsClient.loadPaymentData(paymentDataRequest);
// Step 3: Send paymentData.paymentMethodData.tokenizationData.token to your server
// Step 4: Process token via Interswitch API