El embedded hosted checkout permite que tu página mantenga su layout mientras COPE renderiza el formulario de pago en un iFrame. Tu sitio posee la experiencia envolvente. COPE posee la ruta de checkout, el cobro, la finalización de impuestos, la creación de pedidos y todos los estados terminales del comprador.
Usa embedded checkout cuando necesitas un storefront personalizado o un modal de checkout in-page. Usa redirect checkout cuando la integración más simple es suficiente o cuando un navegador bloquea el flujo del iFrame.
📄 Documentación completa: [Embedded hosted checkout - COPE]
Requisitos
Antes de crear sesiones de embedded checkout:
Crear una clave publicable para el negocio en COPE
Registrar cada origin de página padre que vaya a alojar el iFrame (p. ej.
https://shop.example.com)Usar solo el origin: esquema, host y puerto opcional – sin ruta, query string ni fragmento
Solo HTTPS en producción (
http://localhostsolo para desarrollo)Configurar URLs de success y cancel permitidas para completion por redirect o fallback
El origin padre debe coincidir exactamente con el origin del navegador de la página que llama a checkout({ embed_origin }). https://shop.example.com y https://www.shop.example.com son origins distintos.
Integración
ts
import { CopeCart } from "@copecart/sdk" const cope = new CopeCart({ publishableKey: "cope_pk_live_...", }) async function openEmbeddedCheckout(productId: string, planId: number) { const cart = await cope.createCart({ currency: "EUR" }) await cope.addLine(cart.id, { product_id: productId, plan_id: planId, }) await cope.setBuyerIdentity(cart.id, { email: "buyer@example.com", tax_location: { country: "DE", postal_code: "10115" }, }) await cope.reprice(cart.id) const checkout = await cope.checkout(cart.id, { embed_origin: window.location.origin, success_url: "https://shop.example.com/thank-you", cancel_url: "https://shop.example.com/cart", consents: [{ type: "buyer_tos" }], }) return cope.mountCheckout("#cope-checkout-frame", checkout, { fallback: "redirect", onReady: () => showCheckoutFrame(), onResize: ({ height }) => resizeContainer(height), onSuccess: () => showOrderConfirmation(), onCancel: () => closeCheckoutFrame(), onError: ({ code, retryable }) => reportCheckoutError(code, retryable), }) }La respuesta de checkout incluye ambas formas de URL:
Campo | Significado |
| Ruta de redirect, p. ej. |
| Ruta de iFrame, p. ej. |
| Origin padre aprobado devuelto por COPE |
mountCheckout() rechaza el mount si checkout.embedOrigin falta o no coincide exactamente con window.location.origin.
Comportamiento del mount
mountCheckout() crea el iFrame automáticamente:
src→checkout.embedCheckoutUrltitle→COPE checkoutallow→payment *para soporte de wallets del navegadorreferrerPolicy→no-referrerwidth→100%min-height→720pxSin atributo
sandbox
No construyas el iFrame manualmente – el SDK también realiza el trusted mount handshake y filtra todos los mensajes del iFrame por origin, source window, message source y versión.
Fallback
Usa fallback: "redirect" para recuperación segura si el iFrame no completa el trusted ready handshake antes de readyTimeoutMs:
ts
cope.mountCheckout("#cope-checkout-frame", checkout, { fallback: "redirect", readyTimeoutMs: 8000, onFallbackRedirect: () => { console.log("Cayendo a hosted checkout") }, })Con el fallback: "error" por defecto, el SDK llama a:
ts
onError({ code: "load_failed", retryable: true })Eventos
El iFrame envía eventos saneados al SDK. Los payloads de los callbacks no incluyen credenciales de checkout, payment client secrets ni PII del comprador.
Evento | Significado |
| iFrame cargado y listo |
| Pago completado con éxito |
| Usuario canceló |
| Error en el proceso de pago (incl. flag |
| Altura del iFrame ha cambiado |
Para el stream de eventos saneados en bruto:
ts
cope.mountCheckout("#cope-checkout-frame", checkout, { onMessage: (event) => { analytics.track("cope_checkout_embed_event", event) }, })Modelo de seguridad
Embedded checkout tiene dos capas de autorización:
COPE valida
embed_origincontra la allowlist del negocio al crear la sesión de checkoutLa ruta del iFrame valida el mismo contrato de embed antes de renderizar el formulario de pago
El SDK envía el mensaje de mount con un targetOrigin específico – nunca *. Los mensajes del iFrame solo se aceptan cuando event.origin, event.source, event.data.source (cope.checkout) y event.data.version (1) coinciden todos.
Casos de uso
Modal de checkout in-page
El formulario de pago se abre como overlay dentro de tu página. Sin redirect, sin pérdida de contexto – el usuario permanece en tu navegación y layout durante todo el checkout.
Flujo de upgrade SaaS
Un usuario hace upgrade de free a pro directamente en el dashboard. mountCheckout() renderiza el formulario de pago como iFrame en un modal o sección dedicada, sin perder el estado actual.
Storefront personalizado
Construyes una página de producto completamente propia con tu branding – COPE solo renderiza el formulario de pago dentro del iFrame. Tu página mantiene control total sobre layout, colores y experiencia de usuario.
Checkout de alta conversión
Cada redirect es un punto de abandono potencial. Embedded checkout elimina esa fricción y mantiene al usuario en tu página hasta el pago exitoso.
Troubleshooting
Error | Causa probable | Solución |
| Origin no registrado | Registrar el origin exacto, crear nueva sesión |
|
| Pasar |
| Sesión creada para otro origin | Llamar |
iFrame nunca listo | Token expirado, bloqueado o handshake fallido | Usar |
Wallet del navegador no disponible | Registro de dominio de wallet incompleto | Verificar |

