Mobile Money Integration Guide

Integrate mobile money payments with PayOS

Overview

Mobile money integration with PayOS enables you to accept payments through various mobile money providers in Zambia. This guide details the complete integration process using PayOS’s API.

Prerequisites

Before integrating mobile money payments, ensure you have:

  • A PayOS account with mobile money enabled
  • OAuth2 client credentials (Client ID and Secret)
  • Webhook endpoint configured to receive transaction status updates

Integration Steps

1. Authentication (OAuth2 Client Credentials Flow)

First, obtain an access token using your OAuth2 credentials:

$curl -X POST https://api.payos.money/auth/oauth2/token \
> -H "Content-Type: application/x-www-form-urlencoded" \
> -H "Authorization: Basic <base64(clientId:clientSecret)>" \
> -d "grant_type=client_credentials"

The response will include your access token:

1{
2 "access_token": "eyJhbGciOiJIUzI1...",
3 "expires_in": 3600,
4 "token_type": "Bearer"
5}

2. Session Creation

Create a payment session using the obtained access token:

$curl -X POST https://api.payos.money/v1/checkout/session \
> -H "Authorization: Bearer <access_token>" \
> -H "Content-Type: application/json" \
> -d '{
> "amount": 100,
> "currency": "ZMW",
> "merchantReference": "REFERENCE123456789",
> "merchantId": "123e4567-e89b-12d3-a456-426614174000",
> "payerDetails": {
> "name": "John Doe",
> "emailAddress": "john@example.com",
> "location": "ZMB"
> },
> "integrationType": "direct"
>}'

The response will include:

1{
2 "success": true,
3 "sessionId": "sess_01H9X..."
4}

In case of failure:

1{
2 "success": false,
3 "errorMessage": "Invalid currency for location",
4 "errorCode": "INVALID_CURRENCY"
5}

Important:

  • The merchantReference must be unique for each transaction and contain only alphanumeric characters
  • You’ll handle the payment flow in your application using the sessionId

3. Transaction Initiation

Initiate the mobile money transaction using the session ID:

$curl -X POST https://api.payos.money/v1/transactions/initiate \
> -H "Authorization: Bearer <access_token>" \
> -H "Content-Type: application/json" \
> -d '{
> "sessionId": "{{sessionId}}",
> "paymentMethodId": "mobilemoney",
> "paymentDetails": {
> "type": "mobilemoney",
> "payerFullName": "John Doe",
> "payerMobileNumber": "0970000001",
> "provider": "airtel"
> }
>}'

Transaction Response

A successful initiation will return a response like this:

1{
2 "status": "PENDING",
3 "transactionId": "0193df59-a730-7aaf-8d35-f931c31e3d53",
4 "message": "Transaction pending"
5}

Transaction States

After initiation, the transaction will move through different states:

  1. PENDING: Transaction has been accepted and is being processed

    • At this point, you should display a loading page to the user
    • The customer will receive a prompt on their mobile phone to approve the payment
  2. SUCCESS: Transaction has been successfully completed

    • You will receive a webhook notification
    • The customer’s payment has been processed
  3. FAILED: Transaction has failed

    • You will receive a webhook notification with the failure reason
    • The customer should be prompted to try again

Transaction Response Examples

Successful Response

1{
2 "status": "SUCCESS",
3 "transactionId": "0193df59-a730-7aaf-8d35-f931c31e3d53",
4 "message": "Transaction successful"
5}

Pending Response

1{
2 "status": "PENDING",
3 "transactionId": "0193df59-a730-7aaf-8d35-f931c31e3d53",
4 "message": "Transaction pending"
5}

Failed Response

1{
2 "status": "FAILED",
3 "transactionId": "0193df40-7de8-744b-8bb9-ce9031e48e1f",
4 "message": "Transaction queried successfully",
5 "authState": {
6 "state": "failed",
7 "message": "Transaction not authorised within required time"
8 }
9}

Common Failure Scenarios

Here’s an example of a failure response:

1{
2 "status": "FAILED",
3 "transactionId": "0193df40-7de8-744b-8bb9-ce9031e48e1f",
4 "message": "Transaction queried successfully",
5 "authState": {
6 "state": "failed",
7 "message": "Transaction not authorised within required time",
8 "code": "TIMEOUT"
9 }
10}

The following table lists all possible failure codes and their descriptions:

Error CodeDescription
TIMEOUTTransaction not authorized within required time
INSUFFICIENT_FUNDSInsufficient funds in customer account
INVALID_ACCOUNTInvalid mobile money account
CUSTOMER_REJECTEDCustomer rejected the transaction
DAILY_LIMIT_EXCEEDEDDaily transaction limit exceeded
MONTHLY_LIMIT_EXCEEDEDMonthly transaction limit exceeded
ACCOUNT_NOT_ACTIVEMobile money account is not active
SYSTEM_ERRORA system error occurred
NETWORK_ERRORNetwork or connectivity issue
TRANSACTION_NOT_FOUNDTransaction could not be found
INVALID_PINThe Pin provided is invalid

Supported Providers

PayOS supports the following mobile money providers in Zambia:

ProviderDescription
Airtel MoneyAirtel Zambia’s mobile money service
MTN MoMoMTN Zambia’s mobile wallet platform
Zamtel MoneyZamtel’s mobile payment solution

PayOS supports the following mobile money providers in Ghana:

ProviderDescription
AirtelTigo (AT)AirtelTigo’s mobile money solution

Best Practices

Security

  • Store OAuth credentials securely
  • Use HTTPS for all API calls
  • Implement proper error handling
  • Validate all input data

Transaction Management

  • Implement proper logging
  • Monitor webhook notifications
  • Set up alerts for failed transactions
  • Handle timeout scenarios appropriately

Testing

  • Use test credentials in sandbox environment
  • Test with various amount ranges
  • Verify error scenarios
  • Test webhook integration thoroughly

Sandbox Testing Numbers

When testing in the sandbox environment, use the following phone numbers to simulate different transaction scenarios:

Test Phone NumberScenario
0970000005Insufficient funds
0970000006Customer rejected transaction
0970000007Transaction timeout
0970000008Account not active
0970000009Invalid account
0970000010Daily limit exceeded
0970000011Monthly limit exceeded
0970000012System error
0970000013Network error
0970000014Transaction not found

Any other valid phone number format will result in a successful transaction in the sandbox environment.

Note: These test numbers are for sandbox testing only and will not work in the production environment.

Rate Limiting

  • Standard rate limit: 100 requests per minute
  • Burst rate limit: 200 requests per minute for 5 minutes
  • Implement exponential backoff for retries

Support

For integration support:

  • Technical documentation: docs.payos.money
  • Email support: support@payos.money
  • Integration support hours: 24/7