DEV Community

Cover image for How to Collect Payments Using the Payment Orchestrator Flow in v4

How to Collect Payments Using the Payment Orchestrator Flow in v4

This guide walks you through the payment orchestrator flow and how to use it to process payments with cards, mobile money, and Unstructured Supplementary Service Data (USSD).

What is the Payment Orchestrator Flow?

The Payment Orchestrator flow lets you collect payments easily using multiple payment methods in a single charge. It features a robust endpoint where you can specify the payment method, the customer being charged, and any other required details in a single request.

This approach is useful when you need to process a one-time charge without storing customer payment details for future use. Some common use cases include:

  • E-commerce Checkout: An online store that lets customers buy items without creating an account.
  • Event Ticketing: A platform that sells tickets to multiple customers without saving payment details.
  • Non-Profit Donations: A charity accepting one-time donations.
  • Online Services: A fitness studio charging for drop-in classes on a per-session basis.

Collecting Payments with the Payment Orchestrator Flow

Before you start collecting payments with our APIs, you need to generate a token that lets you access the APIs for a specific period.

To do this, log into your dashboard to obtain your Client ID and Client Secret. These are needed to generate the token and refresh it once it expires.

curl -X POST 'https://idp.flutterwave.com/realms/flutterwave/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>' \
--data-urlencode 'grant_type=client_credentials'
Enter fullscreen mode Exit fullscreen mode

Check out the authentication process to learn more.

Once the token is generated, you can use it to create a charge, as shown below:

Initiate the Charge

To initiate a charge, select the appropriate option based on the customer's payment method.

For Card Payments, send a request to the charge with the orchestrator endpoint with the customer’s personal identifiable information (PII), amount, currency, and encrypted card details.

curl -X POST "https://developersandbox-api.flutterwave.com/orchestration/direct-charges" \
        -H "Content-Type: application/json" \
        -H "X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}" \
        -H "X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}" \
        -H "Authorization: Bearer {{YOUR_ACCESS_TOKEN}}" \
        -d '{
            "amount": 1234.56,
            "currency": "USD",
            "reference": "YOUR_EXAMPLE_REFERENCE",
            "payment_method": {
                "type": "card",
                "card": {
                    "nonce": "{{ENCRYPTED_NONCE}}",
                    "encrypted_expiry_month": "{{ENCRYPTED_EXPIRY_MONTH}}",
                    "encrypted_expiry_year": "{{ENCRYPTED_EXPIRY_YEAR}}",
                    "encrypted_card_number": "{{ENCRYPTED_CARD_NUMBER}}",
                    "encrypted_cvv": "{{ENCRYPTED_CVV}}"
                }
            },
            "redirect_url": "https://google.com",
            "customer": {
                "address": {
                    "country": "US",
                    "city": "Gotham",
                    "state": "Colorado",
                    "postal_code": "94105",
                    "line1": "221B Baker Street"
                },
                "phone": {
                    "country_code": "41",
                    "number": "7069423351"
                },
                "name": {
                    "first": "King",
                    "middle": "Leo",
                    "last": "James"
                },
                "email": "james@example.com"
            }
        }'
Enter fullscreen mode Exit fullscreen mode

A key parameter in the request body is payment_method. It tells the orchestrator what type of payment to process. In this case, the payment method is set to card along with the corresponding card details.

"payment_method": {
    "type": "card",
    "card": {
        "nonce": "{{ENCRYPTED_NONCE}}",
        "encrypted_expiry_month": "{{ENCRYPTED_EXPIRY_MONTH}}",
        "encrypted_expiry_year": "{{ENCRYPTED_EXPIRY_YEAR}}",
        "encrypted_card_number": "{{ENCRYPTED_CARD_NUMBER}}",
        "encrypted_cvv": "{{ENCRYPTED_CVV}}"
    }
},
Enter fullscreen mode Exit fullscreen mode

For Mobile Money, send a request to the same charge endpoint and set the payment method to mobile_money.

curl -X POST "https://developersandbox-api.flutterwave.com/orchestration/direct-charges" \
        -H "Content-Type: application/json" \
        -H "X-Trace-Id: {{UNIQUE_TRACE_ID}}" \
        -H "X-Idempotency-Key: {{UNIQUE_IDEMPOTENCY_KEY}}" \
        -H "Authorization: Bearer {{API_ACCESS_TOKEN}}" \
        -d '{
            "amount": 1234.56,
            "currency": "UGX",
            "reference": "YOUR_EXAMPLE_REFERENCE",
            "payment_method": {
                "type": "mobile_money",
                "mobile_money": {
                    "country_code": "233",
                    "network": "MTN",
                    "phone_number": "9012345678"
                }
            },
            "customer": {
                "address": {
                    "country": "US",
                    "city": "Gotham",
                    "state": "Colorado",
                    "postal_code": "94105",
                    "line1": "221B Baker Street"
                },
                "email": "james@example.com",
                "meta": {},
                "name": {
                    "first": "King",
                    "middle": "Leo",
                    "last": "James"
                },
                "phone": {
                    "country_code": "233",
                    "number": "9012345678"
                }
            }
        }'
