Guides • Accept Payments
Web
doc

Accept payments via Pay by Bank - Web

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.

info

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 - Web

note

Pay by Bank is not available in the sandbox environment. Real transactions must be made to test your implementation in the production environment.

How it works

Implementing the Pay by Bank widget involves these core components:

  1. Server-side: expose an endpoint on your backend that creates an order using the Merchant API: Create an order endpoint.
  2. Client-side: the Revolut Checkout Widget facilitates bank selection, uses your endpoint to create the order, and handles other actions like redirection or customer authentication.
  3. Webhook endpoint (recommended): Set up webhooks to monitor payment lifecycle events. For more details, refer to Use webhooks to track of the payment lifecycle.

The order and payment flow is similar to all payment solutions:

  1. The customer goes to the checkout page.
  2. The customer initiates the payment by clicking a button.
  3. Your client creates an instance of the payByBank widget.
  4. The widget shows a pop-up window to select the customer's bank, and handles additional actions, like redirection to the bank's page to complete the payment.
  5. In the background, the widget uses your endpoint to create an order, initiates the payment processing, and handles payment results via event callbacks.
  6. Your client responds to the callbacks to present the payment result to the customer.
  7. Your server receives webhook notifications about each event you're subscribed to.
info

For more information about the order and payment lifecycle, see: Order and payment lifecycle.

Implementation overview

Here is an overview of the key integration steps:

  1. Install Revolut Checkout Widget
  2. Set up an endpoint for creating orders
  3. Initialise widget
  4. Add DOM element
  5. Listen to DOM events
  6. Configure and show the widget
  7. Listen to webhooks

Before you begin

Make sure you've completed the following:

Implement the Pay by Bank widget

1. Install Revolut Checkout Widget

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
info

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.

2. Set up an endpoint for creating orders

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"
}

3. Initialise widget

Use the RevolutCheckout.payments() module's payByBank instance with your Merchant API Public key to initialise the widget.

my-app.js
const { payByBank } = await RevolutCheckout.payments({
locale: 'en', // Optional, defaults to 'auto'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})

// Configuration code will go here
info

For more information about the RevolutCheckout.payments() function, see: Merchant Web SDKs: The payments object

4. Add DOM element

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.

5. Listen to DOM events

Attach a click handler to your button that will trigger the widget.

my-app.js
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
})


6. Configure and show the widget

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.

my-app.js
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 up
  • createOrder 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.

    1. Your backend calls the Merchant API: Create an order endpoint with that payload.
    2. The Merchant API responds with a token.
    3. You return { 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:

    • Redirect the customer to a confirmation page
    • Update your UI with a "Thank you" message
    • Trigger any post-purchase logic (e.g. emailing a receipt)
  • 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:

    • Display a custom error screen
    • Log the error for diagnostics
    • Retry the order-creation or prompt the user to choose another bank
  • 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.

info

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.

Additional settings

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:

  1. 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.
  2. Instant payment filter:

    • By setting 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.

7. Listen to webhooks

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.

tip

Important considerations for Pay by Bank:

  • Settlement time: Payments processed via non-instant methods like SEPA Credit Transfers can take up to 2 business days to settle in your account. Relying solely on client-side redirects or polling for status updates is not recommended due to these potential delays.
  • Fulfillment trigger: You should wait for the 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.

info

Follow our detailed guide to set up webhooks for your integration: Use webhooks to track the payment lifecycle.

Examples

Insert the following DOM element into your webpage where you want to display the Pay by Bank widget, and attach to your click handler:

checkout.html
<button id='pay-by-bank'>Pay by bank</button>

Example with minimal required parameters

my-app.js
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()
})


Example with additional parameters

my-app.js
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()
})


What's next

Was this page helpful?