Accept Payment
Server to Server
Cards

Server to Server (Cards)

The Direct Charge API lets you charge Visa, Mastercard and Verve cards (NGN) from your own checkout, without redirecting the customer to a BudPay page. You collect the card details, encrypt them, and send them to BudPay from your server.

How it works

  1. Collect card details. Capture the customer's card details in your own checkout form.
  2. Encrypt the card details. Encrypt the card details with AES-256-CBC before they leave your system.
  3. Initialize the transaction. Send the encrypted card to the S2S initialize endpoint.
  4. Complete 3D Secure. If the card requires 3D Secure, complete the authentication flow described in Step 4.
  5. Verify the transaction. Confirm the final status with the verify endpoint before you give value.

Step 1: Collect Card Details

Collect the customer's card details in your checkout. Handling raw card data brings your systems into PCI DSS scope, so make sure your environment is compliant before you go live. You need the following details:

{
  "data": {
    "number": "4242424242424242",
    "cvv": "123",
    "expiryMonth": "12",
    "expiryYear": "28",
    "pin": "1234" // optional - only required for verve/local cards
  },
  "reference": "1234567890123456"
}
FieldDescription
numberThe card number.
cvvThe card verification value (CVV) on the back of the card.
expiryMonthThe card's expiry month, 2 digits, e.g. "12".
expiryYearThe card's expiry year, 2 digits, e.g. "28" for 2028.
pinThe card PIN. Required for Verve and other local cards only.
referenceA unique reference for the transaction, at least 16 characters long. The first 16 characters are used to encrypt the card.

Step 2: Encrypt the Card Details

Encrypt the card details with AES-256-CBC before you send them to BudPay. The examples below show how to do this in Node.js and PHP.

Encryption Parameters
ParameterDescription
dataThe card details to be encrypted.
keyThe encryption key. Use your BudPay public key.
referenceThe unique transaction reference. It must be at least 16 characters long.
ivThe initialization vector: the first 16 characters of the reference.
encryptionTypeThe encryption algorithm and mode: aes-256-cbc.
const crypto = require('crypto');
 
function cardEncryption() {
    const data = {
        number: "5123450000000008",  // Card Number
        expiryMonth: "10",           // Card Expiry Month
        expiryYear: "28",            // Card Expiry Year
        cvv: "100",                  // Card CVV
        pin: "1234"                  // (Optional - only required for verve/local cards)
    };
    
    const key = 'BUDPAY_PUBLIC_KEY'; // Encryption Key: BudPay Public key used for encryption
    const reference = "10033333333333333";  // 16 Digits Minimum
    
    const iv = reference.slice(0, 16);      // Initialization Vector: A fixed-size input for the cryptographic algorithm to ensure uniqueness
    const encryptionType = 'aes-256-cbc';   // Encryption Type: Specifies the encryption algorithm and mode
 
    // Convert key to Buffer for crypto library
    const keyBuffer = Buffer.from(key, 'utf-8');
 
    // Convert iv to Buffer for crypto library
    const ivBuffer = Buffer.from(iv, 'utf-8');
 
    // Create a Cipher object
    const cipher = crypto.createCipheriv(encryptionType, keyBuffer, ivBuffer);
 
    // Encrypt the data
    let encryptedData = cipher.update(JSON.stringify(data), 'utf-8', 'hex');
    encryptedData += cipher.final('hex');
 
    return encryptedData;
}
 
console.log(cardEncryption());

cardEncryption returns the encrypted card details as a hexadecimal string. Send this value as card in Step 3.

Test Your Encryption

Use the test encryption endpoint to check your implementation. Encrypt the same card details and reference in your code, then compare your output with the value returned by this endpoint. If they match, your encryption is correct.

This endpoint is for testing only. In production, always encrypt card details in your own code.

Headers
ParameterDescription
URLhttps://api.budpay.com/api/s2s/test/encryption (opens in a new tab)
MethodPOST
Content-TypeThe content type of the request. Set this to application/json.
AuthorizationThe secret key used to authenticate the request, set this to Bearer YOUR_SECRET_KEY.

Endpoint: POST https://api.budpay.com/api/s2s/test/encryption

1curl -X POST 'https://api.budpay.com/api/s2s/test/encryption' \2  -H 'Content-Type: application/json' \3  -H 'Authorization: Bearer YOUR_SECRET_KEY' \4  -d '{5  "data": {6    "number": "4242424242424242",7    "cvv": "123",8    "expiryMonth": "12",9    "expiryYear": "28",10    "pin": "1234"11  },12  "reference": "1234567890123456"13}'
Sample Response
{
    "card": "83fa6763bb31bae36a74f787ab814514aeede91fcdb311fd67609b414c5e5ea2751a47870c8717e71bcbc9c33287a3d6af9ffae8e2edbf2de1e2694384d699b020d31492637eef60d7a63f303798363a"
}

Step 3: Initialize the Transaction

Send the encrypted card details to the S2S initialize endpoint from your server.

Endpoint: POST https://api.budpay.com/api/s2s/transaction/initialize

1curl -X POST 'https://api.budpay.com/api/s2s/transaction/initialize' \2  -H 'Content-Type: application/json' \3  -H 'Authorization: Bearer YOUR_SECRET_KEY' \4  -d '{5  "amount": "100",6  "card": "83fa6763bb31bae36a74f787ab814514aeede91fcdb311fd67609b414c5e5ea2751a47870c8717e71bcbc9c33287a3d6af9ffae8e2edbf2de1e2694384d699b020d31492637eef60d7a63f303798363a",7  "currency": "NGN",8  "email": "test@email.com",9  "reference": "1253627873656276350"10}'
Sample Request Body
{
  "card": "83fa6763bb31bae36a74f787ab814514aeede91fcdb311fd67609b414c5e5ea2751a47870c8717e71bcbc9c33287a3d6af9ffae8e2edbf2de1e2694384d699b020d31492637eef60d7a63f303798363a",
  "pin": "1234", // optional - only required for verve/local cards
  "amount": 10000,
  "currency": "NGN",
  "email": "test@gmail.com",
  "callback": "https://yourwebsite.com/callback",
  "reference": "1234567890123456"
}

