Francophone Mobile Money
Learn about Mobile Money support in Francs.
Getting Started
We recommend checking out the introductory section to understand the basics of direct charge first. This guide assumes you’ve read that.
If you're collecting money in francs (XAF or XOF), your customers can pay with mobile money services.
The Process
This involves the following steps:
- You call our API to create a charge and pass in the customer's mobile number.
- Your customer completes the payment by authorizing it with their mobile money provider.
Initiating the Payment
To create a mobile money charge for a customer in a Francophone country, you'll need the customer’s valid phone_number along with the following required parameters:
amountcurrencyemailcountrynetworktx_ref(Unique transaction reference)
You can also specify additional details, such as the customer's fullname, redirect_url, and custom meta information. For more information on each parameter and its definition, refer to the endpoint documentation.
Country Codes
Only ISO 3166 Alpha-2 codes are supported as the country param. You can get a full list here. Possible values are
CM(Cameroon),SN(Senegal),BF(Burkina Faso) andCI(Côte d'Ivoire).
// Install with: npm i flutterwave-node-v3
const Flutterwave = require('flutterwave-node-v3');
const flw = new Flutterwave(
process.env.FLW_PUBLIC_KEY,
process.env.FLW_SECRET_KEY
);
const payload = {
phone_number: '24709929220',
amount: 1500,
currency: 'XAF',
country: 'CM',
email: '[email protected]',
tx_ref: this.generateTransactionReference(),
};
flw.MobileMoney.franco_phone(payload).then(console.log).catch(console.log);
// Install with: composer require flutterwavedev/flutterwave-v3
$flw = new \Flutterwave\Rave(getenv('FLW_SECRET_KEY'));
// Set `PUBLIC_KEY` as an environment variable
$mobileMoneyService = new \Flutterwave\MobileMoney();
$payload = [
"type" => "mobile_money_franco"
"phone_number" => '24709929220',
"amount" => 1500,
"currency" => 'XAF',
"country": 'CM',
"email" => '[email protected]',
"tx_ref" => $this->generateTransactionReference(),
];
$response = $mobileMoneyService->mobilemoney($payload);
print_r($response);
# Install with: gem install flutterwave_sdk
require 'flutterwave_sdk'
flw = Flutterwave.new(ENV["FLW_PUBLIC_KEY"], ENV["FLW_SECRET_KEY"], ENV["FLW_ENCRYPTION_KEY"])
charge = MobileMoney.new(flw)
payload = {
phone_number: '24709929220',
amount: 1500,
currency: 'XAF',
country: 'CM',
email: '[email protected]',
tx_ref: generate_transaction_reference,
}
response = charge.initiate_charge payload
print response
curl --request POST \
--url https://api.flutterwave.com/v3/charges?type=mobile_money_franco \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--header 'content-type: application/json' \
--data '{
"phone_number": "24709929220",
"amount": 1500,
"currency": "XAF",
"country": "CM",
"email": "[email protected]",
"tx_ref": "BJUYU399fcd43"
}'
Supported Networks
Flutterwave helps you charge customers across various networks. You need to specify the network in your request when initiating the mobile money charge. Here is a list of supported networks across our markets:
| Country | Country code | Currency | Supported Networks |
|---|---|---|---|
| Burkina Faso | BF | XOF | ORANGEMONEY, MOBICASH |
| Cameroon | CM | XAF | MTN, ORANGEMONEY |
| Côte D'Ivoire | CI | XOF | MTN, ORANGEMONEY, MOOV, WAVE |
| Senegal | SN | XOF | ORANGEMONEY, WAVE |
Making an Orange Money Payment
This only applies to Orange money transactions in Senegal.
Unlike other providers in the francophone region, Orange transactions use a unique QR flow to complete their transactions. Orange supports the following methods for completing a payment:
- Push notification (current flow)
- QR to redirect (new flow)
Push Notifications
After the transaction is initiated with the current auth flow, the customer receives a notification to complete the payment on their mobile devices. This flow would no longer be supported from December 5, 2025.
QR to App
This flow redirects the customer to their payment app to complete the payment. Your system generates a QR code that the customer scans to open their app.
Depending on the customer's device, there are two major ways to handle this flow:
- For Web devices (laptops and PCs): Set the
use_qrflag totruein your request. The response includes a base64 encoded QR image. Render this image in your web application so the customer can scan it with their phone.
curl --location 'https://api.flutterwave.com/v3/charges?type=mobile_money_franco' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--data-raw '{
"amount": 100,
"currency": "XOF",
"country": "SN",
"phone_number": "24709929220",
"email": "[email protected]",
"tx_ref": "20a568b8-401c-4ab6-ad57-81ea1e32897e",
"fullname": "George Considine",
"client_ip": "121.67.138.135",
"use_qr": true
}'
You'll get a response similar to this:
{
"status": "success",
"message": "Charge initiated",
"data": {
"id": 9823071,
"tx_ref": "08d39164-0c64-494d-9435-026204ed66cf",
"flw_ref": "FLWTK43726MCK1764174804541",
"device_fingerprint": "N/A",
"amount": 100,
"charged_amount": 100,
"app_fee": 2,
"merchant_fee": 0,
"processor_response": "Transaction in progress",
"auth_model": "AUTH",
"currency": "XOF",
"ip": "173.222.20.225",
"narration": "Corvus DevOps",
"status": "pending",
"payment_type": "mobilemoneysn",
"fraud_status": "ok",
"charge_type": "normal",
"created_at": "2025-11-26T16:33:24.000Z",
"account_id": 122055,
"customer": {
"id": 3412401,
"phone_number": "24709929220",
"name": "Corvus DevOps",
"email": "[email protected]",
"created_at": "2025-11-26T16:33:01.000Z"
},
"qr_code": "data:image/png;base64,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"
},
"meta": {
"authorization": {
"mode": "redirect",
"redirect_url": "https://ravesandboxapi.flutterwave.com/flwv3-pug/getpaidx/api/completemobilemoneysn?transactionreference=URF_1764174804129_4920135"
}
}
}
- For mobile devices such as smartphones and tablets, generating a QR code is not practical. The customer cannot scan a code that is displayed on the same device they are using. Set the
use_qrflag tofalsein your request. The response includes a redirect URL that opens the customer’s payment app directly on their device.
curl --location 'https://api.flutterwave.com/v3/charges?type=mobile_money_franco' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_SECRET_KEY' \
--data-raw '{
"amount": 100,
"currency": "XOF",
"country": "SN",
"phone_number": "24709929220",
"email": "[email protected]",
"tx_ref": "2de18794-8ab5-4bba-b8af-6565976ac1ee",
"fullname": "Darnell Sipes",
"client_ip": "238.195.163.178",
"use_qr": false
}'
You'll get a response similar to this:
{
"status": "success",
"message": "Charge initiated",
"data": {
"id": 9823075,
"tx_ref": "2d87c9a6-f008-4442-9047-ccb97242c01c",
"flw_ref": "FLWTK43726MCK1764174939569",
"device_fingerprint": "N/A",
"amount": 100,
"charged_amount": 100,
"app_fee": 2,
"merchant_fee": 0,
"processor_response": "Transaction in progress",
"auth_model": "AUTH",
"currency": "XOF",
"ip": "175.95.22.191",
"narration": "Corvus DevOps",
"status": "pending",
"payment_type": "mobilemoneysn",
"fraud_status": "ok",
"charge_type": "normal",
"created_at": "2025-11-26T16:35:39.000Z",
"account_id": 122055,
"customer": {
"id": 3412401,
"phone_number": "24709929220",
"name": "Corvus DevOps",
"email": "[email protected]",
"created_at": "2025-11-26T16:33:01.000Z"
},
"qr_code": null
},
"meta": {
"authorization": {
"mode": "redirect",
"redirect_url": "https://ravesandboxapi.flutterwave.com/flwv3-pug/getpaidx/api/completemobilemoneysn?transactionreference=URF_1764174939204_806235"
}
}
}
For Orange payments in Burkina Faso, include an
authorization_codeto successfully initiate a transaction. The customer provides this code by dialing*144*4*6*the_amount*secret_code#on their mobile device.
Handling the Response
After making the request, below are the expected responses:
{
"status":"success",
"message":"Charge initiated",
"data":{
"id":2079825,
"tx_ref":"MC-15852113s09v5050e8",
"flw_ref":"YVOO069611620649860887",
"device_fingerprint":"N/A",
"amount":1500,
"charged_amount":1500,
"app_fee":481.5,
"merchant_fee":0,
"processor_response":"Transaction in progress",
"auth_model":"AUTH",
"currency":"XAF",
"ip":"::ffff:10.63.255.131",
"narration":"MerchantName",
"status":"pending",
"payment_type":"mobilemoneysn",
"fraud_status":"ok",
"charge_type":"normal",
"created_at":"2021-05-10T12:30:57.000Z",
"account_id":732559,
"customer":{
"id":843193,
"phone_number":"237******20",
"name":"Anonymous customer",
"email":"[email protected]",
"created_at":"2021-05-10T12:30:56.000Z"
}
},
"meta":{
"authorization":{
"mode":"callback",
"redirect_url":null
}
}
}
{
"status":"success",
"message":"Charge initiated",
"data":{
"id":1413020339,
"tx_ref":"BJUYU399fcd43-00677001",
"flw_ref":"YMJW562781716997167",
"device_fingerprint":"N/A",
"amount":100,
"charged_amount":102.5,
"app_fee":4.5,
"merchant_fee":0,
"processor_response":"Transaction in progress",
"auth_model":"AUTH",
"currency":"XOF",
"ip":"52.18.161.235",
"narration":"Testing charge",
"status":"pending",
"payment_type":"mobilemoneysn",
"fraud_status":"ok",
"charge_type":"normal",
"created_at":"2024-05-29T15:39:27.000Z",
"account_id":1834035,
"customer":{
"id":887634078,
"phone_number":"2250747837699",
"name":"John Doe",
"email":"[email protected]",
"created_at":"2024-05-29T14:21:43.000Z"
}
},
"meta":{
"authorization":{
"mode":"redirect",
"redirect_url":"https://flutter-orange-ci.myflutterwave.com/flw-orangeci/api/v2/page/YMJW562781716997167"
}
}
}
The meta.authorization.mode field indicates the type of authorization required to complete the transaction. It can be one of the following:
callbackorredirecturl
See the next section on how to complete the charge in both scenarios.
Completing the Payment
Callback
To complete the payment, the customer needs to be authorized with their mobile money provider (for instance, via a push notification from the app).
Testing Tip
In Test Mode, Francophone mobile money transactions are automatically completed after a few seconds.
Redirecturl
Native mobile apps: don't open the Wave Payment link in an embedded WebView
If your Android or iOS app opens redirect_url inside a
WebView/WKWebView, the Wave app never launches and the payment silently stalls with no error. This applies only to native apps embedding a web view — browser-based checkouts are unaffected. See Opening the Wave link from a native app.
The customer should be redirected to the provided URL in the meta.authorization.redirect_url field to complete the payment.
Opening the Wave Payment link
This section applies if you've built a native Android or iOS app and open the payment URL inside it. If your customers pay through a mobile browser, the operating system handles the deep link for you, and nothing here applies.
The URL in meta.authorization.redirect_url deep-links into the Wave app. An embedded web view renders web content but doesn't forward.wave:// or intent://URLs to the OS package manager, so the link resolves to nothing. The customer sees a blank or stuck page, and your app receives no error to handle.
Recommended: open it in a system browser. Android Custom Tabs and iOS SFSafariViewController both perform App Link verification and forward custom schemes to the OS, so the Wave app opens as expected. You keep an in-app feel without owning the navigation logic.
// Android — Custom Tabs
CustomTabsIntent.Builder()
.build()
.launchUrl(context, Uri.parse(redirectUrl))
// iOS — SFSafariViewController
let safari = SFSafariViewController(url: URL(string: redirectUrl)!)
present(safari, animated: true)
If you must use an embedded WebView, intercept navigation yourself and pass any non-HTTP scheme to the OS.
// Android — WebViewClient
override fun shouldOverrideUrlLoading(
view: WebView, request: WebResourceRequest
): Boolean {
val url = request.url.toString()
if (url.startsWith("http")) return false // let the WebView load it
return try {
val intent = if (url.startsWith("intent://")) {
Intent.parseUri(url, Intent.URI_INTENT_SCHEME)
} else {
Intent(Intent.ACTION_VIEW, request.url) // wave://
}
context.startActivity(intent)
true
} catch (e: ActivityNotFoundException) {
// Wave app not installed — send the customer to the store
true
}
}
// iOS — WKNavigationDelegate
func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
guard let url = navigationAction.request.url else {
decisionHandler(.allow); return
}
if url.scheme != "http" && url.scheme != "https" {
UIApplication.shared.open(url)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
Completing an Orange Money Payment
This only applies to Orange money transactions in Senegal.
Follow the steps below to confirm the transaction:
- After the payment is initiated, the API returns a payment confirmation URL.
- Redirect the customer to this URL.
- The customer waits on the confirmation page while the transaction is processed.
- The final transaction status is displayed once processing is complete.
When the payment is completed, we'll send you a webhook notification. Here's what the response would look like:
{
"event": "charge.completed",
"data": {
"id": 2073992,
"tx_ref": "MC-15852113s09v5050e8",
"flw_ref": "YVOO069611620649860887",
"device_fingerprint": "N/A",
"amount": 1500,
"currency": "XAF",
"charged_amount": 1500,
"app_fee": 481.5,
"merchant_fee": 0,
"processor_response": "Approved",
"auth_model": "MOBILEMONEY",
"ip": "::ffff:10.30.86.54",
"narration": "MerchantName",
"status": "successful",
"payment_type": "mobilemoneysn",
"created_at":"2021-05-07T09:48:13.000Z",
"account_id": 732559,
"meta": null,
"customer":{
"id": 841600,
"name": "Anonymous Customer",
"phone_number": "237******20",
"email": "[email protected]",
"created_at":"2021-05-07T09:48:13.000Z"
}
}
// iOS — WKNavigationDelegate
func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
guard let url = navigationAction.request.url else {
decisionHandler(.allow); return
}
if url.scheme != "http" && url.scheme != "https" {
UIApplication.shared.open(url)
decisionHandler(.cancel)
return
}
decisionHandler(.allow)
}
In your webhook handler, you can then verify the payment and credit your customers with whatever they paid for. See our guide to transaction verification for details.
Updated 8 days ago
