Transporte postMessage para el Widget
¿Qué es?
Una segunda opción para entregar la configuración al checkout en modo widget. En lugar de enviar todos los parámetros en la URL del iframe — donde quedan expuestos en logs, historial del navegador y herramientas de red — la configuración se inyecta después de que el checkout carga, usando el mecanismo nativo del navegador postMessage. Esto evita que datos sensibles (como tokens cifrados) viajen visibles en la barra de direcciones.
¿Cuándo lo necesito?
Si tu integración con el widget cifra los campos de referencia de PSE usando JWE (por ejemplo, para cumplir con controles antifraude), los tokens cifrados con RSA generan ~790 bytes cada uno. Con tres referencias cifradas, la URL puede superar los límites seguros de longitud (~2,048 bytes) y el checkout podría no cargar correctamente.
Síntoma: El iframe del widget se queda en blanco o muestra un error al usar paymentMethod.referenceOne/Two/Three con valores JWE largos.
Si tus campos de referencia son cortos (texto plano), probablemente no necesitas este transporte. Tu integración actual funciona sin cambios. Sin embargo, puedes activarlo preventivamente para que tus parámetros no queden expuestos en la URL.
¿Cómo se activa?
Agrega una sola línea a tu configuración del widget:
const checkout = new WidgetCheckout({
currency: 'COP',
amountInCents: 2449600,
reference: 'TU-REFERENCIA',
publicKey: 'pub_prod_XXXXXXXXXX',
signature: { integrity: 'tu-hash-de-integridad' },
paymentMethod: {
referenceOne: '<TOKEN-JWE-CIFRADO>',
referenceTwo: '<TOKEN-JWE-CIFRADO>',
referenceThree: '<TOKEN-JWE-CIFRADO>'
},
bootstrapTransport: 'postmessage' // ← esta línea
})
Valores posibles
| Valor | Comportamiento |
|---|---|
| No declarado (por defecto) | Todo funciona exactamente como hoy. La configuración viaja en la URL. |
'query' | Igual que no declarar nada. Transporte por URL, comportamiento actual. |
'postmessage' | La URL del iframe es mínima (~90 bytes). La configuración se entrega por postMessage al checkout ya cargado. |
¿Qué cambia para el usuario final?
Nada. La experiencia de pago es idéntica. El checkout se comporta exactamente igual: muestra el loader, valida los parámetros, muestra los métodos de pago, procesa la transacción y devuelve el resultado al comercio.
La única diferencia es interna: cómo viajan los datos entre tu página y el checkout.
¿Qué cambia para mi integración?
| Aspecto | Sin bootstrapTransport | Con bootstrapTransport: 'postmessage' |
|---|---|---|
| Configuración del widget | Sin cambios | Agregar una línea |
| Callback de resultado | Sin cambios | Sin cambios |
Firma de integridad (signature) | Sin cambios | Sin cambios |
| Métodos de pago disponibles | Sin cambios | Sin cambios |
| Verificación de transacción en backend | Sin cambios | Sin cambios |
| URL del iframe | Contiene toda la config (~2,800+ bytes con JWE) | Mínima (~90 bytes): solo mode, bootstrap y un nonce |
Compatibilidad
- Navegadores: Todos los que soportan
crypto.getRandomValues(Chrome 11+, Firefox 21+, Safari 6.1+, Edge 12+, IE 11). Si el navegador no lo soporta, el widget degrada automáticamente al transporte por URL y registra un warning en consola. - Versiones del widget: Solo disponible a partir de la versión que incluye este cambio. Versiones anteriores del script
widget.jsignoran el campobootstrapTransport. - Coexistencia: Los dos transportes son permanentes. No hay plan de retirar el transporte por URL.
Seguridad
| Protección | Descripción |
|---|---|
| Nonce criptográfico | Cada apertura del widget genera un nonce único de 128 bits. Solo se acepta la configuración que incluya el nonce correcto. |
| Validación de origen | El checkout solo acepta la configuración del window padre (tu página). Mensajes de otros orígenes se ignoran. |
| Un solo uso | Una vez que el checkout recibe la configuración, ignora cualquier mensaje posterior. No es posible inyectar datos a mitad de flujo. |
| Timeout | Si la configuración no llega en 8 segundos, el checkout muestra un error. No se queda cargando indefinidamente. |
| Origin explícito | El widget envía la configuración solo al origin del checkout (nunca a '*'). Tus tokens JWE no se exponen a otros orígenes. |
Ejemplo completo
<script src="https://checkout.wompi.co/widget.js"></script>
<script>
const checkout = new WidgetCheckout({
currency: 'COP',
amountInCents: 5000000,
reference: 'ORDER-PSE-2024-001',
publicKey: 'pub_prod_XXXXXXXXXX',
redirectUrl: 'https://mitienda.com/resultado',
signature: {
integrity: 'a1b2c3d4e5f6...'
},
paymentMethod: {
referenceOne: 'eyJhbGciOiJSU0EtT0FFUC0yNTYi...', // JWE cifrado
referenceTwo: 'eyJhbGciOiJSU0EtT0FFUC0yNTYi...',
referenceThree: 'eyJhbGciOiJSU0EtT0FFUC0yNTYi...'
},
bootstrapTransport: 'postmessage'
})
checkout.open(function (result) {
const transaction = result.transaction
console.log('Estado:', transaction.status)
// Verificar la transacción en tu backend con transaction.id
})
</script>
Preguntas frecuentes
¿Puedo usar bootstrapTransport: 'postmessage' sin cifrar las referencias?
Sí. Funciona con cualquier configuración, no solo con JWE. Si tu query string es corto no lo necesitas, pero no hay problema en usarlo siempre.
¿Funciona con el modo de tokenización?
Sí. Ambos modos (compra y tokenización) funcionan con ambos transportes.
¿Afecta la verificación de firma (signature.integrity)?
No. La firma se calcula sobre los mismos campos de siempre. El transporte no modifica los datos, solo cómo llegan al checkout.
¿Qué pasa si uso una versión vieja del widget.js?
El campo bootstrapTransport se ignora silenciosamente. El widget sigue funcionando con el transporte por URL. No hay error ni ruptura.
¿El endpoint del backend recibe datos diferentes?
No. El formato de datos que se persiste es idéntico independientemente del transporte. Los flujos de transacción (PSE, BNPL, etc.) funcionan sin cambios.
Diagrama de flujo
Notas técnicas
- El timeout de 8 segundos es fijo y no configurable por el comercio.
- Si
crypto.getRandomValuesno está disponible (navegadores muy antiguos), el widget degrada automáticamente al transporte por URL y registra un warning en consola. - El campo
bootstrapTransportno se incluye en los datos que se persisten. Es metadata de transporte, no de la transacción.