LogoLogo
  • Welcome!
  • Integrating Klasha
    • Getting Started
    • Prerequisites
    • Integration Checklist
    • Wrap Up
  • Overview
    • Introduction
    • Parameters
    • Token Generation
    • Errors
    • Countries & Payment Methods
  • Accepting Payments
    • Test Payments
    • Payments API
      • Mobile money
      • USSD
    • Payment Link
      • Dashboard
      • Payment Link API
    • Klasha Inline
    • HTML Checkout
  • PLUGINS AND SDKS
    • Plugins
    • Mobile SDKs
    • Web SDKs
  • MISC
    • Transaction Status
    • Webhook
    • API Status
  • Features
    • One-time Payments
    • Recurrent Payment
  • Transfers
    • Payout
      • ZAR Payout(new encryption)
      • KES Payout(new encryption)
      • ZMW Payout(new encryption)
      • TZS Payout(new encryption)
      • CNY Payout(new encryption)
    • Klasha Wire API
    • Swap API
    • Currency Coverage
  • Bank Account Collection
    • Virtual Account Creation
    • VA balance and statement
    • Business Identification Service
Powered by GitBook
On this page
  • Payment collection
  • Before you begin
  • Encryption algorithm
  • Card payments
  • Initiate card payment
  • Charge card
  • Validate card
  • Bank transfer
  • M-Pesa
  • Initiate a refund
  • Get a refund
  • Generate a bearer token
  • Exchange rate
  1. Accepting Payments

Payments API

Summary

PreviousTest PaymentsNextMobile money

Last updated 2 months ago

This documentation page contains everything you need to know about integrating to Klasha’s Payment Gateway. Once integration is done, you can begin to process payments from anywhere in the world in seconds.

Whilst you start your integration, please remember to reach out to our Compliance team to go through the KYB process and get your business verified. This is a mandatory process before you can start using our production platform.

If you are going to be implementing the direct charge API, you would require additional verification as this is only available to businesses that are PCI-DSS certified.

Payment collection

As a business owner, here is a way we make it possible for you to collect payments from customers all over the world:

In all the following APIs, you can simply substitute the desired currency to the path variable {{gateway}}.

Before you begin

Get your API keys

  • Find your keys on the Klasha Dashboard → Settings → Generate API Keys ()

  • Klasha Dashboard, Generate API Keys page

Encryption algorithm

Since we are treating payment data, the communication from merchant to APIs must be encrypted. We are using a standard 3DES technology with Padding. Please find some code snippets below for the 3DES encryption:

public static String Encrypt3DES(String messageToEncrypt, byte[] secret) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    SecretKeySpec secretKeySpec = new SecretKeySpec(secret, "TripleDES");
    byte[] iv = Arrays.copyOfRange(secret, 0, 8);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);

    Cipher encryptCipher =Cipher.getInstance("TripleDES/CBC/PKCS5Padding");
    encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);

    byte[] secretMessagesBytes=      messageToEncrypt.getBytes(StandardCharsets.UTF_8);
    byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessagesBytes);

    return Base64.getEncoder().encodeToString(encryptedMessageBytes);
}
public static string Encrypt3DES(string message, string secret)
{
    byte[] secretByte = Encoding.UTF8.GetBytes(secret.Trim());

    using (TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider())
    {
        tripleDES.Key = secretByte;
        byte[] iv = new byte[8];
        Buffer.BlockCopy(secretByte, 0, iv, 0, 8);
        tripleDES.IV = iv;
        tripleDES.Mode = CipherMode.CBC;
        tripleDES.Padding = PaddingMode.PKCS7;

        ICryptoTransform encryptor = tripleDES.CreateEncryptor(tripleDES.Key, tripleDES.IV);

        byte[] messageBytes = Encoding.UTF8.GetBytes(message);
        byte[] encryptedMessageBytes = encryptor.TransformFinalBlock(messageBytes, 0, messageBytes.Length);

        return Convert.ToBase64String(encryptedMessageBytes);
    }
}
#Ensure you have the pyDes library installed (pip install pyDes)

from pyDes import triple_des, PAD_PKCS5, CBC
import base64

def encrypt_3des(data, key):
    des = triple_des(key, CBC, pad=None, padmode=PAD_PKCS5)

    encrypted_data = des.encrypt(data)
   
    return base64.b64encode(encrypted_data).decode()

# Example usgae:
if __name__ == "__main__":
    # key (24 bytes)
    key = b'Use your 24 bytes key here'
    data = "Hello, Klasha!"
    encrypted_text = encrypt_3des(data, key)
    print("Encrypted text:", encrypted_text)
