---
agentTools:
  projectIndex: https://developer.flutterwave.com/llms.txt
---

# Francophone Mobile Money

Learn about Mobile Money support in Francs.

> 📘 Getting Started
>
> We recommend checking out the [introductory section](/v3.0.0/docs/introduction-4)  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:

1. You call our API to create a charge and pass in the customer's mobile number.
2. Your customer completes the payment by authorizing it with their mobile money provider.

[block:image]
{
  "images": [
    {
      "image": [
        "https://files.readme.io/b43be1d89e7ce083d901bcd4e390b0b0bb9f0dfb4855b20ee70ac065a273fdd1-xaf_momo.png",
        "",
        ""
      ],
      "align": "center"
    }
  ]
}
[/block]

<br />

## 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:

* `amount`
* `currency`
* `email`
* `country`
* `network`
* `tx_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](/v3.0.0/reference/charge-via-francophone-mobile-money).

> 📘 Country Codes
>
> Only ISO 3166 Alpha-2 codes are supported as the country param. You can get a [full list here](https://www.iban.com/country-codes). Possible values are `CM` (Cameroon), `SN` (Senegal), `BF` (Burkina Faso) and `CI` (Côte d'Ivoire).

```javascript Node.js
// 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: 'JoeBloggs@acme.co',
	tx_ref: this.generateTransactionReference(),
};
flw.MobileMoney.franco_phone(payload).then(console.log).catch(console.log);
```
```php
// 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" => 'JoeBloggs@acme.co',
    "tx_ref" => $this->generateTransactionReference(),
];
$response = $mobileMoneyService->mobilemoney($payload);
print_r($response);
```
```ruby
# 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: 'JoeBloggs@acme.co',
    tx_ref: generate_transaction_reference,
}
response = charge.initiate_charge payload
print response
```
```shell cURL
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": "JoeBloggs@acme.co",
     "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`               |

<br />

### 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:

1. Push notification (current flow)
2. 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**.

<br />

#### 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_qr` flag to `true` in 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 cURL
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": "Rachel.DAmore80@gmail.com",
    "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:

```json 200 Ok
{
    "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": "ravesb_5d01e093d62217e4a03e_cornelius@flutterwavego.com",
            "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"
        }
    }
}
```

<br />

* **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_qr` flag to `false` in your request. The response includes a redirect URL that opens the customer’s payment app directly on their device.

```curl Example
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": "Keira93@gmail.com",
    "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:

```json 200 Ok
{
    "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": "ravesb_5d01e093d62217e4a03e_cornelius@flutterwavego.com",
            "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_code`  to 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:

```json Success (Callback)
{
   "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":"user@flw.com",
         "created_at":"2021-05-10T12:30:56.000Z"
      }
   },
   "meta":{
      "authorization":{
         "mode":"callback",
         "redirect_url":null
      }
   }
}
```
```json Success (Redirect)
{
   "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":"john.doe@gmail.com",
         "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:

* `callback` or
* `redirecturl`

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](/v3.0.0/docs/testing#mobile-money), 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.

```kotlin Kotlin
// Android — Custom Tabs
CustomTabsIntent.Builder()
    .build()
    .launchUrl(context, Uri.parse(redirectUrl))
```
```swift
// 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.

```kotlin
// 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
    }
}
```
```swift
// 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)
}
```

<br />

### Completing an Orange Money Payment

> 🚧
>
> This only applies to Orange money transactions in **Senegal**.

Follow the steps below to confirm the transaction:

1. After the payment is initiated, the API returns a payment confirmation URL.
2. Redirect the customer to this URL.
3. The customer waits on the confirmation page while the transaction is processed.
4. 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:

```json
{
  "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": "user@flw.com",
      "created_at":"2021-05-07T09:48:13.000Z"
    }
  }
```
```swift
// 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](/v3.0.0/docs/transaction-verification-1) for details.