Accept Mobile Money Payment with APIs
Another way to accept payments is by using our Mobile Money APIs. The comprehensive guide below will walk you through the process of successfully accepting mobile money on Kora using our APIs.
Get started with accepting Mobile money using APIs
We currently support payments in Kenyan Shillings, Ghanaian Cedis, Cameroonian CFA Franc & Ivorian CFA Franc. For Kenya, we support the following wallets; Mpesa, Airtel, and Equitel. While for Ghana we support; MTN Momo and Airtel Tigo. For Cameroon and Ivory Coast we support both MTN and Orange. Here are some test mobile money numbers we created to help you simulate different scenarios for mobile money payments as you integrate.
Step 1: Collect payment data required to initiate payment
To charge a customer, you will need to collect the necessary payment information from the customer.
Here are the request parameters.
Parameter | Type | Required | Description |
---|---|---|---|
reference | String | True | A unique reference for the payment. The reference must be at least 8 characters long. |
amount | Number | True | The amount for the charge |
currency | String | True | The currency for the charge |
redirect_url | String | False | A URL to which we can redirect your customer after their payment is complete |
customer | Object | True | The information of the customer you want to charge |
customer.name | String | False | The name of your customer |
customer.email | String | True | The email of your customer |
mobile_money | Object | True | Object holding the mobile money wallet details |
mobile_money.number | String | True | The mobile number of the customer to be charged e.g 254700000000 |
notification_url | String | False | The webhook URL to be called when the transaction is complete. |
merchant_bears_cost | Boolean | False | This sets who bear the fees of the transaction. If it is set to true, the merchant will bear the fee. If it is set to false, the customer will bear the fee. By default, it is false. |
description | String | False | Information/narration about the transaction |
metadata | Object | False | It takes a JSON object with a maximum of 5 fields/keys. Empty JSON objects are not allowed. Each field name has a maximum length of 20 characters. Allowed characters: A-Z, a-z, 0-9, and -. |
After collecting the necessary mobile money payment information from your customer, prepare your data object to look like the example shown below.
{
"amount": 701,
"currency": "GHS",
"reference": "idkMain27105551011",
"description": "Payment for a emilokan",
"notification_url": "https://webhook.site/1c209942-1a66-4cdf-a7ab-78d9cc684ad2",
"redirect_url": "https://webhook.site",
"customer": {
"name": "John Doe",
"email": "[email protected]"
},
"merchant_bears_cost": true,
"mobile_money": {
"number": "254700000000"
}
}
To charge the number make a POST
request with the payload to our charge mobile money endpoint. Ensure to include the relevant country currency.
Endpoint - POST https://api.korapay.com/merchant/api/v1/charges/mobile-money
If the request is successful, you should receive a message with either OTP
or STK_PROMPT
as the auth model.
Sample OTP
Auth Response:
{
"status": true,
"code": "AA001",
"message": "Authorization required",
"data": {
"amount": 701,
"amount_expected": 701,
"currency": "GHS",
"fee": 1.87,
"vat": 0.13,
"auth_model": "OTP",
"transaction_reference": "KPY-PAY-rYF4c5ZWioeb",
"payment_reference": "idkMain27105551021",
"status": "processing",
"narration": "Payment for a emilokan",
"message": "Token generated and sent out successfully",
"mobile_money": {
"number": "+254700000000"
},
"customer": {
"name": "John Doe",
"email": "[email protected]"
}
}
}
Sample STK_PROMPT
Auth Response:
{
"status": true,
"code": "AA001",
"message": "Authorization required",
"data": {
"amount": 10,
"amount_expected": 10,
"currency": "KES",
"fee": 0.25,
"vat": 0.04,
"auth_model": "STK_PROMPT",
"transaction_reference": "KPY-PAY-rYF4c5ZWioeb",
"payment_reference": "KPY-PAY-79lsPQSqHXSz",
"status": "processing",
"narration": "Live Test Link",
"message": "You will receive a pin prompt on your mobile number +25470000000 for GHS 10. Kindly enter your wallet PIN to authorize the payment",
"mobile_money": {
"number": "254700000000"
},
"customer": {
"name": "John Doe",
"email": "[email protected]"
}
}
}
Step 2: Authorize mobile money transaction
The next step is based on the auth model returned in the previous response after initiating the charge. There are 2 ways of authorizing a transaction OTP
and STK_PROMPT
.
Authorizing an OTP transaction
After making the request to charge the number, if the status of the transaction is processing and auth_model is OTP, this means an OTP has been sent to the wallet owner's phone. You would need to collect the OTP in order to authorize the transaction.
Collect the OTP sent to the customer’s phone and make a request to our authorize endpoint with the OTP and the transaction reference.
Endpoint - https://api.korapay.com/merchant/api/v1/charges/mobile-money/authorize
curl --location 'https://api.korapay.com/merchant/api/v1/charges/mobile-money/authorize' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_KORAPAY_SECRET_KEY' \
--data '{
"reference": "KPY-PAY-rYF4c5ZWioeb",
"token": "123456"
}'
-X POST
If the OTP verification is successful, an STK prompt will be sent to the wallet owner's phone for him to enter his PIN.
Sample response
{
"status": true,
"message": "Authorization required",
"data": {
"amount": "10.00",
"amount_expected": "10.00",
"currency": "GHS",
"fee": 1.75,
"vat": 0.12,
"auth_model": "STK_PROMPT",
"transaction_reference": "KPY-PAY-rYF4c5ZWioeb",
"payment_reference": "KPY-PAY-rYF4c5ZWioeb",
"status": "processing",
"message": "You will receive a prompt on mobile number. Kindly enter your wallet PIN to authorize the payment",
"mobile_money": {
"number": "+254700000000"
}
}
}
{
"status": true,
"message": "Authorization required",
"data": {
"amount": "10.00",
"amount_expected": "10.00",
"currency": "GHS",
"fee": 1.75,
"vat": 0.12,
"auth_model": "OTP",
"transaction_reference": "KPY-PAY-rYF4c5ZWioeb",
"payment_reference": "KPY-PAY-rYF4c5ZWioeb",
"status": "processing",
"message": "The OTP you provided is invalid",
"mobile_money": {
"number": "+254700000000"
},
"attempts_left": 2
}
}
Authorizing an STK transaction
After making the request to charge/authorize the number, if the status of the transaction is processing and auth_model is STK, this means an STK has been sent to the wallet owner's phone.
Step 3: Verify Payment
The final step after receiving payment is to ensure that the payment was successful by making a verification request to our verification charge endpoint. The reference here should be your transaction reference.
Here's a sample request and response for verifying a mobile money payment:
curl https://api.korapay.com/merchant/api/v1/charges/:reference
-H "Authorization: Bearer YOUR_KORAPAY_SECRET_KEY"
-X GET
Sample response for a successful transaction:
{
"status": true,
"message": "Charge retrieved successfully",
"data": {
"reference": "KPY-PAY-rYF4c5ZWioeb",
"status": "success",
"amount": "10.00",
"amount_paid": 0,
"fee": 0.29,
"currency": "GHS",
"description": "Payment for a emilokan",
"mobile_money": {
"number": "+254700000000"
},
"customer": {
"name": "John Doe",
"email": "[email protected]"
}
}
}
{
"status": true,
"message": "Charge retrieved successfully",
"data": {
"reference": "KPY-PAY-rYF4c5ZWioeb",
"status": "failed",
"amount": "2000.00",
"amount_paid": 0,
"fee": "180.00",
"currency": "GHS",
"description": "Mobile money payment for a book",
"payment_attempts": [
{
"reference": "KPY-CM-unEr27sJ616S",
"status": "failed",
"channel": "mobile_money",
"message": "The OTP you provided is invalid"
}
],
"mobile_money": {
"number": "+25470000000"
}
}
}
Step 4: Setup Webhook
You can set your application to receive a confirmation via webhooks when a mobile money payment is successful. Please visit Webhooks to see more information about the webhook request body and how to verify and handle the webhook request.
Error Responses
{
"status": false,
"message": "The OTP you provided is invalid",
"data": null
}
{
"status": false,
"message": "Payment has already been completed"
"data": {}
}
Updated 3 months ago