Ir al contenido

Firma integrada

<bf-signing> muestra la página de firma de Bona Fide en un iframe aislado dentro de su página, ajusta su tamaño al del documento y comunica lo que hace el firmante mediante eventos del DOM. No depende de ningún framework e incluye wrappers ligeros para React y Vue.

  1. Cree el sobre con delivery: "embedded", para que no se envíen correos a los destinatarios.

  2. Genere una sesión en su servidor cuando el firmante abra la página, con el origen de su sitio en allowedOrigins. La página integrada se niega a comunicarse con cualquier página contenedora que no figure en esa lista.

    // Your backend (never expose the API key to the browser)
    const res = await fetch(`https://api.bonafidesign.com/v1/envelopes/${envelopeId}/sessions`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${process.env.BONA_FIDE_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ recipient: recipientId, mode: 'embedded', allowedOrigins: ['https://app.example.com'] }),
    });
    const { token } = await res.json(); // 'bfs_…', single-use, 10 minutes by default
  3. Renderice el elemento con el token.

    <script type="module" src="https://js.bonafidesign.com/v1"></script>
    <bf-signing session="bfs_…" theme="auto" min-height="480" max-height="90vh"></bf-signing>
    <script>
    const el = document.querySelector('bf-signing');
    el.addEventListener('completed', (e) => {
    // e.detail = { type: 'completed', envelope: 'env_…' }
    window.location.href = '/onboarding/next';
    });
    el.addEventListener('session_expiring', () => refreshSession());
    el.addEventListener('error', (e) => console.error(e.detail.code, e.detail.message));
    </script>
  4. Confírmelo en su servidor. Trate el evento del navegador como una señal para la interfaz y básese en el webhook envelope.completed (o en GET /v1/envelopes/{id}) para conocer el resultado.

Atributo (prop de React / Vue) Valor predeterminado Notas
session El token bfs_…. Al cambiarlo, se vuelve a cargar el marco
base-url (baseUrl) https://sign.bonafidesign.com/s/ La ruta de firma alojada del despliegue
theme auto auto, light o dark
locale Se pasa a la página de firma
min-height, max-height (minHeight, maxHeight) 480, 90vh Píxeles o vh. El marco crece con el documento entre ambos valores y, a partir de ahí, se desplaza por dentro
timeout 30000 Milisegundos de espera a la página antes de un error con el código load_timeout
frame-title Document signing El título accesible del iframe

El elemento también tiene un método reload(), por ejemplo, para después de generar una sesión nueva.

Los eventos se propagan hacia arriba, atraviesan los shadow roots y llevan la carga en event.detail. bf-event se dispara para todos ellos.

Evento detail
ready { type: 'ready' }: se ha cargado la página de firma
field_completed { type, field }: se ha rellenado un campo
signed { type, recipient }: este destinatario ha enviado su firma
completed { type, envelope }: el sobre está completo
declined { type, reason? }
session_expiring { type, expiresAt }: genere una sesión nueva en breve
error { type, code, message }, incluidos load_timeout e invalid_base_url

Las props de React son onReady, onFieldCompleted, onSigned, onCompleted, onDeclined, onSessionExpiring, onError y onEvent; Vue emite los nombres de los eventos (@completed, @session_expiring, …) y event.

  • El token viaja en el fragmento de la URL del iframe (#session=…), que nunca llega a ningún servidor ni a una cabecera Referer. La página de firma lo lee, lo elimina de la URL y del historial y lo canjea por un token de acceso en memoria. No se utilizan cookies.
  • El iframe se ejecuta en un sandbox (allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads) con referrerpolicy="strict-origin".
  • Su página solo acepta un mensaje cuando procede del propio iframe del elemento, y del origen de base-url, y se interpreta como un mensaje bona-fide.embed/1 con su espacio de nombres. Todo lo demás se ignora.
  • La página de firma envía los mensajes a su origen exacto (nunca a *), y solo si ese origen figura en los allowedOrigins de la sesión. La API también rechaza las llamadas de una sesión integrada procedentes de orígenes no permitidos.