Qué es Secure Elements
Secure Elements es un SDK de JavaScript,@fluz/secure-elements, que monta un frame aislado, alojado por Fluz, directamente dentro de un elemento contenedor en tu página. El frame renderiza o recopila datos de tarjeta; tu página y tus servidores solo conservan un token opaco y de corta duración que autoriza una acción específica. Cubre dos capacidades:
- Revelado de tarjeta — mostrar a un usuario su propio PAN, fecha de expiración y CVV.
- Entrada segura de tarjeta — capturar una tarjeta física y agregarla como método de pago en su cuenta.
El mismo compromiso aplica al recopilar una tarjeta: un widget permite a Fluz capturar el PAN dentro de su propio alcance PCI, y Entrada segura de tarjeta te brinda la misma propiedad de “nunca toca tus servidores” en línea en tu propia página en lugar de un modal.
Si ya estás usando el Widget embebido para todo, no
necesitas esto. Secure Elements es para integraciones headless o impulsadas
por API que aún necesitan mostrar o recopilar detalles de tarjetas sin abrir
el modal completo del widget ni buscar
PCI_COMPLIANCE.Cómo funciona
Tu backend genera un client token
Intercambia tu token de acceso OAuth de Fluz
existente por un client token de corta duración, con alcance a un solo
revelado o a una sola adición de tarjeta.
Tu frontend monta el frame
Entrega el client token a
@fluz/secure-elements, que monta el frame
alojado por Fluz en un contenedor que proporcionas — en línea en tu página,
no un modal.El SDK informa mediante callbacks
Tu página nunca lee los datos crudos de la tarjeta. Solo ve eventos de
éxito, error o montaje.
Requisitos previos
-
Tu aplicación está registrada con Fluz. El alcance requerido en tu token de acceso depende de para cuál capacidad estás generando un client token:
-
Para un token de revelado específicamente, también necesitas un id de tarjeta virtual
ACTIVE, propiedad de la cuenta que estás revelando, para pasarlo al generarlo.
Entornos
frameHostOrigin es opcional en createCardViewer — omítelo y usará por defecto producción (https://secure.fluz.app). Pásalo explícitamente para apuntar a staging. Solo se aceptan estos dos orígenes exactos; cualquier otro lanza un FluzElementsError (error.code === "INVALID_FRAME_HOST_ORIGIN") en cuanto llamas a createCardViewer, antes de montar cualquier frame.
Cargar el SDK
@fluz/secure-elements no está publicado en npm — cárgalo como un build global de navegador (IIFE) desde el CDN de Fluz con una etiqueta <script>. Expone un global FluzSecureElements:
FluzSecureElements, como arriba.
Cada versión se publica en una ruta inmutable, fijada por versión (.../v0.1.0/index.global.js) y en una .../latest/index.global.js flotante que siempre apunta al lanzamiento más nuevo. Fija una versión específica para cualquier cosa más allá de un prototipo — latest puede cambiar sin previo aviso.
Generar un client token
Tu backend llama a esto usando el token de acceso OAuth de Fluz que ya obtienes mediante el flujo de otorgamiento OAuth estándar. Nunca envíes ese token de acceso al navegador — solo el parclientToken / loadToken que devuelve este endpoint debe llegar a tu frontend.
purpose es "reveal" (con un virtualCardId) o "tokenization" (sin virtualCardId — ver Entrada segura de tarjeta).
201. Ambos tokens son de un solo propósito y de corta duración — genera un nuevo par cada vez. clientToken es lo que autoriza el propio revelado o agregado de tarjeta (expiresIn segundos — 300 por defecto para reveal, 1800 para tokenization); loadToken tiene un alcance aún más estrecho (60 segundos) ya que viaja en una URL y se rechaza en todos lados excepto al cargar el frame. Pasa ambos directamente a createCardViewer o renderFieldsForTokenization, y nunca coloques clientToken en una URL tú mismo — el SDK ya lo evita.
Respuestas de error
Respuestas de error
| Estado | Error | Significado | | :— | :— | :— | | 400 |
invalid_purpose | falta o no es válido purpose | | 400 |
virtual_card_id_required | falta virtualCardId para un token de revelado |
| 401 | unauthorized | falta el token de acceso | | 401 |
invalid_token | el token de acceso falló la verificación (mal formado,
vencido, firma incorrecta) | | 403 | insufficient_scope | al token de
acceso le falta el alcance requerido para este purpose — ver
Requisitos previos | | 403 | app_not_registered | tu
aplicación no está registrada — contacta a Fluz | | 403 | forbidden | tarjeta
no encontrada o no es propiedad de este usuario | | 429 | rate_limited |
demasiadas solicitudes de client-token para este usuario — ver el header
Retry-After | | 500 | internal_error | error inesperado del servidor |Estilos de los campos
createCardViewer acepta un objeto style opcional, aplicado a cada campo que monta:
style se valida antes de enviar nada al frame. Si un valor no coincide con lo documentado abajo, await viewer.mount(...) rechaza con un FluzElementsError (error.code === "INVALID_STYLE") — envuelve tu llamada a mount() en un try/catch si aceptas entradas de estilo configurables tú mismo.
fontFamily debe ser una coincidencia exacta, con distinción de mayúsculas/minúsculas para una de dos listas permitidas:
- Fuentes del sistema — pilas comunes de SO/web-safe (
system-ui,-apple-system,Helvetica Neue,Arial,Georgia,Menlo, y las palabras clave genéricasmonospace/serif/sans-serif, entre otras). Estas renderizan de inmediato, sin petición de red. - Google Fonts — cualquier familia del catálogo de Google Fonts (
"Roboto","Inter","IBM Plex Mono", etc.), pasada exactamente como la lista Google. El SDK carga la fuente por ti — no necesitas una etiqueta<link>ni una regla@font-face.
Una Google Font se obtiene después de que el campo se monta, no se incluye de
antemano, por lo que hay una breve ventana en caché fría donde el campo se
renderiza con la fuente de respaldo del navegador antes de cambiar a la que
elegiste. Una fuente del sistema no tiene tal demora.
Content Security Policy
Si tu página establece una CSP, permite el host del frame al que apuntas y el host del CDN desde el que se carga el SDK:script-src; el bloque <script> inline en tu propio código de integración (como en los ejemplos de esta página y en Revelado de tarjeta y Entrada segura de tarjeta) aún necesita su propio nonce o hash si tu CSP no permite 'unsafe-inline'. Si usas un nonce, el valor en la etiqueta debe coincidir exactamente con el del header:
Modelo de seguridad
- Tu token de acceso OAuth nunca sale de tus servidores.
- El client token que tu frontend conserva es opaco y de un solo propósito — no transporta datos de tarjetas y no puede reutilizarse para una tarjeta o acción diferente.
- Los datos de tarjeta solo se pueden leer dentro de frames alojados por Fluz, aislados del propio JavaScript de tu página. Cada frame está en sandbox (
allow-scripts allow-same-origin allow-forms) conreferrerPolicy="no-referrer"— el SDK nunca coloca datos de tarjeta en el DOM fuera de ellos. - El frame solo se renderiza dentro de orígenes que hayas preregistrado con Fluz.
- Los datos de tarjeta nunca llegan a tus servidores ni al JavaScript de tu página — esta es la condición más relevante para la elegibilidad SAQ A bajo PCI DSS, junto a los demás requisitos que establece SAQ A (p. ej., no almacenar, procesar ni transmitir por tu cuenta datos del titular de la tarjeta). Tus obligaciones aplicables bajo PCI DSS dependen de todo tu entorno de datos del titular; confirma tu alcance con tu QSA.
Próximos pasos
Revelado de tarjeta
Crea el visor de tarjeta, móntalo y controla qué campos se revelan.
Entrada segura de tarjeta
Captura una tarjeta física y agrégala como método de pago.
Demos en vivo
Mira ambas capacidades ejecutándose contra staging.
Integraciones de ejemplo
Ejemplos ejecutables en HTML puro y React, ambos llamando a infraestructura
real de staging.
Aplicaciones OAuth
Cómo obtener el token de acceso que intercambiarás por un client token.