🔐 Encryption Logic

All requests and responses use AES-256-CBC encryption with a static initialization vector (IV). The encryption key and IV are provided in your integration kit.

Encryption Details: Node.js Implementation


const crypto = require('crypto');
const forge = require('node-forge');

function encrypt(plainText, publicKeyPem) {
  const aesKey = crypto.randomBytes(32);
  const iv = crypto.randomBytes(12);

  const cipher = crypto.createCipheriv("aes-256-gcm", aesKey, iv);
  const encrypted = Buffer.concat([
    cipher.update(plainText, "utf8"),
    cipher.final(),
  ]);
  const authTag = cipher.getAuthTag();

  const encryptedBuffer = Buffer.concat([encrypted, authTag]);
  const dataB64 = encryptedBuffer.toString("base64");

  const encryptedKeyB64 = crypto
    .publicEncrypt(
      { key: publicKeyPem, padding: crypto.constants.RSA_PKCS1_PADDING },
      aesKey
    )
    .toString("base64");
  const encryptedIvB64 = crypto
    .publicEncrypt(
      { key: publicKeyPem, padding: crypto.constants.RSA_PKCS1_PADDING },
      iv
    )
    .toString("base64");

  return `${dataB64}^${encryptedKeyB64}^${encryptedIvB64}`;
}

function decrypt(encryptedString, privateKeyPem) {
  if (typeof encryptedString !== "string") {
    throw new TypeError("Expected encrypted string to be of type string.");
  }

  const [dataB64, encryptedKeyB64, encryptedIvB64] = encryptedString.split("^");

  const privateKey = forge.pki.privateKeyFromPem(privateKeyPem);
  const aesKeyBinaryStr = privateKey.decrypt(
    forge.util.decode64(encryptedKeyB64),
    "RSAES-PKCS1-V1_5"
  );
  const ivBinaryStr = privateKey.decrypt(
    forge.util.decode64(encryptedIvB64),
    "RSAES-PKCS1-V1_5"
  );

  const aesKey = Buffer.from(aesKeyBinaryStr, "binary");
  const iv = Buffer.from(ivBinaryStr, "binary");

  const encryptedBuffer = Buffer.from(dataB64, "base64");
  const authTag = encryptedBuffer.slice(-16);
  const ciphertext = encryptedBuffer.slice(0, -16);

  const decipher = crypto.createDecipheriv("aes-256-gcm", aesKey, iv);
  decipher.setAuthTag(authTag);

  const decrypted = Buffer.concat([
    decipher.update(ciphertext),
    decipher.final(),
  ]);
  return decrypted.toString("utf8");
}

// Usage Example:
const payload = {
    "amount": "10",
    "customer_email": "testing@gmail.com",
    "dial_code": "+91",
    "mobile_no": "9999999990",
    "expiry_date": "2026-04-25",
    "media_type": [
      { "id": 1, "name": "API", "code": "API" },
      { "id": 2, "name": "QR Code", "code": "QR_CODE" },
      { "id": 4, "name": "SMS", "code": "SMS" },
      { "id": 3, "name": "Email", "code": "EMAIL" },
      { "id": 5, "name": "WhatsApp", "code": "WHATS_APP" }
    ],
    "order_id": "test552",
    "first_name": "Azam",
    "last_name": "Shah",
    "reminder1": "",
    "product": "product1",
    "reminder2": "",
    "country": "ARE",
    "currency": "AED"
};

const encryptedPayload = encrypt(JSON.stringify(payload), publicKeyPem);

// Send to API
const requestBody = {
  "enc": encryptedPayload
};

📊 Status API

Check the status of a transaction or order. Use this API when you haven't received real-time status updates. All requests and responses are encrypted using AES-256.

Endpoint

GET {BASE_URL}/api/v1/payment/status_check

Request Parameters

order_id: test552 (Unique order ID for which status needs to be fetched)

Example Request

GET {BASE_URL}/api/v1/payment/status_check?order_id=test552