Enter fullscreen mode Exit fullscreen mode

For USSD, the process involves two steps. First, you need to retrieve the bank code, which is a unique identifier for each bank.

Note that bank codes are retrieved based on the specified country.

For Nigerian banks, send a request using the NG identifier.

curl -X GET "https://developersandbox-api.flutterwave.com/banks?country=NG" \
        -H "accept: application/json" \
        -H "X-Trace-Id: {{UNIQUE_TRACE_ID}}" \
        -H "authorization: Bearer {{API_ACCESS_TOKEN}}"
Enter fullscreen mode Exit fullscreen mode

You’ll get a response with the list of banks.

{
    "status": "success",
    "message": "Bank list retrieved successfully",
    "data": [
    {
        "id": "bnk_cYjd92Qk",
        "code": "044",
        "name": "Access Bank"
    }
    .......
    ]
}
Enter fullscreen mode Exit fullscreen mode

Then, use the bank code to make the same request to the charge endpoint and set the payment method to ussd.

curl -X POST "https://developersandbox-api.flutterwave.com/orchestration/direct-charges" \
        -H "Authorization: Bearer {{YOUR_ACCESS_TOKEN}}" \
        -H "Content-Type: application/json" \
        -H "X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}" \
        -H "X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}" \
        -d '{
            "reference": "YOUR_EXAMPLE_REFERENCE",
            "currency": "NGN",
            "amount": 1234.56,
            "payment_method": {
                "type": "ussd",
                "ussd": {
                    "account_bank": "044"
                }
            },
            "redirect_url": "http://www.google.com",
            "customer": {
                "address": {
                    "country": "US",
                    "city": "Gotham",
                    "state": "Colorado",
                    "postal_code": "94105",
                    "line1": "221B Baker Street"
                },
                "phone": {
                    "country_code": "1",
                    "number": "9069423351"
                },
                "name": {
                    "first": "King",
                    "middle": "Leo",
                    "last": "James"
                },
                "email": "james@example.com"
            }
        }'
Enter fullscreen mode Exit fullscreen mode

In addition to the payment methods discussed above, the orchestrator flow also supports accepting payments with OPay.

Payment Method Type
OPay opay

Check the API reference for the complete list of supported parameters you can include in your request.

Authorize the Charge

After initiating the charge, you’ll get a response that contains a next_action object that informs you on how the customer should complete the transaction.

For example, if the next_action is of type redirect_url, you need to redirect the user to the provided URL so they can complete the transaction.

"next_action": {
    "type": "redirect_url",
    "redirect_url": {
    "url": "https://developer-sandbox-ui-sit.flutterwave.cloud/redirects?card&token=eyJhbGciOiJIUzI1NiJ9.eyJjbGllbnRJZCI6ImFjODMxOTNlLWFhMmItNDc2ZS1hZTNjLTMxYmVmMTc4NDUxZCIsImNoYXJnZUlkIjoiY2hnX1JDRHNDQkR5YVYiLCJzdWIiOiJhYzgzMTkzZS1hYTJiLTQ3NmUtYWUzYy0zMWJlZjE3ODQ1MWQiLCJpYXQiOjE3MzA5NjQ1MTIsImV4cCI6MTczMDk2NDgxMn0.tMv1VZ4WevvZ_dg37AzYnhj0Z1YtXK_tQIOJcErNscI"
    }
},
Enter fullscreen mode Exit fullscreen mode

Possible responses you may receive include:

  1. requires_pin: The customer needs to complete the transaction using their card PIN.
  2. requires_otp: The customer must complete the transaction using the password sent to their mobile number.
  3. redirect_url: The customer needs to visit the provided URL to complete the transaction.
  4. requires_additional_fields: The customer must provide additional information, such as the billing address.
  5. payment_Instructions: The customer must follow specific instructions to complete the charge. For example, a USSD transaction requires the customer to complete the process offline.

For authorization methods like redirect_url and payment_instruction, where users complete the charge externally by visiting a redirect URL or completing it on their mobile phone, you only need to verify the payment. You can do this using a webhook or by querying the charge endpoint at specific intervals. More details on the verification step are covered in the next section.

