---
updatedAt: 2026-02-19T12:39:37.000Z
agentTools:
  projectIndex: https://transactpay.readme.io/llms.txt
---

# Card Payments

<Callout icon="📘" theme="info">
  Transactpay's REST API enables secure card payments by creating an encrypted order and processing it with or without authentication. It supports encryption, tokenization, and real-time status updates.
</Callout>

Transactpay enables secure card payments using debit or credit cards through two primary methods:

* **REST API** – Full control, flexible integration.
* **Standard Checkout** – No-code option (**recommended** for quick setup and PCI offloading) [Standard Kit](https://transactpay.readme.io/docs/standard-kit-checkout#/)

***

## Step 1: Create an Order

Before initiating a card payment, you **must create an order** by encrypting and submitting customer and order data.

### Encrypt the Order Payload

Use RSA PKCS#1 v1.5 encryption with your public encryption Key. Kindly follow our [encryption guide](https://transactpay.readme.io/v2.0/update/reference/encryption#/).

### Example Payload (Before Encryption)

```json
{
  "customer": {
    "firstname": "transact",
    "lastname": "pay",
    "mobile": "+2348134543421",
    "country": "NG",
    "email": "email@transactpay.ai"
  },
  "order": {
    "amount": 100,
    "reference": "12121212112",
    "description": "Pay",
    "currency": "NGN"
  },
  "payment": {
    "RedirectUrl": "https://www.hi.com"
  },
   "paymentMeta": {
     "ipAddress": "101.101.101.101"
  }
}
```

> ℹ️ Encryption
>
> Encrypt this JSON payload with the RSA public key from your dashboard.

### Encrypted Request Format

```curl curl
curl --request POST \
     --url https://payment-api-service.transactpay.ai/payment/order/create \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'api-key: PUBLIC_KEY'
{
  "data": "{{encrypteddata}}"
}

```

Once successful, you'll receive an order reference to use in the card payment step.

***

## Prerequisites for Card Payments

| Requirement              | Description                                 |
| ------------------------ | ------------------------------------------- |
| ✅ Live API Keys          | Obtainable from the Dashboard               |
| 🔐 Public Encryption Key | Used to encrypt card data before sending    |
| 🧾 PCI-DSS Compliance    | Required if handling raw card data directly |
| 🌐 HTTPS Server          | All communication must occur over HTTPS     |

<Callout icon="💡" theme="default">
  ### Testing

  Use the Test Credentials and Test Cards to simulate transactions during development.
</Callout>

***

## Authentication

All requests must include:

* [A valid public key to encrypt the payload]()

  👉 See full [Authentication Guide →](https://www.notion.so/Card-Payments-1f8ccdebd2778055a543ce809cc37bdb?pvs=21)

***

## Encrypting Card Data

Sensitive fields like **card number**, **expiry**, and **CVV** must be encrypted using RSA with your public key.

### JavaScript Encryption Snippet

```jsx

const forge = require('node-forge');
const { DOMParser } = require('xmldom');
const BigInteger = forge.jsbn.BigInteger;

/**
 * Encrypt data using RSA public key.
 *
 * @param {string} data - The data to encrypt.
 * @param {string} rsaPubKey - The RSA public key in base64 XML format.
 * @returns {string} - The encrypted data in base64 encoding.
 */
function encryptForge(data, rsaPubKey) {
  // Decode the base64 encoded public key and remove the prefix
  let rsaKeyValue = Buffer.from(rsaPubKey, 'base64').toString('utf-8');
  rsaKeyValue = rsaKeyValue.replace('4096!', '');

  // Parse the XML to extract Modulus and Exponent
  const parser = new DOMParser();
  const xmlDoc = parser.parseFromString(rsaKeyValue, 'text/xml');
  const modulus = xmlDoc.getElementsByTagName('Modulus')[0].textContent;
  const exponent = xmlDoc.getElementsByTagName('Exponent')[0].textContent;

  // Convert the Modulus and Exponent from base64 to BigInteger
  const modulusBI = parseBigInteger(modulus);
  const exponentBI = parseBigInteger(exponent);

  // Set up the RSA public key
  const pubKey = forge.pki.setRsaPublicKey(modulusBI, exponentBI);

  // Encrypt the data
  //const encryptedBytes = pubKey.encrypt(forge.util.encodeUtf8(data));
  const encryptedBytes = pubKey.encrypt(forge.util.encodeUtf8(JSON.stringify(data)));

  // Return the encrypted text in base64 encoding
  return Buffer.from(encryptedBytes, 'binary').toString('base64');
}

/**
 * Convert a base64 encoded string to a BigInteger.
 *
 * @param {string} b64 - The base64 encoded string.
 * @returns {BigInteger} - The BigInteger representation of the string.
 */
function parseBigInteger(b64) {
  const decoded = forge.util.decode64(b64);
  return new BigInteger(forge.util.createBuffer(decoded).toHex(), 16);
}

```

👉 View full [Encryption Guide →](https://www.notion.so/Card-Payments-1f8ccdebd2778055a543ce809cc37bdb?pvs=21)

<Callout icon="⚠️" theme="warn">
  Never log or store raw card details — always encrypt before sending.
</Callout>

## Card Payment Modes

### 1. Card Payment With Auth (Recommended)

Requires calling the **Verify Order API** after payment initiation.

### Flow

1. Encrypt and send to [Pay Order API](https://www.notion.so/Pay-Order-1f6ccdebd277800c9ed8eb58b276b247?pvs=21)

```json

{
  "reference": "txn_123456789",
  "paymentoption": "C",
  "country": "NG",
  "card": {
    "cardnumber": "5123450000784608",
    "expirymonth": "01",
    "expiryyear": "39",
    "cvv": "193"
  }
}
```

1. Make a request to the verify Order API to confirm the order status

```curl curl
//Encrypt the Payload with your Encryption key

{
    "reference": "{{orderreference}}"
}

// Sample Request
curl --request POST \
     --url https://payment-api-service.transactpay.ai/payment/order/status \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'api-key: PUBLIC_KEY'
     
 {
    "data": "{{encrypteddata}}"
}
```

***

### 2. Card Payment Without Auth

Skips the `/verify` step — suitable for tokenized or low-risk cards.

### Flow

1. Encrypt and send to [Pay Order API](https://transactpay.readme.io/reference/pay-order-1)

```json

{
  "reference": "txn_123456789",
  "paymentoption": "C",
  "country": "NG",
  "card": {
    "cardnumber": "5123450000784608",
    "expirymonth": "01",
    "expiryyear": "39",
    "cvv": "193",
    "authOption": "NOAUTH"
  }
}

```

2. No `/verify` call needed — response will contain final status

<Callout icon="⚠️" theme="warn">
  Use NOAUTH only if you're certain the card supports this mode.
</Callout>

## Tokenization Flow

To enable reusable charges, we provide an auth token which is gotten via the save card request after completing an order with the card.

### Sample Request

```curl

//Encrypt the Payload with your Encryption key

{
    "reference": "{{orderreference}}"
}

// Sample Request
curl --request POST \
     --url https://payment-api-service.transactpay.ai/payment/order/save-card \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --header 'api-key: PUBLIC_KEY'
     
 {
    "data": "{{encrypteddata}}"
}
```

You can reuse this token in future charges to skip collecting card details again.

👉 View full [Tokenization Guide →](https://www.notion.so/Card-Payments-1f8ccdebd2778055a543ce809cc37bdb?pvs=21)

***

## Webhooks

Set up your webhook endpoint via your dashboard developer section to get real-time updates and confirmations of transactions.

<Callout icon="💡" theme="default">
  Webhook must return HTTP 200 OK and be publicly accessible.
</Callout>

Follow this guide to setup your webhooks.

## Testing Your Integration

* Use test cards from the [Card Reference](https://www.notion.so/Card-Payments-1f8ccdebd2778055a543ce809cc37bdb?pvs=21)
* Simulate various flows like:
  * Success
  * 3DS redirect
  * Failed auth
  * NoAuth
  * Token reuse

## Summary

| Mode         | Verify Required | Best Use Case                    |
| ------------ | --------------- | -------------------------------- |
| With Auth    | ✅ Yes           | Most cards & default integration |
| No Auth      | ❌ No            | Trusted or tokenized cards only  |
| Tokenization | Optional        | Reusable billing & subscriptions |