> ## Documentation Index
> Fetch the complete documentation index at: https://devs.tapipay.la/llms.txt
> Use this file to discover all available pages before exploring further.

# Eventos postMessage

> El protocolo crudo del iframe embebido, para integrar sin el SDK.

El iframe embebido avisa lo que va pasando adentro con mensajes `postMessage` al window que lo contiene:

```js theme={null}
window.parent.postMessage({ type: "TAPIPAY_DOMICILIATION_BANK_SELECTED", payload }, "*");
```

El [SDK](/es/portal-de-pagos/sdk-adhesiones) no hace nada mágico con eso: escucha esos mismos mensajes y los re-emite con nombres más cómodos. Esta página documenta la capa de abajo, para cuando montas el iframe a mano.

<Tip>
  Si puedes usar el SDK, úsalo: te ahorra el listener, la validación de origen y el alto del iframe. Esta página es para cuando no puedes instalar un paquete, o ya tienes tu propio iframe montado.
</Tip>

## Montar la vista a mano

El widget tiene dos vistas y cada una emite su propio conjunto de mensajes. Son las mismas que monta el SDK, y la URL las distingue: la de domiciliación termina en `/autopay`.

<CodeGroup>
  ```html Domiciliación theme={null}
  <iframe
    src="https://app.tapipay.la/s/acme-corp/embed/CLI-00042/autopay"
    width="100%"
    height="700"
    style="border: none;"
    allow="payment"
    title="Domiciliación"
  ></iframe>
  ```

  ```html Medios de pago theme={null}
  <iframe
    src="https://app.tapipay.la/s/acme-corp/embed/CLI-00042"
    width="100%"
    height="700"
    style="border: none;"
    allow="payment"
    title="Medios de pago"
  ></iframe>
  ```
</CodeGroup>

Puedes identificar tu empresa por `companyCode` en lugar del alias:

```text theme={null}
https://app.tapipay.la/c/MX-S-12345/embed/CLI-00042/autopay
```

<Note>
  Esto es distinto de [embeber el portal completo](/es/portal-de-pagos/embeber-portal), que muestra la lista de deudas. Aquí montas solo el widget.
</Note>

## Escuchar los mensajes

```js theme={null}
window.addEventListener("message", function (event) {
  // 1. Valida el origen antes de leer nada
  if (event.origin !== "https://app.tapipay.la") return;

  // 2. Enruta por el tipo de mensaje
  switch (event.data?.type) {
    case "TAPIPAY_DOMICILIATION_BANK_SELECTED":
      console.log("Banco elegido:", event.data.payload.name);
      break;
    case "TAPIPAY_DOMICILIATION_CONFIRMED":
      mostrarPantallaProcesando();
      break;
    case "TAPIPAY_AUTOPAY_ACTIVATED":
      mostrarExito(event.data.payload.lastFour);
      break;
    case "TAPIPAY_DOMICILIATION_ACCOUNT_CHECK_FAILED":
      registrar(event.data.payload.reason);
      break;
  }
});
```

<Warning>
  **Valida siempre `event.origin`.** Los mensajes se emiten con `targetOrigin: "*"`, así que tu listener recibe también lo que mande cualquier otro iframe o script de tu página. Sin ese chequeo, cualquiera puede simular un evento de TapiPay desde el navegador del usuario.
</Warning>

En homologación el origen es `https://homo.tapipay.la`.

<Warning>
  **La forma del dato no es la misma que en el SDK.** El mensaje crudo es `{ type, payload }`: el contenido viaja **adentro de `payload`**. El SDK te entrega ese `payload` desenvuelto al handler, pero aquí tienes que leer `event.data.payload`.
</Warning>

## Señales de ciclo de vida

Las dos vistas emiten estas tres señales mientras corren dentro de un iframe, sin importar lo que haga tu usuario.

| Mensaje            | Cuándo llega                                           | Datos                |
| ------------------ | ------------------------------------------------------ | -------------------- |
| `TAPIPAY_JS_READY` | El widget terminó de montarse y ya puede mostrarse.    | Ninguno              |
| `TAPIPAY_READY`    | Los datos cargaron y la pantalla real es visible.      | Ninguno              |
| `TAPIPAY_RESIZE`   | Al montar y cada vez que cambia el alto del contenido. | `height`, en píxeles |

