There are two ways to collect Mobile Money in Cameroon, and they are not equivalent. The first is available right now. The second needs a contract with the operator. Plenty of merchants lose weeks waiting for the second when they could already have been selling with the first - and plenty of others stay stuck on the first without measuring what it costs them in manual work.
The merchant code, concretely
MTN and Orange hand out a merchant code long before they open access to their API. The customer dials a USSD code on their phone - *126# for MTN, #150# for Orange - picks merchant payment, enters your code, the amount, then their PIN. They receive a confirmation SMS containing a transaction identifier.
It is simple, it works everywhere, and it requires no technical integration at all. A merchant who has a code can collect the same day.
Its limit, and it is structural
The operator notifies you of nothing. No incoming call to your server, no status to query, no automatic way of knowing a payment has just landed. A merchant code is a one-way pipe: the money passes, the information does not.
This is not an integration gap you could work around with a bit of code. It is the nature of the product. At WalleoPay, the merchant-code payment driver owns that limit instead of hiding it: it puts the payment in "awaiting confirmation", shows the customer the USSD instructions, and stops there. Asked for a status, it answers "still pending" every time, because it has no source of truth to consult.
Three practical consequences:
- No automatic confirmation. The customer types in the identifier they received by SMS, and someone has to approve it by reconciling against the Mobile Money statement of the merchant account.
- A manual reconciliation, every day. The more you sell, the bigger that chore gets. At a few transactions a day it is trivial; at several dozen, it is somebody's job.
- No automated payouts. Getting the money out is done by hand from the MoMo app.
There is a fourth consequence, less visible: screenshot fraud. When the proof of payment is an SMS or a screenshot, it can be manufactured. A transaction identifier is worth nothing until it is matched against the real statement.
What the API changes
With an operator contract, the mechanism reverses. Your server requests the payment, the operator pushes a prompt to the customer's phone, the customer enters their PIN, and the outcome comes back to you.
At MTN the sequence is clear: the collection request returns a 202 with no body, along with a reference you generated yourself and passed in the X-Reference-Id header. That reference is what lets you query the status of the operation afterwards, as many times as needed, until it has succeeded or failed. In parallel, the operator calls back the callback address supplied with the request.
What you gain:
- A queryable source of truth. You can always ask again "where is this payment?" and get an answer the operator stands behind.
- Confirmation in seconds. Your site can deliver on its own, with no human in the loop.
- A usable failure reason. Insufficient balance, limit exceeded, PIN not entered in time: you know what to tell the customer instead of a generic "it did not work".
- Programmable payouts. The disbursement product lets you send money to a number without going through the app.
Two traps are worth knowing before you sign. MTN's sandbox only accepts the euro as a currency, whatever the real currency of the transaction - production works in CFA francs. And the production endpoint is specific to each account, assigned when the service goes live: it is not the sandbox host with one word changed.
Reconciling a merchant-code payment, in practice
When you collect on a merchant code, the transaction identifier from the customer's SMS is your only handle. Use it properly: ask for the identifier rather than a screenshot, look it up in the Mobile Money statement of the merchant account, and match on that identifier - never on amount and time alone. Two customers paying 15,000 francs three minutes apart is not a rare event, it is a Saturday afternoon.
Two habits save a lot of trouble later. Write the identifier next to the order, so that a dispute six weeks old can still be settled. And give yourself a fixed moment in the day for reconciliation rather than doing it between two customers: a reconciliation done under pressure is where wrong approvals come from.
How to choose
Take the merchant code if you sell by talking to your customers - messaging, phone, counter - if your volumes fit inside a daily reconciliation of a few minutes, or if you simply want to start collecting while an operator file moves along.
Move to the API if you deliver digital goods that must go out immediately, if your volume makes manual reconciliation unbearable, if several people need to see the same payment state, or if your site has to decide on its own to ship an order.
The deciding criterion is not technical, it is operational: who confirms, and how fast? If the answer can stay "me, some time today", the merchant code holds. If it has to be "the system, in ten seconds", you need the API.
You will not have to rewrite everything
This is what makes the decision lighter than it looks. Both modes live behind the same interface: the drivers - merchant code, MTN, Orange, sandbox - expose the same operations. The choice is made in configuration, operator by operator and mode by mode.
Put differently: if you integrate today with the merchant code, your code already creates a payment, follows a status and receives a notification when that status changes. The day the operator contract is signed, the routing is switched. Your application does not move.
Only one thing has to be designed in from the start: the "awaiting confirmation" status exists. If your shop only knows "paid" or "failed", it will be unusable on a merchant code and fragile on the API - because that intermediate status also shows up whenever a customer is slow to enter their PIN.
What we recommend
Start with the merchant code, but integrate as if you were already on the API: create your payments through the code, listen to notifications, never deliver without re-reading the status. You collect from tomorrow, and the day you switch costs you one configuration change.