Why Mobile Money is unavoidable in Africa
Across Central and West Africa, card payments remain a minority. What dominates is Mobile Money: MTN MoMo, Orange Money, and their equivalents. For any app that needs to collect payments — an online store, a fintech, a collection app, a SaaS — integrating Mobile Money isn't optional, it's the condition for having customers who actually pay.
But between "add a pay button" and "run a reliable payment system in production" lies a huge gap. Here's what you really need to understand.
The two main players
- MTN Mobile Money (MoMo) exposes an API (MTN MoMo Open API) with two key products: Collection (receiving money) and Disbursement (sending money). Access goes through a developer account, an API key and an access token (OAuth).
- Orange Money offers its web payment API: your server initiates a payment request, the user confirms on Orange's side, and you're notified of the result.
In both cases the principle is the same: your backend talks to the operator, never your mobile app directly. Secrets (keys, tokens) must never live on the client.
How a Mobile Money payment works
The typical collection flow:
- The user enters their number and confirms the amount in your app.
- Your backend calls the operator's API to initiate the transaction (
requestToPayon MoMo, payment request on Orange). - The operator sends a USSD/push prompt to the user's phone; they enter their PIN to confirm.
- The transaction goes through a "pending" state, then "successful" or "failed".
- Your backend learns the result — either by polling the status, or via a webhook/callback sent by the operator.
The crucial point: step 3 is asynchronous and out of your control. The user might take 2 seconds, 2 minutes, or never confirm.
The real technical challenges (where it breaks)
1. Asynchronous confirmations
You don't get the result instantly. Two strategies:
- Polling: periodically query the transaction status. Simple, but costly and slow.
- Webhook: the operator calls your URL when the state changes. Cleaner, but you need a public, secured, idempotent URL (the same event can arrive several times).
In practice: a webhook plus a fallback poll for cases where the notification is lost.
2. Intermediate states and failures
A transaction isn't binary. You must explicitly handle: pending, successful, failed, timeout, insufficient balance, invalid number, user declined. Every case needs clear behaviour in your app — otherwise you ship a product that "works on luck".
3. Idempotency (avoiding double charges)
If a user clicks twice, or a request is replayed, you must never charge twice. The solution: an idempotency key (a unique transaction identifier generated server-side) and a check before every initiation.
4. Reconciliation
At the end of the day, what your database says must match exactly what the operator says. A reconciliation job that compares your transactions against the API avoids silent discrepancies — and nasty accounting surprises.
5. Security
- Secrets server-side only, never in the app.
- Validate webhook authenticity (signature / operator IP).
- Log every transaction for audit.
Production-ready integration checklist
- Backend initiates payments (never the client)
- Explicit handling of all states (pending, success, failed, timeout)
- Idempotent webhook + fallback polling
- Idempotency key to prevent duplicates
- Daily reconciliation job
- Webhook validation and server-side secrets
- Audit log for every transaction
- Sandbox testing before production
Where to start
A clean Mobile Money integration — one operator, end-to-end collection, error handling and webhooks — takes 2 to 3 weeks depending on your product's complexity. The longest part isn't the happy path: it's making the system reliable in the face of failures.
Got a project?
I integrate Mobile Money (MTN MoMo, Orange Money) into web and mobile apps, end to end, with error handling and reconciliation. If you're building a product that needs to collect payments in Africa, let's talk — the first call is free.