function encrypt3DES($messageToEncrypt, $secret) {
    $iv = substr($secret, 0, 8); // Get the IV (first 8 bytes of the secret key)
    $cipher = "des-ede3-cbc"; // 3DES encryption with CBC mode
    $options = OPENSSL_RAW_DATA;

    // Encrypt the message
    $encryptedMessageBytes = openssl_encrypt($messageToEncrypt, $cipher, $secret, $options, $iv);

    return base64_encode($encryptedMessageBytes);
}

// NOTE: You need crypto-js.min.js to use CryptoJS

function encrypt3DES(messageToEncrypt, secret) {
    try {
        if (secret.length < 24) {
            console.error("Secret key must be at least 24 characters long.");
            return;
        }

        // Use the first 24 characters of the secret key for 3DES
        const key = CryptoJS.enc.Utf8.parse(secret.substring(0, 24));

        // Use the first 8 characters of the secret key for the IV
        const iv = CryptoJS.enc.Utf8.parse(secret.substring(0, 8));

        // Encrypt the message
        const encrypted = CryptoJS.TripleDES.encrypt(messageToEncrypt, key, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7,
        });

        // Return the Base64-encoded encrypted message
        return encrypted.toString();
    } catch (error) {
        console.error(error);
    }
}

const crypto = require('crypto');

/**
 * Encrypt a message using 3DES with CBC mode and PKCS5 padding.
 * @param {string} messageToEncrypt - The plaintext message to encrypt.
 * @param {Buffer} secret - The 24-byte secret key.
 * @returns {string} The Base64 encoded encrypted message.
 */
function encrypt3DES(messageToEncrypt, secret) {
    if (secret.length !== 24) {
        throw new Error('Secret must be exactly 24 bytes.');
    }
    // Derive the IV from the first 8 bytes of the secret key
    const iv = secret.slice(0, 8);  // First 8 bytes are used as IV

    // Create cipher
    const cipher = crypto.createCipheriv('des-ede3-cbc', secret, iv);

    // Encrypt the message
    let encrypted = cipher.update(messageToEncrypt, 'utf8', 'base64');
    encrypted += cipher.final('base64');

    return encrypted;
}

// Sample Usage
function testEncrypt3DES() {
    const jsonObject = {
        id: 1,
        name: 'John Doe',
        role: 'Senior Backend Engineer',
        skills: ['Java', 'Node.js', 'AWS']
    };

    // Convert JSON object to string
    const message = JSON.stringify(jsonObject);

    // 24-byte secret key
    const secretKey = '24-byte key'; // replace with your 24-byte encryption key

    console.log('Original JSON Object:', jsonObject);
    console.log('Secret Key (Base64):', secretKey.toString('base64'));

    // Encrypt the JSON string
    const encryptedMessage = encrypt3DES(message, secretKey);
    console.log('Encrypted Message (Base64):', encryptedMessage);
}

testEncrypt3DES();

Card payments

To accept a card payment, you need to integrate with the following flow:

  • First, initiate the card payment

  • Then charge the card

  • And at the end validate the payment (to provide OTP and/or PIN)

Initiate card payment

POST {{env_url}}/pay/aggregators/{{gateway}}/card/payment/v2

You’d need to pass, as header the x-auth-token. This can be obtained from your merchant dashboard → Settings → Generate API keys → Merchant public key.

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Request Body (encrypted)

{
    "message": "encrypted-body"
}

Request Body (plain)

{
   "card_number": "507850785078507812",
   "card_holder_name": "John Doe",
   "cvv": "081",
   "expiry_month": "05",
   "expiry_year": "25",
   "currency": "NGN",
   "country": "NG",
   "amount": "200",
   "rate": 1,
   "paymentType": "woo",
   "sourceCurrency": "NGN",
   "sourceAmount": 200,
   "rememberMe": true,
   "phone_number": "080344006699",
   "email": "email@klasha.com",
   "fullname": "John Doe",
   "tx_ref": "test910-on2007u047e-2910tytrr76"
}

Response

