MOKO Afrika API

MOKO Afrika API Documentation

Version: 6.0 | Last Updated: July 2024

MOKO Afrika Presentation

MOKO Afrika is a payment aggregator that connects merchants and telecommunications networks to enable secure, real-time transactions. It provides a flexible API for seamless payment integration, supporting various payment methods while ensuring security and scalability for businesses in sectors like e-commerce and financial services.

Welcome to the MOKO Afrika Payment Processing API documentation. This guide provides detailed information on how to interact with the MOKO Afrika payment switch for send money and payment transactions.

Transaction Handling

Communication with the MOKO Afrika processor API follows an asynchronous communication model. In this model, the initiator sends a request to the API, which returns a response that is not the final status of the transaction. The initial response is merely an acknowledgment indicating that the money transfer request has been received.

To obtain the final status of the transaction, the initiator must perform a check using an appropriate search action via the same API, but with a slightly different parameter format. This allows the initiator to retrieve the updated status of the transaction.

Additionally, final status notifications can also be sent to the initiator via a callback mechanism. When making a transaction request, you can specify a callback URL in the request parameters. Once the final status of the transaction is available, MOKO Afrika will send a notification to this callback URL with the transaction details, including the final status.

Basic Flow

Client Application

MOKO Afrika API

Payment Processor

Mobile Money Platform / Bank

Authentication

To interact with the MOKO Afrika API, you need to authenticate your requests using a token. This token is generated using your merchant ID and merchant secret.

Generate Authentication Token

To generate an authentication token for interacting with the processor API, you can make a request to the following endpoint:

POSThttps://paydrc.gofreshbakery.net/api/v5/token

Request