Plain Response Example

{
  "code": "00",
  "response": "SUCCESS",
  "message": "Transaction status fetched successfully",
  "data": {
    "me_id": "202402140004",
    "ag_ref": "2058491775820692144",
    "currency": "AED",
    "txn_date": "13-04-2026",
    "txn_time": "10:50:54",
    "pg_ref": "123456789",
    "status": "Successful",
    "res_code": "00000",
    "res_message": "Successful",
    "bank_response": "APPROVED",
    "order_no": "cbbeec348dde847430fbd40d0862486d",
    "amount": "11.00",
    "country": "ARE"
  },
  "timestamp": "2026-04-13 12:24:45"
}

Transaction Status Values

Important Notes

res_code "00000": Indicates successful API response with no errors
status field: Main transaction status to track
Pending Status: Bank response not received yet - check back later

💰 Refund API

Initiate full or partial refunds for successful transactions.

Endpoint

POST {BASE_URL}/api/v1/payment/refund

Request Parameters

Plain Request Example

{
"me_id": "202410170001",
"order_no": "78408",
"refund_reason": "Customer Request",
"refund_amount": "16",
"ag_ref": "2058321738144799252"
}

Plain Response Example

{
"ag_id": "6215f3b65aba8f48b9ad4324",
"me_id": "202410170001",
"ag_ref": "2058321738144799252",
"refund_amount": "16",
"refund_status": "FULL_REFUND",
"refund_message": "Refund",
"currency": "AED",
"txn_date": "2025-01-30",
"txn_time": "11:55:55",
"refund_ref": "67a0ade40fd9681e77e70f68",
"pg_ref": "123456789",
"status": "FULL_REFUND",
"res_code": "00000",
"res_message": "Refund",
"order_no": "78408",
"amount": "16.00",
"country": "ARE",
"balance_amount": "0.00"
}

Refund Types

Important Notes

Partial Refunds: You can refund any amount up to the original transaction amount
Multiple Refunds: You can initiate multiple refunds for the same transaction
Encryption Required: All sensitive data must be encrypted before sending

🔔 Webhook / Callback API

Server-to-server transaction updates. Webhooks provide reliable transaction status notifications and serve as a fallback when browser redirections fail.

Why Use Webhooks?

While browser redirections provide real-time status, they may fail due to network issues or technical glitches. Webhooks ensure you never miss transaction updates through automatic server-to-server communication.

Webhook Setup Steps

  1. Create Server URL: Set up your endpoint (e.g., https://yourdomain.com/payment/callback)
  2. Share Details: Provide webhook URL and server IP to integration team
  3. Whitelist: We will whitelist your URL. Add IP to your firewall.
  4. Configure Content Types: Ensure your server accepts:
    • application/x-www-form-urlencoded
    • application/json
    • FormData
  5. Send Acknowledgment: Return `{"success": true}` to confirm receipt

Prerequisites for Configuration

Webhook URL: Your endpoint for receiving updates
Webhook IP: Your server's IP address
SSL Certificate: For HTTPS URL whitelisting
Event Types: Select which events to receive

Supported Webhook Events

Event ID Event Name Description
0 AuthRR Auth Request Received
1 AuthVRR Auth Void Request Received
2 CaptureRR Capture Request Received
3 SaleRR Sale Request Received
4 RefundRI Refund Request Initiated
5 RequestSTPGoB Request Sent To Payment Gateway / Bank
6 ResponseRFPGoB Response Received From Payment Gateway / Bank
16 SaleRP Sale Request Processed ✓
17 SaleRF Sale Request Failed
18 RefundRP Refund Request Processed ✓
19 RefundRF Refund Request Failed
21 SettlementD Settlement Done ✓

✓ Most commonly used events for webhook integration

Webhook Scheduler Configuration

Retry Interval: 10 minutes
Retry Scope: Current day's transactions
Retry Stops When: Merchant sends success acknowledgment

Best Practices