> ## Documentation Index
> Fetch the complete documentation index at: https://flutterwaveinc.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# USSD Charge

> Learn how to collect payment with USSD.

<Info>
  We recommend checking out the [introductory
  section](/payment-api/introduction) to understand the basics of direct
  charge first. This guide assumes you've read that.
</Info>

Direct USSD charge allows you to collect payments via USSD. With a USSD charge, you call our API to initiate the payment, and your customer completes it by dialing their bank's USSD code on their mobile phone. Once the payment is completed, we’ll notify you via a webhook.

<img src="https://mintcdn.com/flutterwaveinc/8LJ4mpYLmd_SNb9Z/images/ussd.png?fit=max&auto=format&n=8LJ4mpYLmd_SNb9Z&q=85&s=c25ccf1731ed8bb850560cc5d08e966b" alt="ussd" width="5760" height="10788" data-path="images/ussd.png" />

### Initiating the Payment

First, you'll need the customer's payment details. Since it's a USSD transaction, the only detail you need is the `account_bank`, the code matching the customer's bank. You can provide a simple UI for the user to select their bank.

<Note>
  ### Supported Banks

  USSD payments are currently only supported for the following banks:

  | Banks                           | bank code |
  | ------------------------------- | --------- |
  | Access bank                     | (044)     |
  | Ecobank                         | (050)     |
  | Fidelity bank                   | (070)     |
  | First bank of Nigeria           | (011)     |
  | First City Monument Bank (FCMB) | (214)     |
  | Guaranty trust bank             | (058)     |
  | Heritage bank                   | (030)     |
  | Keystone bank                   | (082)     |
  | Lotus bank                      | (303)     |
  | Premium Trust bank              | (105)     |
  | Stanbic IBTC bank               | (221)     |
  | Sterling bank                   | (232)     |
  | Union bank                      | (032)     |
  | United Bank for Africa (UBA)    | (033)     |
  | Unity Bank                      | (215)     |
  | VFD microfinance bank           | (090110)  |
  | Wema bank                       | (035)     |
  | Zenith bank                     | (057)     |
</Note>

