跳转到内容

嵌入式签署

<bf-signing> 会在您的页面中以沙盒 iframe 渲染 Bona Fide 的签署页面,根据文档调整其尺寸,并以 DOM 事件的形式报告签署人的操作。它不依赖任何框架;同时附带轻量的 React 和 Vue 封装。

  1. 使用 delivery: "embedded" 创建信封,这样就不会向收件人发送电子邮件。

  2. 在签署人打开页面时,在您的服务器上签发会话,并将您网站的源加入 allowedOrigins。嵌入的页面会拒绝与任何未列出的父页面通信。

    // 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. 使用令牌渲染该元素。

    <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. 在您的服务器上确认结果。 请把浏览器事件仅视为界面信号,并以 envelope.completed Webhook(或 GET /v1/envelopes/{id})作为最终结果的依据。

属性(React / Vue prop) 默认值 说明
session bfs_… 令牌。更改后会重新加载框架
base-url(baseUrl) https://sign.bonafidesign.com/s/ 该部署的托管签署路由
theme auto auto、light 或 dark
locale 传递给签署页面
min-height、max-height(minHeight、maxHeight) 480、90vh 像素或 vh。框架在两者之间随文档增高,超出后在内部滚动
timeout 30000 等待页面加载的毫秒数,超时后触发代码为 load_timeout 的 error
frame-title Document signing iframe 的无障碍标题

该元素还有一个 reload() 方法,例如可在签发新会话后调用。

事件会冒泡、穿越 Shadow Root,并在 event.detail 中携带负载。bf-event 会针对所有事件触发。

事件 detail
ready { type: 'ready' }:签署页面已加载
field_completed { type, field }:某个字段已填写
signed { type, recipient }:该收件人已提交
completed { type, envelope }:信封已完成
declined { type, reason? }
session_expiring { type, expiresAt }:请尽快签发新会话
error { type, code, message },包括 load_timeout 和 invalid_base_url

React 的 prop 为 onReady、onFieldCompleted、onSigned、onCompleted、onDeclined、onSessionExpiring、onError 和 onEvent;Vue 则发出与事件同名的事件(@completed、@session_expiring 等)以及 event。

  • 令牌通过 iframe 的 URL 片段(#session=…)传递,片段永远不会到达服务器,也不会出现在 Referer 请求头中。签署页面读取令牌后,会将其从 URL 和历史记录中移除,并换取一个保存在内存中的访问令牌。不使用任何 Cookie。
  • 该 iframe 处于沙盒中(allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads),并设置了 referrerpolicy="strict-origin"。
  • 只有当消息来自该元素自己的 iframe,并且来自 base-url 的源,并且能解析为带命名空间的 bona-fide.embed/1 消息时,您的页面才会接受它。其他一切消息都会被忽略。
  • 签署页面只向您的确切源发送消息(绝不使用 *),而且仅当该源位于会话的 allowedOrigins 中时才会发送。API 也会拒绝嵌入式会话来自未获允许的源的调用。