AAPD

AAPD Widget

Embebe el widget de pago para órdenes AAPD que ve el paciente — integración completa.

El widget AAPD reutiliza la misma infraestructura del widget Spot — cuando minteas un widget token con un order_token, el widget lo detecta y cambia al flujo AAPD.

Qué ve el paciente

pre_start  →  skip_user / start  →  select_isapre  →  select_insurance
       →  confirmation  →  payment_start  →  payment_capture  →  success

No controlas la secuencia de pantallas. El widget corre end-to-end y emite un WIDGET_PAYMENT_SUCCESS cuando termina.

Qué construyes

PasoQué
1. Crear ordenPOST /orders server-side — ver Crear una orden
2. Mintear widget tokenPOST /api/spot/widget con order_token (siguiente sección)
3. Renderizar iframe<iframe> desde el lado paciente (sección "Dimensiones del embed")
4. Escuchar la completitudwindow.addEventListener("message", …) (sección "Eventos postMessage")

Después de que el widget emita éxito, el resto es vía webhooks (order.changed con status = paid, seguimiento ISAPRE, eventual cobro anticipado o liquidación final). El contrato del widget (query params y eventos) está consolidado en Referencia → Parámetros del widget.

Construir la URL del widget

Después de que tu backend cree la orden y mintee el widget token, construye la URL que ve el paciente agregando el order token.

Lo que tienes

Después de las dos llamadas backend:

1. POST /orders                  →  { hash: "2f88b330-f3ed-5521-aa1f-9d15af1fce8d" }
2. POST /api/spot/widget         →  { widget_token, url: "https://spot.getskip.ai?widget_token=..." }

Lo que entregas al paciente

Agrega &order_token={order_hash} a la URL del widget:

https://spot.getskip.ai?widget_token=550e8400-...&public_key=pk_xxx&order_token=2f88b330-f3ed-5521-aa1f-9d15af1fce8d

La presencia de order_token es lo que activa el flujo AAPD dentro del widget. Sin él, el widget trata la sesión como un registro estándar de Spot.

Bootstrap del backend

async function startCnplSession(patient, totalAmountCLP) {
  // 1. Crear la orden SkipPay (server-side, credencial secreta)
  const orderRes = await fetch("https://pay.getskip.ai/orders", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SKIPPAY_CLIENT_SECRET}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      reference: `MY-ORDER-${Date.now()}`,
      total_amount: String(totalAmountCLP),
      customer: {
        rut: patient.rut,
        first_name: patient.firstName,
        last_name: patient.lastName,
        email: patient.email,
        phone_number: patient.phoneNumber,
      },
    }),
  });
  const { hash: orderToken } = await orderRes.json();

  // 2. Mintear el widget token de Spot (server-side, public_key)
  const widgetRes = await fetch(
    `https://backend.getskip.ai/api/spot/widget?public_key=${process.env.SKIP_PUBLIC_KEY}`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        rut: patient.rut,
        user_data: {
          name: patient.firstName,
          surname: patient.lastName,
          email: patient.email,
          phone_number: patient.phoneNumber,
        },
        order_token: orderToken,
      }),
    },
  );
  const { url: widgetUrl } = await widgetRes.json();

  // 3. Agregar order_token para la URL que ve el paciente
  const iframeUrl = `${widgetUrl}&order_token=${orderToken}`;

  return { iframeUrl, orderToken };
}

Devuelve iframeUrl a tu frontend — eso es lo que consume el <iframe src="...">.

Dimensiones del embed

El widget AAPD es una SPA en React renderizada como iframe. Necesita suficiente espacio vertical para formularios, pantallas de pago y vistas de confirmación.

PantallaAncho mínimoAlto recomendado
Móvil320 px820 px
Desktop480 px820 px

Embed mínimo

<iframe
  src="{iframeUrl}"
  width="480"
  height="820"
  style="border: 0; max-width: 100%;"
  allow="clipboard-read; clipboard-write"
  title="Widget AAPD de Skip"
></iframe>

Patrón modal

La mayoría de partners renderiza el widget dentro de un modal que toma toda la pantalla en móvil:

.skip-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
}

.skip-modal iframe {
  width: min(480px, 100vw);
  height: min(820px, 100vh);
}

CSP

El iframe carga desde https://spot.getskip.ai. Si tu sitio usa Content-Security-Policy, permite frame-src https://spot.getskip.ai;.

Eventos postMessage

El widget AAPD se comunica con la página padre vía postMessage estándar. Suscríbete una vez y despacha por tipo de evento. El vocabulario completo está en Referencia → Parámetros y eventos del widget.

window.addEventListener("message", (event) => {
  if (event.origin !== "https://spot.getskip.ai") return;

  switch (event.data) {
    case "WIDGET_PAYMENT_SUCCESS":
      closeIframeModal();
      showCnplConfirmation();
      break;
    case "WIDGET_FORM_CLOSE":
      closeIframeModal();
      break;
  }
});

Verifica siempre event.origin — esto es higiene estándar de postMessage. Sin ella, cualquier página embebida puede falsificar estos eventos.

WIDGET_PAYMENT_SUCCESS es la señal frontend de que el paciente terminó. La confirmación autoritativa es tu webhook server-side (order.changed con status = paid). Si tu lógica de negocio requiere "la orden está pagada con seguridad", espera el webhook antes de cumplir. Para UX (cerrar el modal, redirigir, mostrar "¡listo!"), el postMessage está perfecto.

On this page