Now, combine that with the rest of the payment details to create the payload and send to our [charge USSD endpoint](api-reference/charges#ussd). 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](api-reference/charges#ussd) for details.

<CodeGroup>
  ```javascript Node.js theme={null}
  // 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 = {
      account_bank: '058',
      amount: 7500,
      currency: 'NGN',
      email: 'chunkylover53@aol.com',
      tx_ref: this.generateTransactionReference(),
      fullname: 'Homer Simpson',
  };
  flw.Charge.ussd(payload)
      .then(console.log)
      .catch(console.log);
  ```

  ```php PHP theme={null}
  // Install with: composer require flutterwavedev/flutterwave-v3

  $flw = new \Flutterwave\Rave(getenv('FLW_SECRET_KEY'));
  // Set `PUBLIC_KEY` as an environment variable
  $ussdChargeService = new \Flutterwave\Ussd();
  $payload = [
      "account_bank" => '058',
      "amount" => 7500,
      "currency" => 'NGN',
      "email" => 'chunkylover53@aol.com',
      "tx_ref" => $this->generateTransactionReference(),
      "fullname" => 'Homer Simpson',
  ];
  $response = $ussdChargeService->ussd($payload);
  print_r($response);
  ```

  ```ruby Ruby theme={null}
  # 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_ussd = USSD.new(flw)
  payload = {
      account_bank: '058',
      amount: 7500,
      currency: 'NGN',
      email: 'chunkylover53@aol.com',
      fullname: 'Homer Simpson',
      tx_ref: generate_transaction_reference,
  }
  response = charge_ussd.initiate_charge payload
  print response
  ```

  ```json cURL theme={null}
  curl --request POST \
     --url https://api.flutterwave.com/v3/charges?type=ussd \
     --header 'Authorization: Bearer YOUR_SECRET_KEY' \
     --header 'content-type: application/json' \
     --data '{
       "account_bank": "058",
       "amount": 7500,
       "currency": "NGN",
       "email": "chunkylover53@aol.com",
       "fullname": "Homer Simpson",
       "tx_ref": "BJUYU399fcd43"
  }'
  ```
</CodeGroup>

## Handling the response

You'll get a response that looks like this:

```json Success theme={null}
{
    "status": "success",
    "message": "Charge initiated",
    "data": {
        "id": 276641033,
        "tx_ref": "BJUYU399fcd43",
        "flw_ref": "FLW693741590884271975",
        "device_fingerprint": "N/A",
        "amount": 7500,
        "charged_amount": 7500,
        "app_fee": 491.2,
        "merchant_fee": 0,
        "processor_response": "Transaction in progress",
        "auth_model": "USSD",
        "currency": "NGN",
        "ip": "N/A",
        "narration": "MerchantName",
+       "status": "pending",
        "payment_type": "ussd",
        "fraud_status": "ok",
        "charge_type": "normal",
        "created_at": "2020-05-31T00:17:51.000Z",
        "account_id": 17321,
        "customer": {
            "id": 210466255,
            "phone_number": null,
            "name": "Homer Simpson",
            "email": "chunkylover53@aol.com",
            "created_at": "2020-05-31T00:17:50.000Z"
        },
+       "payment_code": "9039"
    },
    "meta": {
        "authorization": {
            "mode": "ussd",
+           "note": "*889*767*9039#"
        }
    }
}
```

Let's break this down:

* `status` is `"successful"`, meaning that the charge was initiated successfully
* `data.status` is `"pending"`, meaning that the customer needs to authorize the transaction via USSD
* `data.payment_code` contains a code for this transaction. For GTBank USSD payments, the user will be prompted to enter this after dialing the USSD code.
* `meta.authorization` contains the important details to complete the payment. The `note` field holds the USSD code that the customer needs to dial from the mobile number linked to their bank account. Typically, it will be in the form `*<bank_code>*xxx*<payment_code>#`.

You should instruct your customer to dial the code in `meta.authorization.note` (and enter the `payment_code`) if necessary to complete the payment.

## Completing the Payment

To complete the payment, the customer needs to dial the USSD code and authorize the charge.

<Info>
  **Testing Tip**

  In [Test Mode](/authentication), USSD transactions will automatically be paid (transition to "successful") after a few seconds.
</Info>

We'll send you a webhook notification when the payment is completed. Here's what that looks like:

```json theme={null}
{
  "event": "charge.completed",
  "data": {
    "id": 2073992,
    "tx_ref": "BJUYU399fcd43",
    "flw_ref": "flwm3s4m0c1620380894041",
    "device_fingerprint": "N/A",
    "amount": 7500,
    "currency": "NGN",
    "charged_amount": 7500,
    "app_fee": 2000,
    "merchant_fee": 0,
    "processor_response": "Transaction Successful",
    "auth_model": "USSD",
    "ip": "::ffff:10.30.86.54",
    "narration": "MerchantName",
    "status": "successful",
    "payment_type": "ussd",
    "created_at": "2020-05-31T00:17:51.000Z",
    "account_id": 17321,
    "meta": null,
    "customer":{
      "id": 841600,
      "name": "Homer Simpson",
      "phone_number": "N/A",
      "email": "chunkylover53@aol.com",
      "created_at":"2021-05-07T09:48: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](/transaction-verification) for details.

<CodeGroup>
  ```javascript Node.js  theme={null}
  const transactionId = payload.data.id;
  await flw.Transaction.verify({ id: transactionId });
  ```

  ```php PHP  theme={null}
  $transactionId = $payload['data']['id'];
  $ussdChargeService->verifyTransaction($transactionId);
  ```

  ```ruby Ruby  theme={null}
  transaction_id = params[:data][:id]
  charge_ussd.verify_charge transaction_id
  ```
</CodeGroup>

You'll get a response that looks like this, and you can see that the `data.status` field is now `"successful"`.

```json Payment Successful theme={null}
{
  "status": "success",
  "message": "Transaction fetched successfully",
  "data": {
    "id": 276641033,
    "tx_ref": "BJUYU399fcd43",
    "flw_ref": "FLW693741590884271975",
    "device_fingerprint": "N/A",
    "amount": 7500,
    "charged_amount": 7500,
    "app_fee": 2000,
    "merchant_fee": 0,
    "processor_response": "Transaction Successful",
    "auth_model": "USSD",
    "currency": "NGN",
    "ip": "::ffff:10.30.86.54",
    "narration": "MerchantName",
    "status": "successful",
    "payment_type": "ussd",
    "created_at": "2020-05-31T00:17:51.000Z",
    "account_id": 17321,
    "customer":{
      "id": 841600,
      "name": "Homer Simpson",
      "phone_number": "N/A",
      "email": "chunkylover53@aol.com",
      "created_at":"2021-05-07T09:48:13.000Z"
    },
    "meta": null,
    "amount_settled": 5500
  }
}
```

All done.

## Putting it Together

Here's what a full implementation might look like:

<CodeGroup>
  ```javascript Node.js theme={null}
  // In an Express-like app:

  // The route where we initiate payment
  app.post('/pay', async (req, res) => {
      const payload = {
          account_bank: req.body.bank_code,
          amount: req.session.amount,
          currency: 'NGN',
          email: req.user.email,
          tx_ref: generateTransactionReference(),
          fullname: req.user.name,
      }
      const response = await flw.Charge.ussd(payload);
      if (response.status !== 'success') {
          // Something went wrong; bail
          res.redirect('back');
      }

      const ussdCode = response.meta.authorization.note;
      const paymentCode = response.payment_code;
      res.send(`
  To complete the payment, dial <strong>${ussdCode}</strong> from the mobile number linked to your bank account.
  If you're prompted for a payment code, enter <strong>${paymentCode}</strong>.
      `);
  });

  // Our webhook endpoint. See the guide on webhooks for a more thorough sample
  app.post("/flw-webhook", (req, res) => {
      // Check signature, log payload, etc
      // Schedule a job that checks for the status of the payment
      transactionVerificationQueue.add({id: req.body.data.id});
      res.status(200).end();
  });
  ```

  ```php PHP theme={null}
  // In a Laravel-like app:

  // The route where we initiate payment
  Route::post('/pay', function ($req) {
      $payload = [
          "account_bank" => $req->input('bank_code'),
          "amount" => session('amount'),
          "currency" => 'NGN',
          "email" => auth()->email,
          "tx_ref" => generateTransactionReference(),
          "fullname" => auth()->name,
      ];
      $response = $ussdChargeService->ussd($payload);
      if ($response['status'] !== 'success') {
          // Something went wrong; bail
          return redirect()->back();
      }

      $ussdCode = $response['meta']['authorization']['note'];
      $paymentCode = $response['payment_code'];
      return <<<HTML
  To complete the payment, dial <strong>$ussdCode</strong> from the mobile number linked to your bank account.
  If you're prompted for a payment code, enter <strong>$paymentCode</strong>.
  HTML;
  });


  // Our webhook endpoint. See the guide on webhooks for a more thorough sample
  Route::post('/flw-webhook', function ($req) {
      // Check signature, log payload, etc
      // Schedule a job that checks for the status of the payment
      dispatch(new CheckTransactionStatus($req->input('data')['id']));
      return response();
  });
  ```

  ```ruby Ruby theme={null}
  # In a Rails-like app:

  # Handles POST /pay
  # The route where we initiate payment
  def pay
      payload = {
          account_bank: params[:bank_code],
          amount: session[:amount],
          currency: 'NGN',
          email: current_user.email,
          fullname: current_user.name,
          tx_ref: generate_transaction_reference,
      }
      response = charge_ussd.initiate_charge payload
      if response['status'] != 'success'
          # Something went wrong; bail
          return redirect_back
      end

      ussd_code = response['meta']['authorization']['note']
      payment_code = response['payment_code']
      render html: <<~HTML
        To complete the payment, dial <strong>#{ussd_code}</strong> from the mobile number linked to your bank account.
        If you're prompted for a payment code, enter <strong>#{payment_code}</strong>.
      HTML
  end

  # Our webhook endpoint. See the guide on webhooks for a more thorough sample
  def flw_webhook
      # Check signature, log payload, etc
      # Schedule a job that checks for the status of the payment
      CheckTransactionStatus.perform_later params[:data][:id]
      head :ok
  end
  ```
</CodeGroup>
