Embedded Checkout
Embedded Checkout is a first-class integration in which your page frames a Maxana-owned checkout experience.
-
Your server creates a checkout session and sets the merchant pages that are permitted in
allowed_origins. -
Your page frames the response’s
embed_urland delegates browser payment permission to the cross-origin frame:<iframe src="https://maxanapay.com/embed/cs_abc123" title="Secure checkout" style="width: 100%; height: 640px; border: 0" allow="payment" ></iframe> -
Your page listens for checkout messages from the frame. The iframe does not navigate your parent page when its state changes, so these messages are the parent UI’s completion and cancellation signal.
-
Your server verifies the durable payment outcome.
Parent-window messages
Section titled “Parent-window messages”Every message has the envelope shown in the listener below.
maxana.checkout.readymeans the checkout is loaded and ready for the buyer.maxana.checkout.completedmeans the payment was captured. Update the buyer experience, but wait for server-side verification before fulfilment.maxana.checkout.pendingmeans the payment is still processing or awaiting a final outcome. Do not fulfil the order yet.maxana.checkout.cancelledmeans the buyer cancelled the checkout. You may close the frame or offer another way to pay.maxana.checkout.errormeans the attempted payment failed. Keep the checkout available so the buyer can retry or choose another method.
Outcome messages can include paypalOrderId, amount, currency, or a
human-readable message when those values are available. Do not require an
optional field before handling the event.
Before trusting a message, compare event.origin with the origin of the
session’s returned embed_url. Also require the Maxana source value and the
session identifier you created:
type MaxanaCheckoutMessage = {
source: 'maxana.checkout';
type:
| 'maxana.checkout.ready'
| 'maxana.checkout.completed'
| 'maxana.checkout.pending'
| 'maxana.checkout.cancelled'
| 'maxana.checkout.error';
sessionId: string;
paypalOrderId?: string;
amount?: number;
currency?: string;
message?: string;
};
type CheckoutSession = {
checkout_session_id: string;
embed_url: string;
};
type CheckoutHandlers = {
ready: (message: MaxanaCheckoutMessage) => void;
completed: (message: MaxanaCheckoutMessage) => void;
pending: (message: MaxanaCheckoutMessage) => void;
cancelled: (message: MaxanaCheckoutMessage) => void;
error: (message: MaxanaCheckoutMessage) => void;
};
export function listenForCheckout(
session: CheckoutSession,
handlers: CheckoutHandlers,
): () => void {
const checkoutOrigin = new URL(session.embed_url).origin;
const receiveMessage = (event: MessageEvent) => {
if (event.origin !== checkoutOrigin) return;
if (event.data?.source !== 'maxana.checkout') return;
if (event.data?.sessionId !== session.checkout_session_id) return;
const message = event.data as MaxanaCheckoutMessage;
switch (message.type) {
case 'maxana.checkout.ready':
handlers.ready(message);
break;
case 'maxana.checkout.completed':
handlers.completed(message);
break;
case 'maxana.checkout.pending':
handlers.pending(message);
break;
case 'maxana.checkout.cancelled':
handlers.cancelled(message);
break;
case 'maxana.checkout.error':
handlers.error(message);
break;
}
};
window.addEventListener('message', receiveMessage);
return () => window.removeEventListener('message', receiveMessage);
}
Origins are exact security inputs, not display metadata. Register only pages that actually host checkout, keep production origins narrow, and test the final HTTPS origin in sandbox before launch. Do not use a wildcard to avoid managing the list.
Embedding provider-hosted fields may reduce the card data your systems touch, but it does not determine your PCI obligations. Confirm your integration and reporting scope with your PCI assessor.
Current limits
Section titled “Current limits”Embedded Checkout remains a Maxana-owned document inside an iframe. It cannot
run from an origin absent from the session’s exact allowed_origins, and a
wildcard is not accepted. Your page can size and position the frame but does
not own the checkout document’s internal markup or payment fields.