rexedge/interswitch · Archived

interswitch-card-payments

>- 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…

First seen Mar 13, 2026

Installation

$ npx skills add rexedge/interswitch --skill interswitch-card-payments

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Also in this package

Other skills from rexedge/interswitch · top by installs.

npx skills add rexedge/interswitch

Browse all from rexedge/interswitch

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License MIT
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,270 B
  • docs SUMMARY.md 547 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 5 installs

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

  1. Collect card details (PAN, expiry, CVV, PIN)
  2. Encrypt card data into authData
  3. Send payment request with encrypted authData
  4. Handle OTP/3D Secure if required
  5. 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

  1. Never log raw card data — Only handle encrypted authData
  2. Use Hosted Fields when possible for PCI compliance
  3. Always verify server-side — Requery every transaction
  4. Handle all response codes — Implement proper error flows for OTP, 3DS
  5. Use unique transaction references — Prevent duplicate charges