Embedded checkout
Take crypto payments on your own website without redirecting. Open the LayerHop checkout as a popup or inline with checkout.js, @layerhop/widget or a React component, and react to paid, cancel and status events.
The embedded checkout shows the LayerHop payment page on your website, in a popup or inline, so customers pay without leaving your site. It is the same checkout as the hosted page (any token, any chain, delivery verified on chain), loaded in a secure iframe from layerhop.com. Wallets connect inside it; your page never touches keys or funds.
You need either a checkout session created by your server (Checkout) or a product id (Payment buttons).
Script tag#
<script src="https://layerhop.com/checkout.js" async></script>
<script>
async function pay() {
// Your server created the session with your API key and returned its id
const { sessionId } = await fetch("/api/create-checkout", { method: "POST" }).then((r) => r.json());
LayerHopCheckout.open({
sessionId,
onPaid: (session) => (location.href = "/thanks?session=" + session.id),
onCancel: () => console.log("closed without paying"),
});
}
</script>
<button onclick="pay()">Pay with crypto</button>Or with a product, no server at all:
LayerHopCheckout.open({ productId: "prod_…", reference: "order_1042", onPaid: (session) => { … } });Show the checkout inside your page instead of a popup:
<div id="pay"></div>
<script>
LayerHopCheckout.mount("#pay", { sessionId: "cs_…", onPaid: (session) => { … } });
</script>The inline frame resizes to fit its content.
npm#
npm install @layerhop/widgetimport { openCheckout, mountCheckout } from "@layerhop/widget";
const checkout = openCheckout({ sessionId, onPaid: (session) => showThanks(session) });
// checkout.close() to dismiss it from your codeReact:
import { LayerHopCheckout } from "@layerhop/widget/react";
export function Pay({ sessionId }: { sessionId: string }) {
return <LayerHopCheckout sessionId={sessionId} onPaid={(s) => router.push(`/thanks/${s.id}`)} />;
}Options and events#
| Option | Meaning |
|---|---|
sessionId |
A session your server created (POST /v1/checkout/sessions). |
productId |
A product: the library starts a session for it (reference and metadata optional). |
onReady() |
The checkout has loaded. |
onStatus(status) |
The session status changed (processing, paid, …). |
onPaid(session) |
LayerHop verified the payment. The session is paid. In the browser it is the public view (no reference or metadata); look those up on your server by session.id, or read them from the webhook. |
onCancel() |
The customer cancelled. |
onClose() |
The popup closed (after paying or not). |
The iframe talks to your page with postMessage messages { source: "layerhop-checkout", version: 1, type, sessionId, … }, where type is ready, resize, status, paid, cancel or close. The library checks that each message comes from layerhop.com and from its own frame before calling your callbacks.
Important
Browser callbacks are for the user interface. Fulfil orders on the signed
checkout.session.completedwebhook, or by fetching the session from your server with your key, never because the browser said so.
Wallets inside the frame#
Browser-extension wallets (MetaMask, Phantom, Rabby, Coinbase Wallet and others) and WalletConnect QR codes work inside the embedded checkout. On phones, the popup becomes a full-screen sheet.
Test it#
Create the session or product with an lh_test_ key: the checkout shows a Test mode badge and a Simulate test payment button, and onPaid fires about 10 to 20 seconds later. See Test mode.
Last updated