Pular para o conteúdo

Assinatura integrada

<bf-signing> apresenta a página de assinatura da Bona Fide num iframe isolado (sandbox) dentro da sua página, ajusta o tamanho ao documento e comunica o que o signatário faz através de eventos DOM. Não depende de nenhuma framework; inclui wrappers leves para React e Vue.

  1. Crie o envelope com delivery: "embedded", para que os destinatários não recebam e-mails.

  2. Crie uma sessão no seu servidor quando o signatário abrir a página, com a origem do seu site em allowedOrigins. A página integrada recusa-se a comunicar com qualquer página principal que não conste dessa 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. Apresente o elemento com o 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 no seu servidor. Trate o evento do navegador como um sinal para a interface e baseie-se no webhook envelope.completed (ou em GET /v1/envelopes/{id}) para conhecer o resultado.

Atributo (prop de React / Vue) Predefinição Notas
session O token bfs_…. Alterá-lo volta a carregar a moldura
base-url (baseUrl) https://sign.bonafidesign.com/s/ A rota de assinatura alojada da implementação
theme auto auto, light ou dark
locale Transmitido à página de assinatura
min-height, max-height (minHeight, maxHeight) 480, 90vh Píxeis ou vh. A moldura cresce com o documento entre os dois valores e depois desloca-se internamente
timeout 30000 Milissegundos de espera pela página antes de um error com o código load_timeout
frame-title Document signing O título acessível do iframe

O elemento tem também um método reload(), por exemplo para utilizar depois de criar uma nova sessão.

Os eventos propagam-se (bubble), atravessam shadow roots e transportam o payload em event.detail. bf-event é disparado para todos eles.

Evento detail
ready { type: 'ready' }: a página de assinatura foi carregada
field_completed { type, field }: foi preenchido um campo
signed { type, recipient }: este destinatário submeteu
completed { type, envelope }: o envelope está concluído
declined { type, reason? }
session_expiring { type, expiresAt }: crie uma nova sessão em breve
error { type, code, message }, incluindo load_timeout e invalid_base_url

As props de React são onReady, onFieldCompleted, onSigned, onCompleted, onDeclined, onSessionExpiring, onError e onEvent; o Vue emite os nomes dos eventos (@completed, @session_expiring, …) e event.

  • O token viaja no fragmento do URL do iframe (#session=…), que nunca chega a um servidor nem a um cabeçalho Referer. A página de assinatura lê-o, remove-o do URL e do histórico e troca-o por um token de acesso mantido em memória. Não são utilizados cookies.
  • O iframe é isolado (allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads) com referrerpolicy="strict-origin".
  • A sua página só aceita uma mensagem quando esta vem do próprio iframe do elemento e da origem de base-url e é interpretada como uma mensagem bona-fide.embed/1 com espaço de nomes. Tudo o resto é ignorado.
  • A página de assinatura envia mensagens para a sua origem exata (nunca *), e apenas se essa origem constar das allowedOrigins da sessão. A API também recusa chamadas de uma sessão integrada provenientes de origens não permitidas.