Mobile Money Integration

Integrate mobile money payments with PayOS

Mobile Money Integration Guide

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/api/v1/auth/oauth2/token \
> -H "Content-Type: application/json" \
> -d '{
> "merchantId": "123e4567-e89b-12d3-a456-426614174000",
> "clientSecret": "your_client_secret_here"
> }'

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/api/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": {
> "fullName": "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/api/v1/transaction/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}

4. Transaction Polling

To check the status of a transaction, use the polling endpoint:

$curl -X GET "https://api.payos.money/api/v1/transaction/poll?transactionId=<transactionId>" \
> -H "Authorization: Bearer <access_token>"

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
insufficientFundsInsufficient funds in customer account
invalidAccountInvalid mobile money account
customerRejectedCustomer rejected the transaction
dailyLimitExceededDaily transaction limit exceeded
monthlyLimitExceededMonthly transaction limit exceeded
accountNotActiveMobile money account is not active
systemErrorA system error occurred
networkErrorNetwork or connectivity issue
transactionNotFoundTransaction could not be found
invalidPinThe 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
  • Poll transaction status regularly until a final state is reached

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