M-PESA

Learn about Mobile Money support in Kenya.

📘

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 KES, your customers can pay with M-PESA.

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 from their M-PESA app.

Initiating the Payment

First, you'll need a phone_number, the customer's M-PESA mobile number.

Combine that with the rest of the payment details to create the payload and send it to our charge M-PESA endpoint. You'll need to specify amount, currency, email and a unique tx_ref.

You can also specify more details, such as the customer's fullname, phone_number, and custom meta information. See the endpoint documentation for details.

// 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: '25454709929220',
    amount: 1500,
    currency: 'KES',
    email: '[email protected]',
    tx_ref: this.generateTransactionReference(),
}
flw.MobileMoney.mpesa(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
$mpesaService = new \Flutterwave\Mpesa();
$payload = [
    "phone_number" => '25454709929220',
    "amount" => 1500,
    "currency" => 'KES',
    "email" => '[email protected]',
    "tx_ref" => $this->generateTransactionReference(),
];
$response = $mpesaService->mpesa($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: '25454709929220',
    amount: 1500,
    currency: 'KES',
    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=mpesa \
   --header 'Authorization: Bearer YOUR_SECRET_KEY' \
   --header 'content-type: application/json' \
   --data '{
     "phone_number": "25454709929220",
     "amount": 1500,
     "currency": "KES",
     "email": "[email protected]",
     "tx_ref": "BJUYU399fcd43"
}'

Handling the Response

You'll get a response that looks like this:

{
  "status": "success",
  "message": "Charge initiated",
  "data": {
    "id": 1191376,
    "tx_ref": "MC-15852113s09v5050e8",
    "flw_ref": "0379962762",
    "device_fingerprint": "62wd23423rq324323qew1",
    "amount": 1500,
    "charged_amount": 1500,
    "app_fee": 9,
    "merchant_fee": 0,
    "processor_response": "Successful",
    "auth_model": "LIPA_MPESA",
    "currency": "KES",
    "ip": "::ffff:10.45.236.21",
    "narration": "FLW-PBF MPESA Transaction ",
    "status": "pending",
    "auth_url": "N/A",
    "payment_type": "mpesa",
    "fraud_status": "ok",
    "charge_type": "normal",
    "created_at": "2020-03-27T15:46:37.000Z",
    "account_id": 74843,
    "customer": {
      "id": 349271,
      "phone_number": "25454709929220",
      "name": "Anonymous Customer",
      "email": "[email protected]",
      "created_at": "2020-03-27T15:46:13.000Z"
    }
  }
}

You'll notice that the data.status is "pending", meaning the transaction is yet to be completed. The data.auth_model is "LIPA_MPESA", which means the customer will authorize this via their M-PESA app. Typically, they will get a push notification from the app and complete the payment by entering their PIN.

Completing the Payment

To complete the payment, the customer will authorize it via their M-PESA app.

🧪

Testing Tip

In Test Mode, M-PESA payments will automatically be authorized after a few seconds.

When the payment is completed, we'll send you a webhook notification. Here's what the payload looks like:

{
  "event": "charge.completed",
  "data": {
    "id": 1191376,
    "tx_ref": "MC-15852113s09v5050e8",
    "flw_ref": "0379962762",
    "device_fingerprint": "N/A",
    "amount": 1500,
    "currency": "KES",
    "charged_amount": 1500,
    "app_fee": 43.5,
    "merchant_fee": 0,
    "processor_response": "Successful",
    "auth_model": "LIPA_MPESA",
    "ip": "::ffff:10.45.226.51",
    "narration": "FLW-PBF MPESA Transaction ",
    "status": "successful",
    "payment_type": "mpesa",
    "created_at": "2020-03-27T15:46:37.000Z",
    "account_id": 74843,
    "meta": null,
    "customer": {
      "id": 349271,
      "phone_number": "25454709929220",
      "name": "Anonymous Customer",
      "email": "[email protected]",
      "created_at": "2020-03-27T15:46:13.000Z"
    }
  }
}

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.