Hosted Checkout

Embeber el checkout

Carga el checkout en un iframe en tu página y sigue el pago con eventos postMessage.

Cada sesión tiene una url de checkout. Puedes redirigir al cliente a ella, o embeberla en un iframe en tu propia página y recibir eventos conforme el cliente avanza en el pago.

Alojado (redirección)Embebido (iframe)
checkout_typehosted (por defecto)embedded
Dónde paga el clienteEn la página de TonderDentro de tu página
Cómo lo siguesURLs de redirección + webhooksEventos postMessage + webhooks

El dominio de tu sitio debe estar habilitado para embeber en cada entorno. Pide a soporte de Tonder que lo agregue antes de probar, y dale solo el origen — esquema y dominio, por ejemplo https://shop.example.com, nunca una ruta. Una entrada que incluye una ruta nunca coincide, y el iframe se queda en blanco en todas las páginas de tu sitio sin ningún error en la pestaña de red ni en la consola.

Paso a paso

Crea la sesión con checkout_type: "embedded" y post_message_enabled: true. Agrega redirect_on_completion: "never" si quieres que tu página, y no el checkout, decida a dónde va el cliente al final.

{
  "customer": { "first_name": "Ana", "last_name": "Garcia", "email": "ana@example.com" },
  "amount_total": 100.00,
  "currency": "MXN",
  "line_items": [{ "name": "Deposit", "quantity": 1, "unit_price": 100.00 }],
  "payment_method_types": ["card", "spei"],
  "external_id": "ORD-001",
  "return_url": "https://your-store.com/checkout/complete",
  "checkout_type": "embedded",
  "post_message_enabled": true,
  "redirect_on_completion": "never"
}

Acepta mensajes únicamente del origen del checkout de tu entorno: https://stage-payflow.tonder.io (Sandbox) o https://payflow.tonder.io (Producción).

Usa la url de la respuesta de la sesión como el src del iframe.

Los eventos le dicen a tu página qué mostrar. Confirma el pago en sí desde tu backend, con webhooks o Consultar una sesión.

Eventos

EventoCuándotransaction_statussession_status
checkout.initiatedEl checkout terminó de cargar—pending
checkout.redirectedEl cliente va a un voucher o a una página de pago externaPendingpending
checkout.returnedEl cliente regresa de esa páginavaríavaría
checkout.failedUn intento falló; el cliente puede reintentar (puede repetirse)Failed, Declinedpending
checkout.completedEl pago o el guardado de la tarjeta fue exitoso (se envía una sola vez)Successcompleted

Campos del evento

CampoDescripción
eventNombre del evento.
session_typepayment o enrollment.
payment_idEl pago (no está presente en sesiones de registro de tarjeta).
direct_transaction_idSolo en cuentas de API Direct: el intento más reciente (no está presente antes del primer intento).
external_idTu referencia del pedido.
transaction_status, session_statusEstados actuales.
payment_methodMétodo usado, p. ej. card, oxxopay.
{
  "event": "checkout.completed",
  "session_type": "payment",
  "payment_id": 41528,
  "external_id": "ORD-001",
  "transaction_status": "Success",
  "session_status": "completed",
  "payment_method": "card"
}

Página de ejemplo

<!DOCTYPE html>
<html>
<body>
  <div id="status"></div>
  <script>
    window.addEventListener('message', function (event) {
      const allowedOrigins = ['https://payflow.tonder.io', 'https://stage-payflow.tonder.io'];
      if (!allowedOrigins.includes(event.origin)) return;
      const data = event.data;
      switch (data.event) {
        case 'checkout.initiated':
          document.getElementById('status').textContent = 'Listo para pagar';
          break;
        case 'checkout.completed':
          window.location.href = data.session_type === 'enrollment'
            ? '/card-saved'
            : '/success?payment=' + data.payment_id;
          break;
        case 'checkout.failed':
          document.getElementById('status').textContent =
            'El pago falló: ' + data.transaction_status + '. Inténtalo de nuevo.';
          break;
        case 'checkout.redirected':
          document.getElementById('status').textContent =
            'Redirigiendo a ' + data.payment_method + '...';
          break;
        case 'checkout.returned':
          if (data.transaction_status === 'Success') {
            window.location.href = '/success?payment=' + data.payment_id;
          }
          break;
      }
    });
  </script>
  <iframe id="checkout-iframe" src="SESSION_URL" style="width: 100%; height: 600px; border: none;"></iframe>
</body>
</html>

Nunca entregues un pedido basándote solo en un evento del navegador. Un mensaje en la página puede falsificarse; el webhook o una consulta de la sesión desde tu servidor es la fuente de verdad.

Solución de problemas

SíntomaCausaSolución
El iframe se queda en blanco, sin error en la consola ni en la pestaña de redTu dominio no está habilitado para embeber en este entorno, o se registró con una rutaPide a soporte de Tonder que habilite solo el origen (por ejemplo https://shop.example.com) en el entorno donde estás probando
No llegan eventos a tu páginaLa sesión no se creó con checkout_type: "embedded" y post_message_enabled: true, o tu listener valida un origen distintoVuelve a crear la sesión con ambos campos y acepta https://stage-payflow.tonder.io (Sandbox) o https://payflow.tonder.io (Producción)

Siguientes pasos

¿Te resultó útil esta página?

En esta página