<Warning>
  `TAPIPAY_RESIZE` es la excepción a la regla del `payload`: el alto viaja en la raíz del mensaje, en `event.data.height`.
</Warning>

Ninguna tiene evento equivalente en el SDK, porque el SDK las resuelve por dentro: usa `TAPIPAY_JS_READY` para quitar su pantalla de carga y `TAPIPAY_RESIZE` para ajustar el alto del iframe. Si lo montas a mano, eso corre por tu cuenta.

```js theme={null}
const frame = document.querySelector("#tapipay");

window.addEventListener("message", function (event) {
  if (event.origin !== "https://app.tapipay.la") return;

  switch (event.data?.type) {
    case "TAPIPAY_JS_READY":
      ocultarPantallaDeCarga();
      break;
    case "TAPIPAY_RESIZE":
      frame.style.height = event.data.height + "px";
      break;
  }
});
```

## Los mensajes

Cada mensaje tiene su evento equivalente en el SDK. El `payload` es idéntico en los dos casos, con los mismos nombres de campo.

### Alta de domiciliación

Un mensaje por cada paso que tu usuario completa en el alta. Los primeros cuatro llegan una vez cada uno, en orden.

| Mensaje                                        | Evento del SDK                       |
| ---------------------------------------------- | ------------------------------------ |
| `TAPIPAY_DOMICILIATION_BANK_SELECTED`          | `domiciliationBankSelected`          |
| `TAPIPAY_DOMICILIATION_FORM_COMPLETED`         | `domiciliationFormCompleted`         |
| `TAPIPAY_DOMICILIATION_VERIFICATION_COMPLETED` | `domiciliationVerificationCompleted` |
| `TAPIPAY_DOMICILIATION_CONFIRMED`              | `domiciliationConfirmed`             |
| `TAPIPAY_DOMICILIATION_ACCOUNT_CHECK_FAILED`   | `domiciliationAccountCheckFailed`    |

<Warning>
  `TAPIPAY_DOMICILIATION_CONFIRMED` significa que tu usuario **apretó confirmar**, no que la adhesión quedó activa. El backend la procesa de forma asíncrona. La confirmación real es `TAPIPAY_AUTOPAY_ACTIVATED`.
</Warning>

### Gestión de adhesiones

| Mensaje                     | Evento del SDK     |
| --------------------------- | ------------------ |
| `TAPIPAY_AUTOPAY_LOADED`    | `autopayLoaded`    |
| `TAPIPAY_AUTOPAY_ACTIVATED` | `autopayActivated` |
| `TAPIPAY_AUTOPAY_REMOVED`   | `autopayRemoved`   |
| `TAPIPAY_AUTOPAY_ERROR`     | `autopayError`     |

### Pago con tarjeta

Salen de la **vista de medios de pago**, cuando tu usuario paga con tarjeta desde el widget.

| Mensaje                         | Evento del SDK        |
| ------------------------------- | --------------------- |
| `TAPIPAY_PAYMENT_WINDOW_OPENED` | `paymentWindowOpened` |
| `TAPIPAY_PAYMENT_SUBMITTED`     | `paymentSubmitted`    |
| `TAPIPAY_PAYMENT_CANCELLED`     | `paymentCancelled`    |

`TAPIPAY_PAYMENT_WINDOW_OPENED` y `TAPIPAY_PAYMENT_CANCELLED` llegan sin datos: avisan que se abrió la ventana de pago y que tu usuario la cerró sin terminar.

<Warning>
  `TAPIPAY_PAYMENT_SUBMITTED` significa **enviado, no acreditado**. Nunca des una deuda por pagada con este mensaje: el estado real llega por la [notificación de pago](/es/webhooks/notificacion-de-pago) a tu backend.
</Warning>

<CardGroup cols={2}>
  <Card title="Payloads de domiciliación" icon="code" href="/es/portal-de-pagos/sdk-adhesiones#eventos">
    Los campos de los mensajes de domiciliación y de gestión de adhesiones, con sus tipos.
  </Card>

  <Card title="Payloads de pago" icon="credit-card" href="/es/portal-de-pagos/sdk-medios-de-pago#eventos">
    Los campos de los mensajes de pago con tarjeta, con sus tipos.
  </Card>
</CardGroup>
