Welcome to the implementation guide for Revolut Pay on web! This page provides a comprehensive walkthrough for integrating Revolut Pay into your websites.
Merchants have multiple options to integrate Revolut Pay, either using the event listening function of the widget, using event listening with mobile redirect URLs, or using redirect URLs. The main difference between the options is how the widget handles different results of the payment flow (success
, failure
, cancel
):
The following sections list some aspects of each option merchants should take into consideration.
Check the following high-level procedure to implement Revolut Pay on your website:
The following sections describe each step in detail, to see working examples you can skip ahead.
Before you start this tutorial, ensure that you have completed the following steps:
Make sure you're on the latest version of the @revolut/checkout
library: v1.1.4+
import RevolutCheckout from '@revolut/checkout'
const { revolutPay } = await RevolutCheckout.payments({
locale: 'en' ,// Optional, defaults to 'auto'
mode: 'sandbox', // Optional, defaults to 'prod'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
Before mounting the Revolut Pay button, configure the Revolut Pay object's parameters.
For a more detailed reference of the Revolut Pay options and button styling, see: Payments.revolutPay reference and Revolut Pay button guidelines.
const paymentOptions = {
currency: 'USD', // 3-letter currency code
totalAmount: number, // in lowest denomination e.g., cents
// If you wish to implement Revolut Pay with event listening and mobile redirect URLs (skip this option if you only listen to events or only use redirect URLs):
mobileRedirectUrls: {
success: 'https://www.example.com/success',
failure: 'https://www.example.com/failure',
cancel: 'https://www.example.com/cancel'
},
// If you wish to implement Revolut Pay with redirect URLs (skip this option if you listen to events):
redirectUrls: {
success: 'https://www.example.com/success',
failure: 'https://www.example.com/failure',
cancel: 'https://www.example.com/cancel'
},
createOrder: async () => {
// Call your backend here to create an order
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
// You can put other optional parameters here
}
On your frontend, replace yourServerSideCall()
from the example with a function you defined to call your backend/server. The role of this function is to pass the order details (e.g., amount
, currency
, billing_address
, etc.) from the frontend to your backend.
When your backend received the order details, it needs to send them as the payload of a request to the Merchant API: Create an order endpoint. The backend will receive the token
in the response.
You need to send the token
back to your frontend and pass it to our widget. The token
is required for initialising a new checkout session on the Revolut Pay widget.
The Create an order endpoint was updated to a new version and now returns token
as the public identifier for the order. Previous integrations might still use the deprecated endpoint returning public_id
.
We strongly advise upgrading to the new Create an order endpoint.
Pass the savePaymentMethodForMerchant
parameter as true
in order to save your customer's payment details during checkout. Customers are able to save both their Revolut account and card details via Revolut Pay.
This way, your customers can grant permission for you to initiate payments on their saved payment method stored by Revolut Pay, without any further action required from the customer. Use this feature to initiate recurring payments, e.g., to take payments for a subscription or to charge a customer later for a specific order.
By default, merchant initiated transactions are disabled.
To learn more about how to save and charge a customer's payment method, see: Charge a customer's saved payment method.
If you wish to save a customer's payment details using Revolut Pay - Web, you need to meet one of the following requirements:
email
and assign it to the order by providing customer.id
customer.email
during order creationIf you want the shipping address and delivery method to be quickly collected from the user through Revolut Pay, pass the requestShipping
parameter as true
.
This way, your app can skip the shipping flow during checkout and the user can use existing shipping details stored by Revolut Pay.
By default, Fast checkout is not enabled.
Your backend must support Fast checkout for this functionality to work. For more information, see: Implement Revolut Pay with Fast checkout.
Mount the Revolut Pay button with the following line:
revolutPay.mount(target, paymentOptions)
Parameter | Description |
---|---|
target | Can be either a DOM node e.g., document.getElementById("kiwi") or a CSS selector e.g., "#kiwi" . |
paymentOptions | Refers to the payment options describing the payment being initiated. For more information, see: Payments.revolutPay: Mount options. |
Completing this step is only needed, when implementing Revolut Pay with event listening.
To listen to relevant events during the payment flow, use the following code:
revolutPay.on('payment', (event) => {
// ... do something e.g., perform redirect
})
For more information about listening to payment
events, see: Payments.revolutPay: Listen to events.
For more information about the createOrder
operation, see: Merchant API reference: Create an order.
The order must be created on the server side. The client SDK will only receive the publicId
of the created order.
In the following section, you can find a working example of the Revolut Pay button.
Insert the Revolut Pay button using the code snippet below that contains an example with minimum required parameters, where:
RevolutCheckout
is the widget instance.<yourPublicApiKey>
is your Merchant Public API Key.order.token
is returned when the createOrder
operation runs. For more information, see the following section of the Merchant API reference: Create an order.event.type
is returned after a payment
is triggered, defines the state of the payment. For more information, see: Payments.revolutPay: Listen to events.Insert the following DOM element into your webpage where you want to render the Revolut Pay button, and pass the id
of this element as the first argument of the .mount
statement:
...
<div id='revolut-pay'></div>
...
import RevolutCheckout from '@revolut/checkout'
const { revolutPay } = await RevolutCheckout.payments({
publicToken: '<yourPublicApiKey>' // Merchant public API key
})
const paymentOptions = {
currency: 'USD',
totalAmount: 1000,
createOrder: async () => {
// Call your backend here to create an order
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
// You can put other optional parameters here
}
revolutPay.mount(document.getElementById('revolut-pay'), paymentOptions)
revolutPay.on('payment', (event) => {
switch (event.type) {
case 'cancel': {
if (event.dropOffState === 'payment_summary') {
log('what a shame, please complete your payment')
}
break
}
case 'success':
onSuccess()
break
case 'error':
onError(event.error)
break
}
})
import RevolutCheckout from '@revolut/checkout'
const { revolutPay } = await RevolutCheckout.payments({
publicToken: '<yourPublicAPIKey>' // Merchant public API key
})
const paymentOptions = {
currency: 'USD', // 3-letter currency code
totalAmount: 1000, // In lowest denomination e.g., cents
mobileRedirectUrls: {
success: 'https://www.example.com/success',
failure: 'https://www.example.com/failure',
cancel: 'https://www.example.com/cancel'
},
createOrder: async () => {
// Call your backend here to create an order
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
// You can put other optional parameters here
}
revolutPay.mount(document.getElementById('revolut-pay'), paymentOptions)
revolutPay.on('payment', (event) => {
switch (event.type) {
case 'cancel': {
if (event.dropOffState === 'payment_summary') {
log('what a shame, please complete your payment')
}
break
}
case 'success':
onSuccess()
break
case 'error':
onError(event.error)
break
}
})
import RevolutCheckout from '@revolut/checkout'
const { revolutPay } = await RevolutCheckout.payments({
publicToken: '<yourPublicApiKey>' // merchant public API key
})
const paymentOptions = {
currency: 'USD',
totalAmount: 1000,
redirectUrls: {
success: 'https://www.example.com/success',
failure: 'https://www.example.com/failure',
cancel: 'https://www.example.com/cancel'
},
createOrder: async () => {
// Call your backend here to create an order
// For more information, see: https://developer.revolut.com/docs/merchant/create-order
const order = await yourServerSideCall()
return { publicId: order.token }
},
// You can put other optional parameters here
}
revolutPay.mount(document.getElementById('revolut-pay'), paymentOptions)
This is what the button looks like:
Before deploying your implementation to your production environment, complete the checklist below to see if everything works as expected, using Merchant API's Sandbox environment. To test in Sandbox environment, set the base URL of your API calls to: sandbox-merchant.revolut.com/
.
As Revolut Pay has more complex user flows compared to other payment methods, the following user journey paths needs to be tested (besides general tests):
To see if your implementation is able to manage all flows, check each flow against the checks below.
This is the least complex of user flows. Steps are the following:
This user flow represents the case where the Revolut app is not installed on the customer's phone:
You can test this flow with your browser's built-in mobile browser simulator. Available via the browser's developer tools.
This user flow represent the case, where the Revolut app is installed on the customer's phone:
Only Google Chrome, Safari, Samsung Internet Browser, Firefox, and Opera are supported. If the user begins on any other browser, successful redirection to the same browser is not guaranteed. The user will be redirected to their default mobile browser.
token
is successfully fetched.cancel
events, and you manage every dropOffState
as intended. For more information about the cancellation events, see: Payments.revolutPay: Event object.If you implemented Revolut Pay with event listening:
If you implemented Revolut Pay with event listening and mobile redirect URLs:
If you implemented Revolut Pay with redirect URLs:
If your implementation handles all these cases as you expect in Sandbox, it is advised you also test your implementation in production before going live. Once your implementation passes all the checks in both environments, you can safely go live with your implementation.
These checks only cover the implementation path described in this tutorial, if your application handles more features of the Merchant API, see the Merchant API: Implementation checklists.
Congratulations! You've successfully implemented Revolut Pay and are ready to accept the first payment.