{
    "message": "success",
    "error": null,
    "data": {
        "tx_ref": null,
        "data": {
           "status": "success",
            "message": "Charge authorization data required",
            "meta": {
                "authorization": {
                    "mode": "pin",
                    "fields": [
                        "pin"
                    ]
                }
            }
        }
    }
}
This is for cards that are covered by 3DS flows.
{
    "tx_ref": "klasha-add-bank-card-1697954ttt947238348",
    "redirectUrl": "https://coreflutterwavestaging.com/flwmpgs/trxauth?hid=712b85a8542649e68c19b1c80d81aadc",
    "data": {
        "meta": {
            "authorization": {
                "mode": "redirect",
                "redirect": "https://coreflutterwavestaging.com/flwmpgs/trxauth?hid=712b85a8542649e68c19b1c80d81aadc"
            }
        }
    }
}
{
    "message": "success",
    "error": null,
    "data": {
        "tx_ref": null,
        "data": {
           "status": "success",
            "message": "Charge authorization data required",
            "meta": {
                "authorization": {
                    "mode": "avs_noauth",
                    "fields": [
                        "city",
                        "address",
                        "state",
                        "country",
                        "zipcode"
                    ]
                }
            }
        }
    }
}
{
    "status": "error",
    "message": "Card number is invalid",
    "data": null,
    "tx_ref": "klasha-add-bank-card-1697954ttt947238348"
}

Charge card

POST {{env_url}}/pay/aggregators/{{gateway}}/charge/card/v2

You’d need to pass, as header the x-auth-token. This can be obtained from your merchant dashboard → Settings → Generate API keys → Merchant public key.

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Request Body (encrypted)

{
    "message": "encrypted-body"
}

Request Body (plain)

The tx-ref is contained in the successful response of the initiate payment call.

{
    "mode": "pin",
    "pin": "1111",
    "tx_ref": "test910-on2007u047e-2910tytrr76"
}
{
    "mode": "avs_noauth",
    "city": "city",
    "address": "address",
    "state": "state",
    "country": "country",
    "zipcode": "zipcode",
    "tx_ref": "test910-on2007u047e-2910tytrr76"
}

Response

{
    "message": "success",
    "error": null,
    "data": {
       "tx_ref": "test910-on2007u047e-2910tytrr76",
       "message": "Please enter the OTP sent to your mobile number 080****** and email te**@rave**.com",
       "status": "pending"
    }
}
{
    "status": "error",
    "message": "Invalid Pin",
    "data": null,
    "tx_ref": "klasha-add-bank-card-odochi_test_test11"
}

Validate card

POST {{env_url}}/pay/aggregators/{{gateway}}/validate/card/v2

You would need to pass, as header the x-auth-token. This can be obtained from your merchant dashboard → Settings → Generate API keys → Merchant public key.

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Request Body (encrypted)

{
    "message": "encrypted-body"
}

Request Body (plain)

The tx-ref is contained in the successful response of the initiate payment call.

{
  "otp": "123456",
  "tx_ref": "test910-on2007u047e-291076",
  "type": "card"
}

Response

{
    "message": "success",
    "error": null,
    "data": {
       "tx_ref": "test910-on2007u047e-291076",
       "amount": 200.0,
       "processor_response": "successful",
       "message": "Charge validated",
       "status": "successful"
    }
}
{
    "status": "error",
    "message": "Invalid OTP",
    "data": null,
    "tx_ref": "klasha-add-bank-card-odochi_test_test11"
}

Bank transfer

POST {{env_url}}/pay/aggregators/{{gateway}}/banktransfer/v2

You’d need to pass, as header the x-auth-token. This can be obtained from your merchant dashboard → Settings → Generate API keys → Merchant public key.

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Request Body (encrypted)

{
    "message": "encrypted-body"
}

Request Body (plain) for different gateways.

{
   "tx_ref": "MC-15856767458ffdgddfefhqweert",
   "amount": "500",
   "email": "email@gmail.com",
   "phone_number": "054709929220",
   "currency": "NGN",
   "narration": "A payment",
   "rate": 1.0,
   "paymentType": "woo",
   "sourceCurrency": "NGN",
   "sourceAmount": 500,
   "fullname": "Test"
}
{
   "tx_ref": "test-15856767458ffdgddfefhqweert",
   "amount": "500",
   "email": "email@gmail.com",
   "phone_number": "054709929220",
   "currency": "ZAR",
   "narration": "A payment",
   "rate": 1.0,
   "redirect_url": "merchant_url",
   "paymentType": "woo",
   "sourceCurrency": "ZAR",
   "sourceAmount": 500,
   "fullname": "Test"
}

Response for different gateways.