Headers
ParameterDescription
URLhttps://api.budpay.com/api/s2s/transaction/initialize (opens in a new tab)
MethodPOST
Content-TypeThe content type of the request. Set this to application/json.
AuthorizationThe secret key used to authenticate the request, set this to Bearer YOUR_SECRET_KEY.
Request Body
ParameterTypeRequiredDescription
cardstringYesThe encrypted card details from Step 2.
amountstringYesThe amount to charge.
currencystringYesThe transaction currency.
emailstringYesThe customer's email address.
callbackstringYesThe URL to redirect the customer to after the transaction.
referencestringYesThe same reference you used to encrypt the card.
pinstringNoThe card PIN. Required for Verve and other local cards only.

Step 4: Complete 3D Secure Authentication

If the card supports 3D Secure 2 (3DS2), the initialize endpoint returns an HTML snippet in data and a follow-up request in _links:

3DS2 Response
{
    "status": true,
    "message": "Proceed authentication 3DS2",
    "data": "<div id=\"initiate3dsSimpleRedirect\" xmlns=\"http://www.w3.org/1999/html\"> <iframe id=\"methodFrame\" name=\"methodFrame\" height=\"100\" width=\"200\" > </iframe> <form id =\"initiate3dsSimpleRedirectForm\" method=\"POST\" action=\"https://secure-acs2ui-b1.wibmo.com/v1/acs/services/threeDSMethod/8528?cardType=M\" target=\"methodFrame\"> <input type=\"hidden\" name=\"threeDSMethodData\" value=\"eyJ0aHJlZURTTWV0aG9kTm90aWZpY2F0aW9uVVJMIjoiaHR0cHM6Ly9ldS5nYXRld2F5Lm1hc3RlcmNhcmQuY29tL2NhbGxiYWNrSW50ZXJmYWNlL2dhdGV3YXkvOGFkZGRiNzE1MTQwMjk2OWMxMmI1Y2QzNjBhOTdmYTdiZTE1ZWU1NWZiZDEwZTE5MmI3ZDIwNDcxNmQxYTVlNSIsInRocmVlRFNTZXJ2ZXJUcmFuc0lEIjoiZjgxNGM3YWMtMmRiOS00Nzg1LThhMjYtYjA2NjZlYTBjMGVkIn0=\" /> </form> <script id=\"initiate-authentication-script\"> var e=document.getElementById(\"initiate3dsSimpleRedirectForm\"); if (e) { e.submit(); if (e.parentNode !== null) { e.parentNode.removeChild(e); } } </script> </div>",
    "_links": {
        "url": "http://api.budpay.com/api/mastercard-payment/3ds2auth",
        "method": "POST",
        "payload": [
            "ref"
        ]
    }
}

To complete authentication:

  1. Render the HTML in data in a hidden iframe on your checkout page. It submits the card's 3DS2 device data to the issuing bank.
  2. Wait 20 seconds for the process to complete.
  3. Send a request to the _links.url endpoint, using the _links.method and the fields listed in _links.payload.
  4. Handle the final response below.

Cards that do not support 3DS2 skip this step. The initialize endpoint returns the final response directly.

3DS2 Flow Diagram
3DS Flow Diagram
Final Response

The final response is returned after 3DS2 authentication, or directly from initialize for cards that don't use 3DS2.

Mastercard and Visa
{
    "status": "success",
    "message": "Approved or Captured"
}
Verve
{
    "status": true,
    "message": "Payment Successful"
}
⚠️

Before giving value, confirm that status is successful and that message is "Approved" or "Captured". Then verify the transaction with the endpoint below.


Verifying Transactions

Call the Verify Transaction API with the transaction reference:

GET https://api.budpay.com/api/v2/transaction/verify/:reference

Example Request:

Endpoint: GET https://api.budpay.com/api/v2/transaction/verify/BUD_1673600359168063493

1curl -X GET 'https://api.budpay.com/api/v2/transaction/verify/BUD_1673600359168063493' \2  -H 'Authorization: Bearer YOUR_SECRET_KEY'
{  "status": true,  "message": "Transaction verified successfully",  "data": {    "currency": "NGN",    "amount": "550",    "reference": "BUD_1673600359168063493",    "status": "success",    "message": "Payment successful",    "customer": {      "email": "customer@email.com"    }  }}

Always verify transactions on your server before fulfilling orders. Never rely solely on client-side callbacks or redirects.

Verification Workflow:

  1. Receive callback/webhook with transaction reference
  2. Call Verify API (server-side)
  3. Check status === "success"
  4. Verify amount matches expected
  5. Fulfill order/deliver service

Learn more about verifying transactions.


Testing Your Integration

BudPay provides a comprehensive sandbox environment for testing:

Test Card Numbers:
Card TypeNumberCVVExpiry
Visa424242424242424212312/25
Visa (V2)400000000000109148412/29
Mastercard512345000000000810012/25
Verve506099058000021749912312/25
Test Mobile Money Numbers:
  • Kenya (M-Pesa): 254712345678
  • Ghana (MTN): 233244000000

Remember: Always use test credentials in sandbox mode. Switch to live keys only when ready for production.