Ir al contenido

Firma integrada

<bf-signing> renderiza la página de firma de Bona Fide en un iframe aislado dentro de su página, ajusta su tamaño al documento e informa lo que hace el firmante mediante eventos del DOM. No depende de ningún framework; 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 principal que no figure ahí.

    // 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. Confirme en su servidor. Trate el evento del navegador como una señal para la interfaz y use el webhook envelope.completed (o GET /v1/envelopes/{id}) para conocer el resultado.

Atributo (prop de React / Vue) Predeterminado Notas
session El token bfs_…. Si cambia, se vuelve a cargar el marco
base-url (baseUrl) https://sign.bonafidesign.com/s/ La ruta de firma alojada de la implementación
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 luego se desplaza por dentro
timeout 30000 Milisegundos que se 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 usarlo después de generar una sesión nueva.

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

Evento detail
ready { type: 'ready' }: la página de firma se cargó
field_completed { type, field }: se completó un campo
signed { type, recipient }: este destinatario envió su firma
completed { type, envelope }: el sobre está completo
declined { type, reason? }
session_expiring { type, expiresAt }: genere pronto una sesión nueva
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 un servidor ni a un encabezado Referer. La página de firma lo lee, lo elimina de la URL y del historial, y lo intercambia por un token de acceso en memoria. No se usan cookies.
  • El iframe está aislado con sandbox (allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads) y usa referrerpolicy="strict-origin".
  • Su página acepta un mensaje solo cuando proviene del propio iframe del elemento, y del origen de base-url, y se analiza como un mensaje bona-fide.embed/1 con espacio de nombres. Todo lo demás se ignora.
  • La página de firma envía 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 desde orígenes no permitidos.