Flutterwave Inline
Start integrating Flutterwave with a few lines of code.
Flutterwave Inline is the easiest way to receive payments on your website. Simply import our lightweight JavaScript library on your checkout page, and call the FlutterwaveCheckout()
function when your customer clicks the payment button. We'll handle the payment process and notify you once it's complete.
An Example
Try it Out
You can try out the payment above. Use the card number
4187427415564246
with CVV828
and expiry09/32
, or grab a test card or bank account from our Testing page.
Let's take a closer look at the key things this code does:
- First, you include the Flutterwave Inline library with a script tag:
<script src="https://checkout.flutterwave.com/v3.js"></script>
- Next is the payment button. This is the button the customer clicks after they've reviewed their order and are ready to pay you. You'll attach an
onclick
event handler to this button and call themakePayment()
function.
<button type="button" onclick="makePayment()">Pay Now</button>
- Finally, in the
makePayment()
function, you call theFlutterwaveCheckout()
function with some custom parameters:
function makePayment() {
FlutterwaveCheckout({
public_key: 'FLWPUBK_TEST-SANDBOXDEMOKEY-X',
tx_ref: 'titanic-48981487343MDI0NzMx',
amount: 54600,
currency: 'NGN',
payment_options: 'card, mobilemoneyghana, ussd',
redirect_url: 'https://glaciers.titanic.com/handle-flutterwave-payment',
meta: {
consumer_id: 23,
consumer_mac: '92a3-912ba-1192a',
},
customer: {
email: '[email protected]',
phone_number: '08102909304',
name: 'Rose DeWitt Bukater',
},
customizations: {
title: 'The Titanic Store',
description: 'Payment for an awesome cruise',
logo: 'https://www.logolynx.com/images/logolynx/22/2239ca38f5505fbfce7e55bbc0604386.jpeg',
},
});
}
Calling the FlutterwaveCheckout()
Function
FlutterwaveCheckout()
FunctionLet's take a closer look at the parameters we passed when calling FlutterwaveCheckout()
:
Parameters | Functions |
---|---|
tx_ref | A unique transaction reference you should generate for each transaction. |
amount | The amount the customer is to pay. In this case, we're hardcoding it, but you could also dynamically get it from your server or client-side JavaScript. |
currency | The currency the amount is in. Flutterwave supports over a hundred different currencies, so be sure to specify the currency you mean. |
customer | This field holds the customer details. The email field is required (we'll send the customer a payment receipt afterward unless you've disabled that). You can also pass in a name and phone_number . |
public_key | This is your public API key. Here's how to get it. |
meta (optional) | This will hold any extra details you want to record with the transaction. |
redirect_url (optional) | This is the URL we'll redirect to on your site after the payment is done. Alternatively, you can specify a callback function. See the redirects and callbacks section. |
customizations (optional) | This allows you to customize the look and feel of the payment modal. You can set a logo , the store name to be displayed (title ), and a description for the payment. |
payment_options (optional) | This allows you to specify what payment methods you want to allow payments from. Learn more about this field and the available options here. |
Public Key
Don't forget that this is client-side code, so it uses your public key, not your secret key.
Generating Transaction Reference
We also recommend generating the transaction reference (
tx_ref
) on the server, so you can compare with previous transactions to be sure there are no duplicates.
The call to FlutterwaveCheckout()
returns a JavaScript object with a close()
method that can be used to close the modal, which can be useful if you are using callbacks instead of redirects.
Redirects and Callbacks
After calling the FlutterwaveCheckout()
function and the payment is done, you can do one of the following:
Option 1: Redirect
If you specify a redirect_url
when calling FlutterwaveCheckout()
(like in our example above), we'll redirect the customer to that URL when the payment is made. We'll append your transaction reference, our transaction ID, and status to the URL like this: tx_ref=ref&transaction_id=30490&status=successful.
On your server, you should handle the redirect and always verify the final state of the transaction.
Transaction Verification must be Server-Side
Transaction verification should always be done on the server, as it makes use of your secret key, which should never be exposed publicly.
Option 2: Callback
Alternatively, you can specify a callback
instead. In this case, you'll specify a JavaScript
function that we'll call when the payment is made, passing in the payment object. Here's what that object looks like:
{
"amount": 54600,
"currency": "NGN",
"customer": {
"name": "Rose DeWitt Bukater",
"email": "[email protected]",
"phone_number": "08102909304"
},
"flw_ref": "FLW-MOCK-597ae423f1470309edcb5879e3774bfa",
"status": "successful",
"tx_ref": "titanic-48981487343MDI0NzMx",
"transaction_id": 495000
}
Note
Note that the
callback
will be called after the payment is completed, but while the modal is still open. You can combine thecallback
with theonclose
handler for a better experience.
Here's an example that uses a callback
and onclose
function. The callback
function sends a verification request to the backend in the background. Then, when the customer closes the modal, the onclose
function displays a "verifying" message if the background request is not complete or a thank-you message if the verification was successful. If the verification fails, the customer will be asked to try again or contact support.
Always Verify your Transactions
You should always verify the payment on your server afterwards, even if you used a callback.
Note
The
redirect_url
has higher precedence than thecallback
, so if you specify both, we'll use the redirect.
You can also use the callback
option to manually close the modal with the modal's close()
method (this won't trigger the onclose
handler):
function makePayment() {
const modal = FlutterwaveCheckout({
// ...
callback: function (payment) {
// Send AJAX verification request to backend
verifyTransactionOnBackend(payment.id);
modal.close();
},
});
}
What if the Payment Fails?
If the payment attempt fails (for instance, due to insufficient funds), you don't need to do anything. We'll keep the payment page open so the customer can try again until the payment succeeds or they choose to cancel.
If you have webhooks enabled, we'll send you a notification for each failed payment attempt. This is useful in case you want to later reach out to customers who had issues paying. See our webhooks guide for an example.
If the customer closes the payment modal, you can handle this event using the onclose
option, described in the next section.
Handling Cancelled Payments
If the customer closes the payment modal before making payment or clicks Cancel Payment, we'll cancel the payment session, hide the modal, and you won't be notified. You can specify an onclose
function. We'll call this function when the payment is cancelled, with a single boolean argument that's true if the payment was not completed.
Payment Modal
If a customer closes the payment modal while the payment is processing, the payment will be marked as cancelled, but the payment session won't be aborted. If the transaction ends up succeeding later, webhooks, customer notifications, and the like will be triggered.
An example of when you might want to use this is to send such events to your analytics service or reach out to customers who didn't complete their orders.
function makePayment() {
FlutterwaveCheckout({
public_key: 'FLWPUBK_TEST-SANDBOXDEMOKEY-X',
// ...
onclose: function (incomplete) {
if (incomplete === true) {
// Record event in analytics
}
},
});
}
Handling Payment Retries and Timeout on Checkout
Flutterwave allows you to configure retries and timeout on checkout to further improve your customers' experience. Timeouts help you limit the completion time for each payment. Once the timeout period is completed, the payment window is closed, and the user is redirected to the specified URL (redirect_url
). Uncompleted transactions are cancelled and marked as failed.
The timeout can be set to a max value of 1440 minutes.
Additionally, you can limit how many attempts users make for failed transactions on checkout. By setting max_retry
, the user is prevented from attempting transactions unnecessarily at checkout. When making a payment, the transaction would be cancelled and marked as failed if the user attempts to reach max retry.
Using these configurations can help you improve security on checkout by limiting malicious users' payment attempts. For example, If timeout and retry for a transaction are set to 10 minutes and five (5) attempts, respectively. The transaction fails automatically if the user makes more than five attempts or spends longer than 10 minutes to complete the transaction.
function makePayment() {
FlutterwaveCheckout({
public_key: 'FLWPUBK_TEST-SANDBOXDEMOKEY-X',
tx_ref: 'titanic-48981487343MDI0NzMx',
amount: 54600,
currency: 'NGN',
payment_options: 'card, mobilemoneyghana, ussd',
redirect_url: 'https://glaciers.titanic.com/handle-flutterwave-payment',
meta: {
consumer_id: 23,
consumer_mac: '92a3-912ba-1192a',
},
customer: {
email: '[email protected]',
phone_number: '08102909304',
name: 'Rose DeWitt Bukater',
},
customizations: {
title: 'The Titanic Store',
description: 'Payment for an awesome cruise',
logo: 'https://www.logolynx.com/images/logolynx/22/2239ca38f5505fbfce7e55bbc0604386.jpeg',
},
configurations: {
session_duration: 10, //Session timeout in minutes (maxValue: 1440 minutes)
max_retry_attempt: 5, //Max retry (int)
},
});
}
Framework Integrations
If you're using a frontend JS framework, we've got custom integrations to ensure the payment flow plays nice with your framework. Check out our frontend libraries page to see what's available.
Webhooks
If you've set up webhook notifications for your account, we'll send you a webhook when the payment is completed, as well as for each failed payment attempt. Here's what the webhook payload looks like:
{
"event": "charge.completed",
"data": {
"id": 408043532,
"tx_ref": "titanic-48981487343MDI0NzMx",
"flw_ref": "EJEZ7971570422814",
"device_fingerprint": "7852b6c97d67edce50a5f1e540719e39",
"amount": 54600,
"currency": "NGN",
"charged_amount": 54600,
"app_fee": 0.14,
"merchant_fee": 0,
"processor_response": "APPROVED",
"auth_model": "NOAUTH",
"ip": "72.140.222.142",
"narration": "CARD Transaction ",
"status": "successful",
"payment_type": "card",
"created_at": "2021-04-16T11:10:02.000Z",
"account_id": 82913,
"customer": {
"id": 255101610,
"name": "Rose DeWitt Bukater",
"phone_number": "08102909304",
"email": "[email protected]",
"created_at": "2021-04-16T11:10:02.000Z"
},
"card": {
"first_6digits": "539923",
"last_4digits": "2526",
"issuer": "MASTERCARD FIRST BANK OF NIGERIA PLC DEBIT CARD",
"country": "NG",
"type": "MASTERCARD",
"expiry": "01/23"
}
},
"event.type": "CARD_TRANSACTION"
}
Next Steps
All done! Now you know how to collect payments with Flutterwave Inline.
If the JS-based flow doesn't work for you, there are other options:
-
HTML checkout lets you do the same thing, but entirely in HTML.
-
Flutterwave Standard lets you control the payment flow from your server instead.
And there's more! Check out our Payments UI and Embeds page to know your options. And if you get stuck, you can always ask for help on our support page.
Updated 25 days ago