Skip to navigation

Embedded Checkouts

Recurrente Checkout is a JavaScript library that lets you embed a responsive, secure checkout directly on your website. It renders an iframe with your payment session and handles callbacks for key events like success, failure, or pending payments.

For the most up-to-date version of this guide and sample code, visit the repo: github.com/recurrente/recurrente-checkout

Video tutorial

See it in action: https://youtu.be/OUIYVcrnPr0

Prerequisites

To use this library, you need to create a checkout in Recurrente. See the checkout creation docs to get your checkout URL.

Clave in embedded checkouts

Inside an iframe the browser treats our cookies as third-party, so Clave does not always recognise a customer by their browser. That is why the embedded checkout leads with a Pay with Clave button, the way Link’s sits beside Apple Pay: it opens the Clave window, a window on our own origin where the browser does hand over the cookie; the customer picks their card and pays, the window closes itself and your page receives onSuccess exactly as it does for a payment inside the iframe. Whoever would rather stay in the form keeps the usual path: Clave recognises them by the email or phone they are already typing, sends a one-time code, and confirming it brings their saved methods into the checkout.

Nothing needs configuring for this to work, and your customer never has to change browser permissions. In-app browsers (Instagram, Facebook, WhatsApp) cannot hold a popup, so the button stays out there and the code remains. See Accept Clave.

Local development

The checkout’s card fields are served by our processor, which only accepts a parent page on an https:// origin or on http://localhost (any port). If you open your site from http://127.0.0.1, a LAN address or a host like myapp.local, the checkout loads but the card form fails with a 422 on capture_context whose body names the rejected origin.

To test locally, open your site at http://localhost:PORT or expose it over HTTPS with a tunnel such as ngrok.

Installation

npm install recurrente-checkout

CDN

<script src="https://cdn.jsdelivr.net/npm/recurrente-checkout@0.0.5/recurrente-checkout.js"></script>

Pin the version in the CDN URL, so a new release never changes your checkout without you knowing.

Usage

<div id="recurrente-checkout-container"></div>
import RecurrenteCheckout from "recurrente-checkout";
RecurrenteCheckout.load({
url: "https://app.recurrente.com/checkout-session/ch_abc123",
onSuccess: (data) => {
console.log("Payment succeeded", data.checkoutId);
},
onFailure: (data) => {
console.log("Payment failed", data.error);
},
onPaymentInProgress: (data) => {
console.log("Payment in progress", data.checkoutId);
},
});

The checkout mounts in the element with id recurrente-checkout-container. If it doesn’t exist, the library creates it at the end of the page.

Parameters

ParameterTypeDescription
urlstringThe checkout_url the API returns when you create a checkout
onSuccessfunctionWhen the payment completes. Receives checkoutId
onFailurefunctionWhen an attempt fails. Receives error (and notice, with the same text)
onPaymentInProgressfunctionWhen the payment is pending, such as a bank transfer
developmentbooleanAccepts events from any origin. For local testing only

Full flow

  1. Create a checkout through the Recurrente API (POST /api/checkouts)
  2. Pass its checkout_url to RecurrenteCheckout.load
  3. Handle the callbacks for success, failure, or pending payment
  4. Confirm the payment on your server with the webhook or GET /api/checkouts/{id} before fulfilling
// 1. Create the checkout from your backend
const response = await fetch("/api/create-checkout", { method: "POST" });
const { checkout_url } = await response.json();
// 2-3. Mount and initialize
RecurrenteCheckout.load({
url: checkout_url,
onSuccess: () => window.location.href = "/thank-you",
onFailure: () => alert("Payment failed. Please try again."),
});

Already have your own payment form and only want to add Clave? Use the Clave button.