Integración iFrame
Integra FaceGuard directamente mediante un iframe para tener control total sobre el tamaño y el diseño.
La integración con iframe usa postMessage para toda la comunicación. Los eventos se envían mediante window.postMessage y se reciben a través del listener del evento message.
Móvil (pantalla completa)
<div
id="faceguard-container"
style="position: fixed; inset: 0; z-index: 9999; background: #0D141A;"
>
<iframe
src="https://faceguard.surt.com/intro?token=YOUR_PORTAL_TOKEN"
allow="camera"
style="width: 100%; height: 100%; border: none;"
></iframe>
</div>
Escritorio (modal con forma de teléfono)
<div
id="faceguard-backdrop"
style="
position: fixed; inset: 0; z-index: 9999;
background: rgba(0, 0, 0, 0.6);
display: flex; align-items: center; justify-content: center;
"
>
<div style="
width: 420px; height: 760px;
border-radius: 24px; overflow: hidden;
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.4);
">
<iframe
src="https://faceguard.surt.com/intro?token=YOUR_PORTAL_TOKEN"
allow="camera"
style="width: 100%; height: 100%; border: none;"
></iframe>
</div>
</div>
Escritorio (código QR)
Para usuarios de escritorio, usa la ruta /qrcode para mostrar un código QR que abre la verificación en su teléfono:
<iframe
src="https://faceguard.surt.com/qrcode?token=YOUR_PORTAL_TOKEN"
allow="camera"
style="width: 420px; height: 760px; border: none; border-radius: 24px;"
></iframe>
Atributos requeridos
| Atributo | Propósito |
|---|---|
allow="camera" | Concede acceso a la cámara dentro del iframe |
El atributo allow="camera" es obligatorio. Sin él, el navegador bloquea el acceso a la cámara y FaceGuard emite { action: 'close', reason: 'error', error: 'camera_insecure_context' }.
Gestión de eventos
window.addEventListener('message', (event) => {
// Verifica el origen en producción
if (event.origin !== 'https://faceguard.surt.com') return;
const data = event.data;
if (data.type === 'surt:ready') {
console.log('FaceGuard cargado');
return;
}
if (data.action === 'close') {
switch (data.reason) {
case 'approved':
console.log('Verificado', data.confidence);
break;
case 'rejected':
console.log('Fallido', data.confidence);
break;
case 'canceled':
console.log('Usuario canceló');
break;
case 'bypass_active':
console.log('Bypass activo hasta', data.bypass_expires_at);
break;
case 'no_base_photo':
console.log('Sin foto base registrada');
break;
case 'error':
// `data.error` es un código tipado — ver Códigos de error de cámara en la referencia
switch (data.error) {
case 'camera_permission_denied':
showToast('Permite el acceso a la cámara en la configuración del navegador e inténtalo de nuevo.');
break;
case 'camera_unavailable':
showToast('No se detectó cámara en este dispositivo.');
break;
case 'camera_in_use':
showToast('Tu cámara está siendo usada por otra app o pestaña.');
break;
case 'camera_insecure_context':
// Probable embed mal configurado — registrar en monitorización
console.error('FaceGuard: cámara bloqueada, verifica HTTPS y allow="camera".');
break;
default:
console.log('Error de FaceGuard:', data.error);
}
break;
}
// Eliminar iframe
document.getElementById('faceguard-container')?.remove();
}
});
Referencia de eventos
| Evento | Payload | Descripción |
|---|---|---|
| Listo | { type: 'surt:ready' } | FaceGuard está cargado y listo |
| Aprobado | { action: 'close', reason: 'approved', confidence: number } | Cara verificada (puntuación 0-100) |
| Rechazado | { action: 'close', reason: 'rejected', confidence: number } | La cara no coincidió (puntuación 0-100) |
| Cancelado | { action: 'close', reason: 'canceled' } | El usuario cerró FaceGuard |
| Bypass | { action: 'close', reason: 'bypass_active', bypass_expires_at: string } | El cliente tiene bypass activo |
| Sin foto base | { action: 'close', reason: 'no_base_photo' } | Sin foto registrada para comparar |
| Error | { action: 'close', reason: 'error', error: string } | Algo salió mal. El valor de error es un código tipado — ver Códigos de error de cámara. |
Parámetros de URL
| Parámetro | Descripción |
|---|---|
token | JWT de portal (obligatorio) |
lang | Idioma: en, es, pt, de (opcional) |
Tamaño
FaceGuard está diseñado a 375x812px y escala automáticamente.
- Móvil: viewport completo (
100vw x 100vh) - Escritorio: 420x760px recomendado con border-radius de 24px
- Mínimo: 320px de ancho
Establece background: #0D141A en el contenedor del iframe para evitar un destello blanco durante la carga.
Encabezados de seguridad
Si tu sitio usa encabezados Content Security Policy o Permissions-Policy:
frame-src https://faceguard.surt.com;
Permissions-Policy: camera=(self "https://faceguard.surt.com")