interswitch-card-payments
SKILL.md
Interswitch Card Payments API
Process card payments directly via the Interswitch API with 3D Secure support, Hosted Fields, and Google Pay integration.
Card Payment Flow
- Collect card details (PAN, expiry, CVV, PIN)
- Encrypt card data into
authData - Send payment request with encrypted authData
- Handle OTP/3D Secure if required
- Verify transaction server-side
Test Credentials (Card Payment API)
| Parameter | Value |
|---|---|
| Client ID | IKIA3B827951EA3EC2E193C51DA1D22988F055FD27DE |
| Secret Key | ajkdpGiF6PHVrwK |
| Merchant Code | MX21696 |
| Pay Item ID | 4177785 |
Card Data Encryption (authData)
Card details must be encrypted before transmission. The authData is a concatenation of card PAN, PIN, expiry, and CVV encrypted with the Interswitch modulus/exponent:
import 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');
}
Direct Card Payment
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();
}
Handle OTP Validation
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();
}
3D Secure Transactions
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 (PCI Compliant)
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>
Google Pay Integration
// 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
Security Best Practices
- Never log raw card data — Only handle encrypted authData
- Use Hosted Fields when possible for PCI compliance
- Always verify server-side — Requery every transaction
- Handle all response codes — Implement proper error flows for OTP, 3DS
- Use unique transaction references — Prevent duplicate charges
Weekly Installs
1
Repository
rexedge/interswitchFirst Seen
3 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1