Request Body
{
  "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "merchant_secrete": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response

Response Body
{
  "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "merchant_secrete": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE3MDk4OTMwODcsIm5iZiI6MTcwOTg5MzA4NywinanRpIjoiNmFlNTVjM2EtOGU4Zi00MTJiLTgxMDYtY2ZhMzE4MTliODUzIiwiZXhwIjoxNzA5ODkzMjA3LCJpZGVudGl0eSI6Imp3SGZqZG9wZW5jM3l0JFRiIiwiZnJlc2giOmZhbHNlLCJ0eXBlIjoiYWNjZXNzIn0.hjgCcpZ9gLZWJY9oZfV-fX2c-QYvPIuHU0zLeLk6-cg"
}

Important Note

The authentication token has a limited validity period. Make sure to generate a new token if your previous one has expired. You should include this token in the Authorization header of your subsequent API requests.

Generate Merchant Secret

By default, upon the creation of a merchant account, the merchant_secrete is sent to the merchant via email. However, this behavior can be changed as needed.

This request allows you to change the merchant_secrete associated with a specific merchant_id. Make sure to specify the correct merchant_id in the request to perform the modification correctly.

POSThttps://paydrc.gofreshbakery.net/api/v1/merchant/secrete

Request

Request Body
{
  "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Response

Response Body
{
  "resultCode": 0,
  "resultCodeDescription": "Processed",
  "resultData": {
    "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "merchant_secrete": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
    "updated_at": "2024-03-08 09:45:01.326874"
  }
}

Security Note

Keep your merchant secret secure and do not share it with unauthorized parties. If you suspect your secret has been compromised, generate a new one immediately using this endpoint.

Payment Methods

MOKO Afrika supports various payment methods for transactions. Each payment method has a specific identifier that should be used in the method field of your API requests.

OperatorPayment ServiceMethod IdentifierStatus
AirtelAirtel MoneyairtelAvailable
OrangeOrange MoneyorangeAvailable
VodacomM-PesampesaAvailable
AfricellAfrimoneyafricellAvailable

Note

For each payment method, make sure to use the correct method identifier in the method field of your API requests. Using an incorrect or unsupported method will result in an error.

Transactions

MOKO Afrika API allows you to perform two types of transactions: Deposit (C2B) and Payout (B2C). This section explains how to initiate these transactions and handle responses.

Deposit and Payout

Developers can interact with the processor to either place a request for debit (C2B) or credit (B2C), or to request the status of a particular transaction.

POSThttps://paydrc.gofreshbakery.net/api/v5/

Parameters

ParameterTypeRequiredDescription
merchant_idstringRequiredYour MOKO Afrika merchant ID
merchant_secretestringRequiredYour MOKO Afrika merchant secret key
amountstringRequiredThe transaction amount
currencystringRequiredThe currency of the transaction (CDF or USD)
actionstringRequiredThe action to perform (debit or credit)
customer_numberstringRequiredThe customer's phone number
firstnamestringRequiredThe customer's first name
lastnamestringRequiredThe customer's last name
e-mailstringRequiredThe customer's email address
referencestringRequiredA unique reference for the transaction
methodstringRequiredThe payment method to use (e.g., airtel, orange, mpesa)
callback_urlstringOptionalThe URL where MOKO Afrika will send transaction notifications

Request Examples

Requesting Debit (C2B)

To initiate a debit transaction (C2B), developers can send a request to the processor API with the necessary parameters.

Debit Request
{
  "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "merchant_secrete": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "amount": "100",
  "currency": "CDF",
  "action": "debit",
  "customer_number": "0972148867",
  "firstname": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "lastname": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "e-mail": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "reference": "testfp09",
  "method": "airtel",
  "callback_url": ""
}

Requesting Payout (B2C)

Similarly, developers can place a request for a credit transaction (B2C) by sending the required parameters to the processor API.

Credit Request
{
  "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "merchant_secrete": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "amount": "100",
  "currency": "CDF",
  "action": "credit",
  "customer_number": "0972148867",
  "firstname": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "lastname": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "e-mail": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "reference": "testfp09",
  "method": "airtel",
  "callback_url": ""
}

Responses

Upon success, you will receive a response with the HTTP status 200 OK and details of the transaction performed.

Success Response
{
  "Amount": 100,
  "Comment": "Transaction Received Successfully",
  "Created_At": "2024-03-08 08:08:51.533410",
  "Currency": "CDF",
  "Customer_Number": "972148867",
  "Reference": "testfp09",
  "Status": "Success",
  "Transaction_id": "PDABXkT03IfD08M9PfR24Ci4",
  "Updated_At": "2024-03-08 08:08:51.533410"
}

Errors

In case of an error, you will receive a response with the corresponding HTTP status and a detailed message explaining the issue.

Error Response
{
  "Comment": "Customer number is incorrect, be sure to start with 243",
  "Status": "Error",
  "resultCode": 1,
  "resultCodeDescription": "request not executed...",
  "resultCodeError": 405,
  "resultCodeErrorDescription": "Customer number is incorrect, be sure to start with 243..."
}

Callbacks

MOKO Afrika can send transaction notifications to the specified URL via a callback method. Here's an example of a callback payload:

Callback Status Fields

  • Status: Indicates the current status of the transaction request, confirming that the money transfer request has been successfully received and acknowledged.
  • Trans_Status: Is the final status of the transaction.

Failed Transaction Callback

Failed Transaction Callback
{
  "Action": "debit",
  "Amount": 100.0,
  "Comment": "Transaction Found",
  "Currency": "CDF",
  "Customer_Details": "972148867",
  "Financial_Institution_id": "",
  "Method": "airtel",
  "PayDRC_Reference": "PD9pLLM03QZJ08X7fXM242x6",
  "Reference": "testfp09",
  "Status": "Success",
  "Status_Description": "La reference de la transaction est invalide, veuillez reesayez ou contactez le service client au 1213",
  "Trans_Status": "Failed",
  "Trans_Status_Description": "La reference de la transaction est invalide, veuillez reesayez ou contactez le service client au 1213"
}

Successful Transaction Callback

Successful Transaction Callback
{
  "Action": "credit",
  "Amount": 100.0,
  "Comment": "Transaction Found",
  "Currency": "CDF",
  "Customer_Details": "972148867",
  "Financial_Institution_id": "CI240308.0908.C64554",
  "Method": "airtel",
  "PayDRC_Reference": "PDABXkT03IfD08M9PfR24Ci4",
  "Reference": "testfp09",
  "Status": "Success",
  "Status_Description": "Trans.ID: CI240308.0908.C64554 vous avez envoye de 100.0000 CDF a 972148867.Votre solde est -606965937.9689CDF.Cout:1.1600CDF",
  "Trans_Status": "Success",
  "Trans_Status_Description": "Transaction successful"
}

Callback Security

MOKO Afrika ensures security and data integrity through multiple security measures when sending callbacks to your systems:

  • HMAC-SHA256 Signature – To verify the authenticity of requests and prevent tampering
  • AES-256-CBC Encryption – To protect sensitive data during transmission
  • IP Whitelisting – To restrict access to authorized sources only
  • Strict Access Control – To prevent fraudulent manipulation

Security and Compliance

HMAC-SHA256 Signature

To guarantee the integrity of incoming data, MOKO Afrika uses an HMAC-SHA256 signature. This ensures that the message has not been altered and originates from a trusted source.

How it works:

  • The sender generates a signature using the HMAC-SHA256 algorithm with a secret key.
  • The recipient recalculates the signature using the same method and compares it to the received signature.
  • If both signatures match, the message is authenticated.

AES-256-CBC Encryption

To ensure that only the intended recipient can read the data, AES-256-CBC encryption is used.

How it works:

  • The message is encrypted using an AES key and an initialization vector (IV).
  • The recipient decrypts the message using the same AES key.

Even if an attacker intercepts the message, they cannot read it without the secret key.

IP Whitelisting

MOKO Afrika requires that clients whitelist our IP addresses. This ensures that only authorized systems can send or receive callbacks.

Security Benefits:

  • Prevents unauthorized requests from external sources.
  • Reduces the risk of DDoS attacks or fake transactions.
  • Ensures callbacks are only processed by trusted partners.

Callback Details

Request Format

Each payment notification sent by MOKO Afrika includes:

  • HTTP Method: POST
  • Required Headers:
    • Content-Type: application/json
    • X-Signature: <HMAC_SHA256_SIGNATURE>
  • Body Format: (JSON)

Example Request

Callback Request
{
  "data": "<ENCRYPTED_PAYLOAD>"
}

Expected Response Format

Your server must respond with either a success or an error message based on the validation of the request.

Successful Response (200 OK)

Success Response
{
  "status": "Callback received successfully",
  "data": { ... }
}

Error Responses

  • 400 Bad Request → Invalid encryption
  • 401 Unauthorized → Invalid signature

Implementation in Different Languages

Below are secure implementations in Python, PHP, and Node.js for processing the callback safely.

Python Implementation

Python Implementation
import json
import base64                                                                                               
import hashlib
import hmac
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from flask import Flask, request, jsonify
  
SECRET_KEY = b'xxxxxxxxxxxxxxxx'  # 16-byte AES key
HMAC_KEY = b'xxxxxxxxxxxxxxxx'
  
app = Flask(__name__)
  
def decrypt_data(encrypted_data):
  cipher = AES.new(SECRET_KEY, AES.MODE_CBC, iv=SECRET_KEY)
  decrypted_bytes = unpad(cipher.decrypt(base64.b64decode(encrypted_data)), AES.block_size)
  return json.loads(decrypted_bytes.decode())
  
def verify_signature(encrypted_message, received_signature):
  calculated_signature = hmac.new(HMAC_KEY, encrypted_message.encode(), hashlib.sha256).hexdigest()
  return hmac.compare_digest(calculated_signature, received_signature)
  
@app.route('/callback', methods=['POST'])
def callback_handler():
  data = request.json.get("data")
  received_signature = request.headers.get("X-Signature")
  if not received_signature:
    return jsonify({"error": "Signature missing"}), 400
  if verify_signature(data, received_signature):
    try:
      decrypted_data = decrypt_data(data)
      return jsonify({"status": "Callback received", "data": decrypted_data}), 200
    except Exception:
      return jsonify({"error": "Invalid encryption"}), 400
  else:
    return jsonify({"error": "Invalid signature"}), 401

PHP Implementation

PHP Implementation
<?php
define('SECRET_KEY', 'xxxxxxxxxxxxxxxx');
define('HMAC_KEY', 'xxxxxxxxxxxxxxxx');
  
function decrypt_data($encrypted_data) {
  $decoded_data = base64_decode($encrypted_data);
  $iv = SECRET_KEY;
  $decrypted = openssl_decrypt($decoded_data, 'AES-128-CBC', SECRET_KEY, OPENSSL_RAW_DATA, $iv);
  return json_decode($decrypted, true);
}
  
function verify_signature($encrypted_message, $received_signature) {
  $calculated_signature = hash_hmac('sha256', $encrypted_message, HMAC_KEY);
  return hash_equals($calculated_signature, $received_signature);
}
  
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $data = json_decode(file_get_contents('php://input'), true)['data'];
  $received_signature = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
  
  if (!$received_signature) {
    echo json_encode(["error" => "Signature missing"]);
    http_response_code(400);
    exit;
  }
  
  if (verify_signature($data, $received_signature)) {
    try {
      $decrypted_data = decrypt_data($data);
      echo json_encode(["status" => "Callback received", "data" => $decrypted_data]);
      http_response_code(200);
    } catch (Exception $e) {
      echo json_encode(["error" => "Invalid encryption"]);
      http_response_code(400);
    }
  } else {
    echo json_encode(["error" => "Invalid signature"]);
    http_response_code(401);
  }
}
?>

Node.js Implementation (Express.js)

Node.js Implementation
const express = require('express');
const crypto = require('crypto');
const base64 = require('base-64');
const bodyParser = require('body-parser');
  
const app = express();
app.use(bodyParser.json());
  
const SECRET_KEY = Buffer.from('xxxxxxxxxxxxxxxx'); // 16-byte AES key
const HMAC_KEY = 'xxxxxxxxxxxxxxxx';
  
// Function to decrypt AES-256-CBC data
function decryptData(encryptedData) {
  const decipher = crypto.createDecipheriv('aes-128-cbc', SECRET_KEY, SECRET_KEY);
  let decrypted = decipher.update(base64.decode(encryptedData), 'base64', 'utf8');
  decrypted += decipher.final('utf8');
  return JSON.parse(decrypted);
}

// Function to verify HMAC-SHA256 signature
function verifySignature(encryptedMessage, receivedSignature) {
  const hmac = crypto.createHmac('sha256', HMAC_KEY);
  hmac.update(encryptedMessage);
  const calculatedSignature = hmac.digest('hex');
  return calculatedSignature === receivedSignature;
}

// Route to handle callback
app.post('/callback', (req, res) => {
  const data = req.body.data;
  const receivedSignature = req.headers['x-signature'];
  
  if (!receivedSignature) {
    return res.status(400).json({ error: "Signature missing" });
  }
  
  if (verifySignature(data, receivedSignature)) {
    try {
      const decryptedData = decryptData(data);
      return res.status(200).json({ status: "Callback received", data: decryptedData });
    } catch (error) {
      return res.status(400).json({ error: "Invalid encryption" });
    }
  } else {
    return res.status(401).json({ error: "Invalid signature" });
  }
});
  
app.listen(3000, () => console.log('Callback server running on port 3000'));

Security Benefits

  • Encryption (AES-256-CBC): Protects data from being read if intercepted.
  • HMAC-SHA256 Signature: Ensures data integrity and authenticity.
  • Whitelisting IP Addresses: Allows only trusted sources to send callbacks.
  • Strict Validation: Prevents unauthorized transactions or tampering.

Remittance

This API allows for remittance transactions, which involve transferring funds from a sender to a recipient.

POSThttps://paydrc.gofreshbakery.net/api/v5/

Parameters

ParameterTypeRequiredDescription
merchant_idstringRequiredUnique identifier for the merchant
merchant_secretestringRequiredMerchant's secret key for authentication
amountstringRequiredAmount to be transferred
currencystringRequiredCurrency in which the amount is expressed (e.g., USD, CDF)
actionstringRequiredType of transaction (e.g., inbound, outbound)
customer_numberstringRequiredCustomer's phone number
firstnamestringRequiredCustomer's first name
lastnamestringRequiredCustomer's last name
e-mailstringRequiredCustomer's email address
referencestringRequiredUnique reference for the transaction
methodstringRequiredPayment method used (e.g., airtel, orange, mpesa)
prenom_expediteurstringRequiredSender's first name
prenom_destinatairestringRequiredRecipient's first name
nom_expediteurstringRequiredSender's last name
nom_destinatairestringRequiredRecipien's last name
nationalite_expediteurstringRequiredSende's nationality
nationalite_destinatairestringRequiredRecipient's nationality
numero_identitestringRequiredSender's identity document number
nom_fournisseurstringRequiredName of the service provider
date_naissance_expediteurstringRequiredSender's birthdate (format: YYYY-MM-DD)
pays_envoistringRequiredCountry of origin of the transfer
pays_receptionstringRequiredCountry where the funds will be received
ville_expediteurstringRequiredSender's city of residence
date_naissance_beneficiaire_lieustringRequiredRecipient's birthdate and place (format: YYYY-MM-DD, City)
date_emission_document_identitestringRequiredIssue date of the identity document (format: YYYY-MM-DD)
date_expiration_document_identitestringRequiredExpiry date of the identity document (format: YYYY-MM-DD)
adresse_actuellestringRequiredSender's current address
adresse_permanentestringRequiredSender's permanent address
professionstringRequiredSender's occupation

Sample Request

Remittance Request
{
  "merchant_id": "jwHfjdopenc3yt$Tb",
  "merchant_secrete": "jz5ulzR!a54kGg!iF",
  "amount": "100.00",
  "currency": "CDF",
  "action": "inbound",
  "customer_number": "0842634652",
  "firstname": "SupportTest",
  "lastname": "SupportTest",
  "e-mail": "support@gofreshbakery.com",
  "reference": "REF123456",
  "method": "orange",
  "prenom_expediteur": "Jean",
  "prenom_destinataire": "Marie",
  "nom_expediteur": "Dupont",
  "nom_destinataire": "Martin",
  "nationalite_expediteur": "French",
  "nationalite_destinataire": "Canadian",
  "numero_identite": "AB1234567",
  "nom_fournisseur": "ProviderName",
  "date_naissance_expediteur": "1980-01-01",
  "pays_envoi": "France",
  "pays_reception": "Canada",
  "ville_expediteur": "Paris",
  "date_naissance_beneficiaire_lieu": "1985-05-15, Toronto",
  "date_emission_document_identite": "2022-01-01",
  "date_expiration_document_identite": "2032-01-01",
  "adresse_actuelle": "123 Current St, Paris, France",
  "adresse_permanente": "456 Permanent Ave, Paris, France",
  "profession": "Engineer"
}

Sample Response

Remittance Response
{
  "Amount": 100,
  "Comment": "Transaction Received Successfully",
  "Created_At": "2024-07-19 13:32:11.750967",
  "Currency": "CDF",
  "Customer_Number": "0842634652",
  "Reference": "REF123456",
  "Status": "Success",
  "Transaction_id": "PDsfCS007JfM19jIhFz247bw",
  "Updated_At": "2024-07-19 13:32:11.750967"
}

Checking Transaction Status

The verify endpoint allows you to check the status of a transaction. This is particularly useful for asynchronous transactions where the final status might not be immediately available.

POSThttps://paydrc.gofreshbakery.net/api/v5/

Parameters

ParameterTypeRequiredDescription
merchant_idstringRequiredYour MOKO Afrika merchant ID
merchant_secretestringRequiredYour MOKO Afrika merchant secret key
actionstringRequiredThe action to perform (verify)
referencestringRequiredThe transaction reference or ID to check

Request Example

Status Check Request
{
  "merchant_id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "merchant_secrete": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "action": "verify",
  "reference": "PDYjZJL10X8J26VcQmM23bHV"
}

Response

Status Check Response
{
  "Action": "debit",
  "Amount": 100.0,
  "Comment": "Transaction Found",
  "Created_at": "2024-03-08 08:05:37",
  "Currency": "CDF",
  "Customer_Details": "972148867",
  "Financial_Institution_id": "null",
  "Method": "airtel",
  "Reference": "testfp09",
  "Status": "Success",
  "Trans_Status": "Failed",
  "Trans_Status_Description": "La reference de la transaction est invalide, veuillez reesayez ou contactez le service client au 1213",
  "Transaction_id": "PD9pLLM03QZJ08X7fXM242x6",
  "Updated_at": "2024-03-08 08:51:30"
}

Important Note

The Trans_Status field in the response indicates the final status of the transaction. Possible values include "Successful", "Failed", "Pending", etc. Always check this field to determine the actual outcome of the transaction.

Error Codes

When interacting with the MOKO Afrika API, you may encounter various error codes. This section provides a comprehensive list of error codes, their descriptions, and recommended actions.

ErrorStatusCodeDescriptionComment
An Error Occurred During ExecutionError400An error occurred during the execution of the request.There was an error during the execution of the request.
You Cannot Make a Payment of This AmountError401You cannot make a payment of this amount.The specified payment amount is not allowed or exceeds the limit.
Your Balance is InsufficientError402Your balance is insufficient to make this payment.Your account balance is not enough to cover the payment.
Transaction Identifier Not RecognizedError404The transaction identifier is not recognized in the system.The provided transaction identifier does not exist in the system.
Wallet Identifier Not RecognizedError404The wallet identifier is not recognized in the system.The provided wallet identifier does not exist in the system.
User Information Not FoundError404User information was not found in the system.User information could not be found in the system or the user does not have sufficient authorization.
Merchant Identifier Not RecognizedError404The provided merchant identifier is not recognized in the system.Please ensure that you provide valid merchant information in the request parameters (merchant_id, merchant_secrete, firstname, lastname)
Country Flag Not AllowedError405The country flag in the provided phone number is not allowed.Please ensure that you are using a phone number with the correct country code (243 for DRC).
Incorrect Customer Number PrefixError405The prefix of the customer phone number is incorrect.Please ensure that the customer phone number starts with "+243" for DRC country code.
Invalid Currency ValueError407The provided currency value is incorrect or unrecognized.Currency can only be specified as USD or CDF.
Action Not RecognizedError408The specified action is not recognized by the system.Please ensure that you are using a valid action according to the documentation.
Connectivity Problem with the DatabaseError409Connectivity problem with the database.There was a connectivity issue with the database.
Internal Server ErrorError500Internal server error.There was an internal server error.

Error Handling Best Practices

  • Always check the status code and error message in the API response.
  • Implement proper error handling in your application to gracefully handle API errors.
  • For persistent errors, contact MOKO Afrika support at support@mokoafrika.com.