{
    "message": "success",
    "error": null,
    "data": {
        "tx_ref": "MC-15856767458ffdgddfefhqweert",
        "meta": {
            "authorization": {
                "mode": "banktransfer",
                "transfer_note": "Please make a bank transfer to Klasha - Collection",
                "transfer_amount": 500.0,
                "transfer_bank": "WEMA BANK",
                "account_expiration": "2024-05-23T13:55:13.105",
                "transfer_account": "8574551243"
            }
        },
        "message": "Charge initiated",
        "status": "success"
    }
}
{
    "status": "success",
    "message": "Charge initiated",
    "data": {
        "tx_ref": "test_xfer_29071707",
        "message": "Transaction in progress",
        "meta": {
            "authorization": {
                "mode": "redirect",
                "redirect": "https://stagingpay.ozow.com/b1c1bb59-bf46-42ee-bc76-ccdf63e3f453/Secure",
                "validate_instructions": ""
            }
        }
    }
}

M-Pesa

POST {{env_url}}/pay/aggregators/{{gateway}}/card/payment/v2

You would need to pass, as header the x-auth-token. This can be obtained from your merchant dashboard → Settings → Generate API keys → Merchant public key.

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Request Body (encrypted)

{
    "message": "encrypted-body"
}

Request Body (plain)

{
   "currency": "KES",
   "country": "KE",
   "amount": "10",
   "rate": 680,
   "paymentType": "woo",
   "sourceCurrency": "KES",
   "sourceAmount": 10,
   "rememberMe": true,
   "option": "mpesa",
   "phone_number": "+254710000000",
   "email": "email@klasha.com",
   "fullname": "John Doe",
   "tx_ref": "test910-on2007u047e-291076"
}

Response

{
    "message": "success",
    "error": null,
    "data": {
        "tx_ref": "test910-on2007u047e-291076",
        "data": {
            "amount": "10",
            "charged_amount": "10",
            "currency": "KES",
            "customer": {
                "name": "John Doe",
                "phone_number": "+254710000000",
                "email": "email@klasha.com"
            },
            "status": "pending"
        },
        "message": "Transaction in progress",
        "status": "pending"
    }
}
{
    "tx_ref": "test910-on2007u047e-mcnvmlbhgmjfo",
    "data": null,
    "message": "Invalid phone number format",
    "status": "error"
}

Initiate a refund

POST {{env_url}}/nucleus/refund/initiate/v3

You would need to pass, as header the x-auth-token. This can be obtained from your merchant dashboard → Settings → Generate API keys → Merchant public key.

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Request Body (encrypted)

{
    "message": "encrypted-body"
}

Request Body (plain)

{
    "txRef": "txRef",
    "amount": 500,
    "refundType": "partial"
}
Name
Description

txRef

Transaction reference

refundType

partial or full

amount

refund amount

Response

{
    "message": "success",
    "error": null,
    "data": {
        "txRef": "txRef",
        "refundTnxId": 12222,
        "businessId": 133,
        "refundedAmount": 500,
        "status": "pending"
    }
}
{
    "message": "Given final block not properly padded. Such issues can arise if a bad key is used during decryption.",
    "error": "Bad Request",
    "data": null
}

Get a refund

GET {{env_url}}/nucleus/refund/status/{{txRef}}/v2

Headers

Name
Value

Content-Type

application/json

x-auth-token

Your merchant public key

Response

{
    "message": "success",
    "error": null,
    "data": [
        {
            "refundType": "full",
            "txRef": "txRef",
            "refundTnxId": null,
            "businessId": 133,
            "refundedAmount": null,
            "status": "pending"
        }
    ]
}
{
    "message": "Given final block not properly padded. Such issues can arise if a bad key is used during decryption.",
    "error": "Bad Request",
    "data": null
}

Generate a bearer token

Exchange rate

POST {{env_url}}/nucleus/general/exchange/

Make a POST call to the exchange rate API.

Headers

Name
Value

Content-Type

application/json

Authorization

Bearer "token"

Request Body

Name
Description

sourceCurrency

currency users will pay in

amount

amount

destinationCurrency

destination currency

productType

KLASHA_PAY (static value)

businessId

your business ID

Response

{
    "message": "success",
    "error": null,
    "data": {
        "amount": 1557632.40,
        "rate": 0.000642,
        "buyingRate": 0.000676,
        "destinationCurrency": "NGN",
        "sourceCurrency": "USD",
        "cards": null
    }
}
{
    "message": "No exchange found",
    "error": "Not Found",
    "data": null
}

You can find more information on the as well as other APIs.

You can find more information on the as well as other APIs.

You can find more information on the as well as other APIs.

You can find more information on the as well as other APIs.

You can find more information on the as well as other APIs.

Postman link
Postman link
Postman link
Postman link
Postman link
Token Generation
Mobile money
USSD
here
Card Payments
Bank transfer
M-Pesa