For authorization methods like requires_pin, requires_otp, and requires_additional_fields, where users complete the charge internally, you need to authorize the charge by sending a request to the update charge endpoint and specifying the authorization object.

In a card payment that requires the customer’s PIN, update the request by sending the encrypted card PIN.

curl -X PUT "https://developersandbox-api.flutterwave.com/charges/{id}" \
        -H "Authorization: Bearer {{YOUR_ACCESS_TOKEN}}" \
        -H "Content-Type: application/json" \
        -H "X-Trace-Id: {{YOUR_UNIQUE_TRACE_ID}}" \
        -H "X-Idempotency-Key: {{YOUR_UNIQUE_INDEMPOTENCY_KEY}}" \
        -d '{
            "authorization": {
                "type": "pin",
                "pin": {
                    "nonce": "{{ENCRYPTED_NONCE}}",
                    "encrypted_pin": "{{ENCRYPTED_PIN}}"
                }
            }
        }'
Enter fullscreen mode Exit fullscreen mode

Verify the Transaction

Finally, you need to verify the transaction details, such as status and amount, before providing value to the customer. You can verify the transaction using either of the following methods:

Webhook (Recommended): We'll send a webhook with the transaction status if you have webhooks enabled on your dashboard.

{
    "webhook_id": "wbk_yXvsB4LzWSwhUCpAPCBR",
    "timestamp": 1739456704200,
    "type": "charge.updated",
    "data": {
        "id": "chg_zam88NgLb7",
        "amount": 1234.56,
        "currency": "USD",
        "customer": {
            "id": "cus_dc0FUyBpd0",
            "address": {
                "city": "Gotham",
                "country": "US",
                "line1": "221B Baker Street",
                "line2": "",
                "postal_code": "94105",
                "state": "Colorado"
            },
            "email": "james@example.com",
            "name": {
                "first": "King",
                "middle": "Leo",
                "last": "James"
            },
            "phone": {
                "country_code": "1",
                "number": "6313958745"
            },
            "meta": {},
            "created_datetime": "2024-12-25T20:16:38.246Z"
        },
        "description": null,
        "meta": {},
        "payment_method": {
            "type": "card",
            "card": {
                "expiry_month": 9,
                "expiry_year": 32,
                "first6": "553188",
                "last4": "2950",
                "network": "MASTERCARD",
                "billing_address": null,
                "cof": null,
                "card_holder_name": null
            },
            "id": "pmd_ujxuBcf4cJ",
            "customer_id": null,
            "meta": {},
            "device_fingerprint": null,
            "client_ip": null,
            "created_datetime": "2025-02-05T14:06:10.344Z"
        },
        "redirect_url": null,
        "reference": "ex61m23ja3feykheoidho8ilrri",
        "status": "succeeded",
        "processor_response": {
            "type": "approved",
            "code": "00"
        },
        "created_datetime": "2025-02-13T14:24:43.133Z"
    }
}
Enter fullscreen mode Exit fullscreen mode

Charge Endpoint: You can manually check the charge status by sending a request to retrieve a charge endpoint at a specific interval.

curl --request GET \
--url 'https://api-sit.flutterwave.cloud/developersandbox/charges/{id}' \
--header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>' \
--header 'Content-Type: application/json' \
--header 'X-Trace-Id: <YOUR_UNIQUE_TRACE_ID>' \
--header 'X-Idempotency-Key: <YOUR_UNIQUE_INDEMPOTENCY_KEY>' \
Enter fullscreen mode Exit fullscreen mode

You’ll get a response similar to this:

{
    "status": "success",
    "message": "Charge updated",
    "data": {
        "id": "chg_zam88NgLb7",
        "amount": 1234.56,
        "currency": "NGN",
        "customer": "cus_EFE4TQhBSf",
        "meta": {},
        "payment_method_details": {
            "type": "card",
            "card": {
                "expiry_month": 8,
                "expiry_year": 2024,
                "first6": "123412",
                "last4": "4444",
                "network": "mastercard"
            },
            "id": "pmd_NkWibrRJIy",
            "customer": "cus_dc0FUyBpd0",
            "meta": {}
        },
        "redirect_url": null,
        "reference": "ex61m23ja3feykheoidho8ilrri",
        "status": "succeeded",
        "processor_response": {
            "type": "approved",
            "code": "00"
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Wrapping Up

The payment orchestrator flow simplifies payment collection and supports multiple payment methods, including cards and mobile money. Its robust API makes it ideal for various payment-related use cases, such as one-time payments.

To get started:

Top comments (0)