Flutterwave Inline
Flutterwave Inline is the easiest way to collect payments on your website: Import our lightweight JavaScript library on your checkout page, then call the FlutterwaveCheckout()
function when the customer clicks on your payment button. We'll handle the payment and return to you when it's done.
In this guide, we'll walk you through using Flutterwave Inline on your site.
An example
Here's what an implementation of Flutterwave Inline on a checkout page could look like:
See the Pen Flutterwave Inline by Flutterwave Developers (@FlutterwaveEng) on CodePen.
You can actually try out the payment above. Use the card number 4187427415564246
with CVV 828
and expiry 09/32
, or grab a test card or bank account from our Testing Helpers page. It works!
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 up 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 that callsmakePayment()
, a custom JS function you're going to write.<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: "rose@unsinkableship.com", 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", }, }); }
FlutterwaveCheckout()
Calling Let's take a closer look at the parameters we passed when calling FlutterwaveCheckout
:
-
The
public_key
is your Flutterwave public API key. Here's how to get it.Don't forget: this is client-side code, so it uses your public key, not your secret key.
-
The
tx_ref
is a unique transaction reference you should generate for each transaction.We recommend generating the transaction reference on the server, so you can compare with previous transactions to be sure there are no duplicates. -
The
amount
is 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. -
The
currency
is the currency the amount is in. Flutterwave supports over a hundred different currencies, so be sure to specify the currency you mean. -
The
redirect_url
field (optional) is the URL we'll redirect to on your site after the payment is done. Alternatively, you can specify acallback
function. See the redirects and callbacks section.What is a "done" payment?On Flutterwave Inline, a done payment is a successful payment. This is because we don't end the payment session if the payment attempt fails; we keep it open for the customer to try again. We only redirect or callback when the payment succeeds.
-
The
customer
field holds the customer details. Theemail
field is required (we'll send the customer a payment receipt afterwards, unless you've disabled that). You can also pass in aname
andphone_number
. -
The
meta
field (optional) holds any extra details you want to record with the transaction. -
The
customizations
field (optional) allows you to customize the look and feel of the payment modal. You can set alogo
, the store name to be displayed (title
), and adescription
for the payment. -
The
payment_options
field (optional) allows you to specify what payment methods you want to allow payments from. Learn more about this field and the available options here.The
payment_options
field only works if you've unchecked Enable Dashboard Payment Options on your Account Settings.
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're using a callback instead of a redirect.
Redirects and callbacks
Alright, so now you've called FlutterwaveCheckout()
. What happens when the payment is done?
One of two things can happen: redirect or callback. You choose.
Option 1: Redirect
If you specify a redirect_url
when calling FlutterwaveCheckout()
(as we did in our example above), we'll redirect the customer to that URL when the payment is done. 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 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 done, passing in the payment object. Here's what that object looks like:
{
"amount": 54600,
"currency": "NGN",
"customer": {
"name": "Rose DeWitt Bukater",
"email": "rose@unsinkableship.com",
"phone_number": "08102909304"
},
"flw_ref": "FLW-MOCK-597ae423f1470309edcb5879e3774bfa",
"status": "successful",
"tx_ref": "titanic-48981487343MDI0NzMx",
"transaction_id": 495000
}
Note that the callback
will be called after the payment is completed, but while the modal is still open. You can combine the callback
with the onclose 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 failed, it will ask the customer to try again or contact support.
See the Pen Flutterwave Inline (Callback) by Shalvah (@shalvah) on CodePen.
You should always verify the payment on your server afterwards, even if you used a callback.
The redirect_url
has higher precedence than the callback
, 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. If you do want to be notified, though, 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.
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
}
}
});
}
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": "rose@unsinkableship.com",
"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"
}
Moving on from here...
All done! Now you know how to collect payments with Flutterwave Inline.
If the JS-based flow doesn't work for you, we've got other options:
- HTML checkout lets you do the same thing, but entirely in your HTML.
- Flutterwave Standard lets you control the payment flow from your server instead.
And there's more! Check out our Collecting Payments overview to know your options. And if you get stuck, you can always ask for help on our developer forum.