You can use a customer's saved payment details to set up a subscription management solution for your business. This guide will explain how you can store more information about your customers to handle recurring charges.
Make sure you clarify and update your service's Terms and Conditions about handling sensitive data and recurring payments to comply with local regulations.
It's your responsibility as a merchant to meet local legislation requirements and be PCI DSS compliant.
Check the following high-level procedure to implement a subscription management process, using the Revolut Checkout Widget and the Merchant API:
To save a customer's payment details by completing an order, see: Save the card details of a customer.
In case of a subscription management system, you (as the merchant) will initiate the payments, so you have to save the payment method for yourself (Revolut Checkout Widget: savePaymentMethodFor: "merchant"
, Revolut Pay: savePaymentMethodForMerchant: true
). This way, your customers only need to authorise the payment the first time.
You have two options to authorise the first payment:
0
amount to pay, so the customer only authorises their payment method for future payments. This is helpful when you have a separate process to save payment methods. See an example of the Payments.revolutPay
instance:
import RevolutCheckout from '@revolut/checkout'
const { revolutPay } = await RevolutCheckout.payments({
locale: 'en' ,// Optional, defaults to 'auto'
mode: 'prod', // Optional, defaults to 'prod'
publicToken: '<yourPublicApiKey>', // Merchant public API key
})
const paymentOptions = {
currency: 'USD', // 3-letter currency code
totalAmount: number, // in lowest denomination e.g., cents
savePaymentMethodForMerchant: true,
// Put other parameters here
}
revolutPay.mount(target, paymentOptions)
The example above is not complete, it is intended to demonstrate the savePaymentMethodForMerchant
parameter. To see the full implementation process, visit: Accept payments via Revolut Pay - Web.
By initialising the Revolut Pay widget with the savePaymentMethodForMerchant
option customers can grant permission to the merchant to initiate transactions without further action required from the customer. Customers are able to save both their Revolut account and card details via Revolut Pay.
For more information about configuring and mounting the Revolut Pay widget, see: Configure Revolut Pay button and Mount Revolut Pay button.
Only merchant initiated transactions are supported with Revolut Pay on the Pay for an order endpoint.
See an example with the createCardField
instance:
RevolutCheckout("<token>").then(function (instance) {
var card = instance.createCardField({
target: document.getElementById("card-field"),
onSuccess() {
window.alert("Thank you!");
},
onError(message) {
window.alert("Oh no :(");
},
});
document
.getElementById("button-submit")
.addEventListener("click", function () {
card.submit({
savePaymentMethodFor: "merchant",
});
});
});
You can also use the payWithPopup
instance of the Revolut Checkout Widget to save a customer's payment method.
Storing payment details (Revolut account, or card details) can be helpful when you have more websites, and you want to provide a faster subscription experience across all your sites. However, if you choose to store payment details, you must ensure that these are in sync with the ones on the Merchant API.
Use the last paid order of the customer to retrieve a customer's Revolut account or card details stored on Revolut's server. Fetch and save the information from the response of the Retrieve payment list of an order endpoint.
See an example of a saved payment_method
JSON object, returned by the endpoint:
[
{
"id": "64905d4b-a205-aac3-a5ef-dab978b1b7ee",
"order_id": "64905d0f-3f95-a2ac-91ea-57c77f9dbe69",
"state": "completed",
"payment_method": {
"type": "revolut_pay",
"id": "648334a8-9546-a983-a81a-efc6d5bdd0be",
"subtype": "revolut_account"
}
}
]
If you don't receive payment_method.id
, that means the payment method was not saved during checkout. Check your Revolut Pay or Revolut Checkout Widget configuration. If everything seems right, reach out to Revolut for further support.
You can use this JSON object to retrieve and save a customer's payment details on your server.
To manage a customer's subscription plan, you need to handle the following tasks:
/payments
endpointSet up an automated job on your backend that triggers these tasks at the expected time, and use calculations based on the subscription's start date. This job should run at the start of every subscription period until cancelled.
Configure a task which will send a notification (e.g. email) to the customer containing the following:
Local regulations may differ in what is required for such notification. It is your responsibility to consider the requirements of local regulators and comply with the relevant laws.
When it's time to charge the customer for the subscription fee, use your automation to create an order with the amount
, currency
, customer.email
(or customer.id
) parameters in the body of the request.
You can use the metadata
object (optional, but recommended) to add any additional custom parameters.
Set up another task in your automation job, which initiates a payment by sending a POST
request to the Pay for an order endpoint.
Use the order_id
from the response of the previous call and send a request with the following payload to charge the customer's saved payment method.
{
"saved_payment_method": {
"type": "<type of the saved payment method>",
"id": "<ID of the saved payment method>",
"initiator": "<initiator of the payment>"
}
}
Make sure to pass initiator: merchant
in the request body to take the payment without further actions required from your customer.
After your backend sends the request to the /payments
endpoint, use the order_id
from the response of the payment request to set up an automated request that repeatedly checks the payment status. This way, you can track the payment's state
transitions.
For more information about this endpoint, see: Merchant API: Retrieve payment details.
Your backend should continue to check the payment state until the response contains a final payment state. Depending on the received final payment state, you need to do the following:
Payment state | Description |
---|---|
captured | You can handle captured payments as completed and continue with Step 3.5. It usually takes 24 hours to settle payments on your Merchant Account (except in case of instant settlement). |
completed | In case of instant settlements, captured payments instantly get settled to your Merchant Account, so the payment transitions to completed state. Continue with Step 3.5. |
authorised | In case you capture payments manually, payments stay in authorised state until you capture them, to learn more about the process, see: Authorise an amount to capture later. After you captured the payment, continue with Step 3.5. |
declined | The payment was declined for some reason, check the Troubleshooting section to learn more about how to resolve the issue. For more information about specific decline reasons, see: Decline reasons. |
failed | The payment failed for some reason, check the Troubleshooting section to learn more about how to resolve the issue. For more information about specific decline reasons, see: Decline reasons. |
cancelled | If you capture payments manually, a payment in authorised state can be cancelled via the Cancel an order endpoint. If you want to reinitiate the payment, a new order has to be created. Restart the process from creating the order. |
If the payment transitioned to one of the successful final states (captured
, completed
), the corresponding order transitions to completed
state. You can stop polling the payment status, and inform your customers about the status of their purchase.
Optionally, you can also set up webhooks to track order completion. However, Revolut only sends webhook events when a final order state is reached (ORDER_COMPLETED
, ORDER_PAYMENT_DECLINED
, ORDER_PAYMENT_FAILED
).
If you only rely on webhook events, your system cannot react to intermediate payment state transitions. For more information about using webhooks, see: Using webhooks to keep track of the payment lifecycle.
You have two options to check for order completion:
ORDER_COMPLETED
eventsWhen you confirmed that the order is completed, your system should send a notification (e.g. email) to the customer containing the following:
Optionally, you can set up a separate page on your website where customers can manage their subscriptions. This page can have the following features, for example:
Doing this is optional, but it can provide a better user experience, and you don't have to manually keep track of customers changing their subscriptions (e.g. handling cancellations via emails).
You've successfully implemented a subscription management process using the Revolut Checkout Widget and the Merchant API.
The above-described process assumes that everything is working as expected. However, your system should be prepared to handle error cases. To test different payment errors, use the test cards for error cases in the Sandbox environment.
You have two options to check for error events:
declined
, failure
).ORDER_PAYMENT_DECLINED
, ORDER_PAYMENT_FAILED
events.When you catch an error, your system should send a notification (e.g. email) to the customer containing the following:
payments.decline_reason
field from the response of the Retrieve an order endpoint, using the unsuccessful order's id
. To learn more, check our decline reasons.token
and saving the new payment method. Use the new payment method for future payments.