Revolut's Pay by Bank widget allows you to effortlessly accept payments directly from your customers' bank accounts, offering a seamless and secure checkout experience.
In this tutorial, we'll guide you through integrating the Pay by Bank widget, powered by the Revolut Checkout Widget. Customers can securely authorize payments directly from their bank accounts within your website, simplifying the payment process and enhancing user experience.
Pay by Bank is currently available by direct request only. If you'd like to enable this feature for your account, please contact our team at merchant-integration@revolut.com.
Pay by Bank is not available in the sandbox environment. Real transactions must be made to test your implementation in the production environment.
Implementing the Pay by Bank widget involves these core components:
The order and payment flow is similar to all payment solutions:
payByBank
widget.For more information about the order and payment lifecycle, see: Order and payment lifecycle.
Here is an overview of the key integration steps:
Make sure you've completed the following:
Before you begin, ensure the Revolut Checkout Widget is installed in your project. This widget is a necessary component to create and configure the Pay by Bank widget. You can install the widget via your project's package manager.
npm install @revolut/checkout
Alternatively, you can add the widget to your code base by adding the embed script to your page directly. To learn more, see: Adding the embed script.
When a customer proceeds to make payment on your website, the widget will call the createOrder
callback. You'll need to create an order based on your customer's checkout and return its token
using the Merchant API: Create an order endpoint.
This token represents the order and is used to initialise the Pay by Bank widget. The process of creating an order and receiving a token will vary based on your backend setup.
See an example response of an order created with minimal required parameters:
{
"id": "6516e61c-d279-a454-a837-bc52ce55ed49",
"token": "0adc0e3c-ab44-4f33-bcc0-534ded7354ce",
"type": "payment",
"state": "pending",
"created_at": "2023-09-29T14:58:36.079398Z",
"updated_at": "2023-09-29T14:58:36.079398Z",
"amount": 5,
"currency": "GBP",
"outstanding_amount": 5,
"capture_mode": "automatic",
"checkout_url": "https://checkout.revolut.com/payment-link/0adc0e3c-ab44-4f33-bcc0-534ded7354ce",
"enforce_challenge": "automatic"
}
Use the RevolutCheckout.payments()
module's payByBank
instance with your Merchant API Public key to initialise the widget.
const { payByBank } = await RevolutCheckout.payments({
locale: 'en', // Optional, defaults to 'auto'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
// Configuration code will go here
For more information about the RevolutCheckout.payments()
function, see: Merchant Web SDKs: The payments object
Prepare your checkout page by adding a button or similar interactive element that users will click to initiate the payment:
<...>
<button id='pay-by-bank'>Pay by bank</button>
<...>
This button will trigger your JavaScript integration of the widget, so make sure you listen to events.
Attach a click handler to your button that will trigger the widget.
const { payByBank } = await RevolutCheckout.payments({
locale: 'en', // Optional, defaults to 'auto'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
const payByBankButton = document.getElementById('pay-by-bank')
payByBankButton.addEventListener('click', async () => {
// Configuration code will go here
})
Invoke the payByBank({ ... })
instance and pass your configuration parameters. Then, call the .show()
method on the returned instance to open the Pay by Bank modal.
const { payByBank } = await RevolutCheckout.payments({
locale: 'en', // Optional, defaults to 'auto'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
const payByBankButton = document.getElementById('pay-by-bank')
payByBankButton.addEventListener('click', async () => {
const payByBankInstance = payByBank({
createOrder: async () => {
// Call your backend here to create an order and return order.token
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
onSuccess() {
// Do something to handle successful payments
window.alert('Successful payment!')
},
onError(error) {
// Do something to handle payment errors
window.alert(`Something went wrong. ${error}`)
}
})
payByBankInstance.show()
})
RevolutCheckout.payments(...)
initialises the Revolut Checkout module and returns an object containing the payByBank
factory. You must pass your locale
and publicToken
(your merchant public API key) here.
payByBank
is a function that creates a Pay by Bank instance when you call it with your options. It returns a PaymentsModulePayByBankInstance
that exposes two methods:
.show()
— opens the bank-selection modal.destroy()
— removes any rendered UI and cleans upcreateOrder
is a function you define (e.g. yourServerSideCall()) that takes the order details from your frontend (amount
, currency
, billing_address
, etc.) and passes them to your backend.
token
.{ publicId: order.token }
to the widget, so it can start the checkout session.onSuccess
is an event handler that triggers when the payment is successful. In this example it shows a "Successful payment!" alert. It's designed to execute custom actions. Any return value is ignored.
For example, you can:
onError
is an event handler that triggers in case of an error. In this example it displays an alert with the error message. Similar to the onSuccess
, it's intended for implementing custom error handling logic based on the merchant's requirements. Any return value is ignored.
For example, you can:
Finally, once you have your instance, call .show()
to open the Revolut Pay by Bank modal. If you need to abort before rendering, call .destroy()
instead.
For more details about the available parameters, see: Merchant Web SDK: Payments.payByBank.
By following these steps, you have successfully integrated the Revolut Checkout Widget's Pay by Bank module into your website. This setup allows customers to pay with their bank accounts securely.
The payByBank
module of the Revolut Checkout Widget offers several options that allow for a customised checkout experience. Here are some additional settings you can leverage:
Event handlers:
onSuccess
, onError
are event handlers that you can define to manage the different states of the payment process - from successful transactions to errors.onCancel
can be used to handle scenarios where the payment process is interrupted or cancelled by the user.Instant payment filter:
instantOnly: true
, you can restrict the list of available banks to those supporting real-time transfers. We recommend using this filter if your business fulfills orders instantly, as non-instant payments via SEPA can take up to 2 business days to arrive in your account.While client-side callbacks like onSuccess
indicate the customer has completed the flow, it's crucial to confirm the final payment status on your server before fulfilling the order. Webhooks provide a reliable way to track the order and payment lifecycle asynchronously.
Important considerations for Pay by Bank:
ORDER_COMPLETED
webhook event before fulfilling Pay by Bank orders. This event confirms that the funds are successfully settled.We strongly recommend implementing a webhook endpoint to listen for events. This approach is more robust than relying on client-side actions or polling, given potential settlement delays. Setting up webhooks allows you to reliably track order status and manage fulfillment accordingly.
Follow our detailed guide to set up webhooks for your integration: Use webhooks to track the payment lifecycle.
Insert the following DOM element into your webpage where you want to display the Pay by Bank widget, and attach to your click handler:
<button id='pay-by-bank'>Pay by bank</button>
const { payByBank } = await RevolutCheckout.payments({
locale: 'en', // Optional, defaults to 'auto'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
const payByBankButton = document.getElementById('pay-by-bank')
payByBankButton.addEventListener('click', async () => {
const payByBankInstance = payByBank({
createOrder: async () => {
// Call your backend here to create an order and return order.token
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
onSuccess() {
// Do something to handle successful payments
window.alert('Successful payment!')
},
onError(error) {
// Do something to handle payment errors
window.alert(`Something went wrong. ${error}`)
}
})
payByBankInstance.show()
})
const { payByBank } = await RevolutCheckout.payments({
locale: 'en', // Optional, defaults to 'auto'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
const payByBankButton = document.getElementById('pay-by-bank')
payByBankButton.addEventListener('click', async () => {
const payByBankInstance = payByBank({
createOrder: async () => {
// Call your backend here to create an order and return order.token
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
instantOnly: true,
onSuccess() {
// Do something to handle successful payments
window.alert('Successful payment!')
},
onError(error) {
// Do something to handle payment errors
window.alert(`Something went wrong. ${error}`)
},
onCancel() {
// Do something to handle cancelled payments
window.alert('The payment was cancelled.')
}
})
payByBankInstance.show()
})