# A Douala marketplace, from MTN MoMo to the seller's bank

> Following one marketplace order in Cameroon from buyer prompt to escrow, delivery, seller payment and bank settlement, with real XAF amounts and API calls.

Published 2026-10-16 by the Ultraner team. Topic: build. Tags: cameroon, marketplaces, escrow, xaf.
Canonical: https://ultraner.com/blog/marketplace-payment-flow-in-cameroon

At 14:10 on a Tuesday, a buyer in Bonamoussadi orders a refurbished laptop from a seller in Akwa. Price: 185,000 FCFA. Delivery by moto the next morning. Neither has met the other.

That last fact is the whole problem a marketplace in Cameroon is solving. The buyer will not pay a stranger in advance. The seller will not hand a laptop to a stranger on a promise. Your marketplace exists to stand in the middle and make both of them comfortable, and the payment flow is how you do it.

Here is that one order, followed all the way through, with the decisions you have to make at each step. The amounts are illustrative. The rails and API calls are real.

## 14:10. The buyer chooses how to pay

Cameroon's checkout in Ultraner shows three mobile money brands: **MTN MoMo**, **Orange Money** and **Express Union**. MTN and Orange are the two large consumer wallets. Which networks are switched on for your account at a given moment comes from `GET /v5/providers`, so build your picker from that call rather than from a hard-coded list. MTN MoMo is the one you can design around today. Details on each are on [MTN MoMo](/mobile-networks/mtn-momo) and [Orange Money](/mobile-networks/orange-money).

The buyer enters `6 77 12 34 56`. Your code normalises it to `237677123456`: digits only, `237` plus nine digits.

The currency is XAF, the Central African CFA franc issued by the BEAC [1], and it has no minor unit. So the amount is `185000`, not `18500000`. If your marketplace started life with euro prices and a times-100 conversion, fix it before launch. We have written a separate piece on [why CFA francs break that habit](/blog/xof-and-xaf-have-no-cents).

## 14:11. The prompt

Your server sends the charge:

```
POST /v5/payments/express/mno
{ "msisdn": "237677123456", "amount": 185000, "currency": "XAF",
  "country": "CM", "provider": "MTN" }
```

The response is `pending`. The buyer's phone shows a MoMo prompt. Your page says, in French, "Validez le paiement de 185 000 FCFA sur votre téléphone", and shows the number the prompt was sent to.

The buyer approves. A few seconds later your webhook receives `payment.success` with the `transaction_id`. Your order moves to "paid, awaiting delivery". Not before.

If the buyer had walked away, the charge would close as failed after 10 minutes with `payment.failed`. Your order would stay unpaid, and the seller would never be told to ship.

## 14:12. The money waits

This is the decision that defines your marketplace. You have three choices:

1. **Release to the seller immediately.** Simple, and it leaves the buyer with no protection at all. Do this only for sellers you have vetted heavily.
2. **Hold in your own balance and release on a timer.** Common, and it puts the burden on your own code and your support team to handle disputes.
3. **Hold in escrow, released when delivery is confirmed.** The payment itself is conditional.

For a 185,000 FCFA laptop between strangers, the third is the right answer. Ultraner's [escrow](/capabilities/escrow) holds the payment until the buyer releases it or raises a dispute:

```
POST /v1/escrow                         // { seller_phone, amount, condition }
POST /v1/escrow/{escrow_code}/release   // buyer confirms delivery
POST /v1/escrow/{escrow_code}/dispute   // buyer reports a problem
```

The `condition` is your plain-language promise: "Laptop delivered in working order, matches listing photos". Make it specific. When a dispute comes, the condition is what your support person reads first.

Tell the seller, in the same minute, that the money is secured and held. That message is what makes them willing to ship.

## 09:30 the next day. Delivery

The moto rider hands over the laptop. The buyer opens it, switches it on and has a short window to check it. Your app shows two buttons: "Everything is fine, release payment" and "There is a problem".

Make the release button easy and the dispute button honest. Some buyers will forget to press either, so set an automatic release after a reasonable period, say 48 hours, unless a dispute is open, and say so on the order page from the start. Sellers will not wait indefinitely for a buyer who has gone quiet.

## 09:34. Release, and the commission

The buyer taps release. Your marketplace takes its commission, say 8%, which is 14,800 FCFA, leaving 170,200 FCFA owed to the seller. Every one of those figures is a whole number, because XAF has no cents. If your commission maths ever produces a fraction of a franc, round it, and do it the same way every time.

The seller's dashboard now shows 170,200 FCFA available.

## Getting the money to the seller

Here is where Cameroon differs from Tanzania, and where honest marketplaces say so up front.

Wallet payouts, meaning pushing money into the seller's own MoMo or Orange Money wallet, are live in Tanzania today and are being brought up in the other markets one verified rail at a time. Cameroon is not live for wallet payouts yet. So right now, the 170,200 FCFA reaches the seller one of two ways:

- **Settlement and onward payment.** Your marketplace settles its accumulated XAF balance to its own bank account, which works in any country, then pays sellers from that account through your bank or a local partner. Most marketplaces run this as a weekly batch, every Friday, with a statement.
- **Split payouts with seller balances.** If you onboard sellers through Ultraner's [split payouts](/capabilities/split-payouts), each seller has their own balance and your cut is taken automatically. They still settle out to a bank account, but the ledger lives with the payment, not in your spreadsheet.

Tell sellers which one you run, how often, and on which day. A predictable Friday transfer builds more seller loyalty than an unpredictable faster one.

## When it goes wrong

Two failure paths deserve design time:

**The buyer disputes.** The escrow stays held. Your support team contacts both sides, looks at the condition you wrote, and decides. If the buyer is right, the money is refunded. If the seller is right, it is released. Write your dispute policy before you launch, publish it, and stick to it.

**The refund.** On the rail serving Cameroon, mobile money refunds go back to whoever paid, addressed by the Ultraner `transaction_id`, so there is no phone number to mistype. Check what is still refundable first with `GET /v5/refunds/refundable/{transactionId}`. A full refund still leaves you down by the original collection fee, which the rail does not return. Price that into your commission.

## Why this shape works in Cameroon

The GSMA's reports show Central Africa's mobile money market growing quickly from a smaller base than East Africa's [2], and the World Bank's Findex shows mobile money accounts doing much of the work of financial inclusion across the region [3]. That means more of your buyers will have a MoMo or Orange Money wallet than a card, and more of them will be buying online from strangers for the first time.

The marketplace that wins their trust is the one where the money visibly waits for the laptop. Start with the [Cameroon payments page](/payments/cameroon) for the current networks, then write your escrow condition and your release window before you write any code.

## Sources

[1] Banque des Etats de l'Afrique Centrale, BEAC. https://www.beac.int/
[2] State of the Industry Report on Mobile Money, GSMA. https://www.gsma.com/sotir/
[3] The Global Findex Database 2025, World Bank. https://www.worldbank.org/en/publication/globalfindex
