署名が必要なプロダクトの多くは、ユーザーをどこか別の場所へ送り出して署名してもらいます。メールが届き、リンクを開くとあなたのプロダクトとは似ても似つかないページが表示され、ユーザーはそこで署名してから元の場所に戻る道を探し、あなたのシステムは誰かが確認して初めて何かが起きたことを知る。これでも動きはしますが、あらゆるフローが壊れるのはまさにここです。今日から、それが唯一の選択肢ではなくなります。GingerDocsのAPIと埋め込みSDKが公開され、ドキュメントはapp.gingerdocs.com/docsに、2つのSDKパッケージはnpmにあります。

この記事は、それを使って何を構築できるかを、実際に構築する順番で手短にまとめたものです。

3つのステップ:発行し、マウントし、イベントに応える

モデルは意図的に小さくしてあります。あなたのサーバーが当社のAPIに埋め込みセッションを要求します。これは1つのドキュメントと1人の署名者、あるいはあなたのユーザー1人とワークスペースに紐づいた短命のURLです。あなたのページがそのURLをSDKに渡すと、SDKは当社のオリジン上の署名体験をフレームで表示し、オリジンとセッションIDを両端で固定します。あとはあなたのコードが型付きのイベントを受け取り、それに応じて動きます。

シークレットキーがブラウザに届くことは決してありません。これは守るべきガイドラインではなく、設計上その必要がないのです。ページが目にするのはセッションURLだけで、それは自動的に失効し、あなたのサーバーからいつでも取り消せます。

  • サーバー上でシークレットキーを使ってセッションを発行する:ドキュメントと、それをフレームで表示するページのオリジンを指定した1回のPOSTです。
  • SDKでフレームをマウントする:ページに4行、Reactならコンポーネント1つです。
  • イベントに応える:ready、viewed、signed、completed、declined、そしてワークスペースセッションのドキュメントイベントです。フレームの外で完了する事柄については、あなたのウェブフックエンドポイントかイベントAPIが信頼できる情報源になります。

コード

サーバー側では、1回の呼び出しでセッションが作成されます。レスポンスにはページ用のURLと、SDKがそのセッションからのメッセージだけを受け付けるように引き渡すIDが含まれます。

backend.jsJavaScript
const res = await fetch('https://api.gingerdocs.com/api/v1/embed_sessions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.GINGERDOCS_SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    kind: 'signing',
    document_id: documentId,
    host_origin: 'https://app.example.com',
  }),
})
const { id, url } = await res.json()

ページ側では、SDKが任意の要素にフレームをマウントし、イベントを渡してくれます。セッションが失効したら、新しいセッションを発行してその場でフレームを再読み込みしてください。署名者が作業中の位置を見失うことはありません。

frontend.jsJavaScript
import { mount } from '@gingerdocs/embed'

const embed = mount('#signing', { url, sessionId: id })

embed.on('ready', () => hideLoader())
embed.on('completed', () => showConfirmation())
embed.on('session_expired', async () => {
  const fresh = await refetchSession()
  embed.reload(fresh.url, { sessionId: fresh.id })
})

Reactを使っている場合は、すべてのイベントを1つのハンドラーで受けるコンポーネント1つで済み、インラインで渡しても安全です。Reactは必須ではありません。コアパッケージはフレームワークに依存しないため、上の4行はVue、Angular、Svelte、あるいは素のHTMLページでもそのまま動きます。

Signing.jsxJSX
import { GingerDocsEmbed } from '@gingerdocs/react'

<GingerDocsEmbed
  url={session.url}
  sessionId={session.id}
  onEvent={event => event.type === 'completed' && showConfirmation()}
/>

テスト環境で、無料で構築する

開発者モードとテストキーは、Freeを含むすべてのプランで利用できます。この記事の内容はすべてテスト環境で動作します。いかなる種類のメールも当社のサーバーから送信されず、出力されるPDFには法的効力がない旨の透かしが入り、テストドキュメントは90日後に削除されます。テスト用エンドポイントで署名をシミュレートすることもできるので、人間が何もクリックしなくても、ドキュメントがCOMPLETEDに到達することをCIで検証できます。

準備ができたらライブキーに切り替えてください。呼び出しはまったく同じです。

証明書に記されるあなたの名前

完了したドキュメントはすべて完了証明書で締めくくられます。参照番号、検証コード、そして各署名者のタイムラインとIPアドレスです。署名リンクをあなた自身が届けた場合や、埋め込みセッションを通じて署名者の身元を保証した場合、証明書には検証を行った当事者としてあなたの法人名が記載されます。これは開発者モードをオンにするときにインテグレーター利用条件で引き受ける責任であり、記録としても誠実な形です。誰が署名者を保証したのかが明記されるからです。

PDFを手にした人は誰でも、検証ページで当社の記録と照合できます。アカウントは不要です。

ウェブフックと90日間のイベントログ

すべての状態変化がイベントを発行します。ウェブフックエンドポイントを登録すると、各イベントは署名付きのPOSTとして届き、再試行が行われ、配信ログは設定 → 開発者 から確認できます。エンドポイントが1時間ダウンしていて取りこぼしたとしても、イベントはそこに残っています。すべてのイベントは90日間、APIを通じて読み出せます。

フレームが報告するのはフレーム内で起きたことで、ウェブフックが報告するのはどこで起きたことでもです。後者の上に処理を構築し、前者は画面の前にいる人のために使ってください。

オープンソース、2つのパッケージ

SDKは一度に読み切れるほど小さく、それこそが狙いです。@gingerdocs/embedはフレームワークに依存せず、gzip圧縮で1.5 KB未満、依存関係はゼロです。@gingerdocs/reactはそれを1つのコンポーネントにラップしています。どちらもMITライセンスで、GitHubのgingerdocs/embed-sdkとgingerdocs/embed-react-sdkで公開されており、イシュートラッカーも開かれています。

読めるSDKがあるからこそ、上記のセキュリティに関する主張は、信じるしかないものではなく、自分で確かめられるものになります。

料金と、はじめ方

テストキーでの構築は無料です。本番への移行はDeveloperプランで:年額100ドルで、Proのすべての機能、同じ月1,000件のドキュメントアップロード、そしてライブAPIキーが使えます。詳細は料金ページをご覧ください。

まずはクイックスタートから。新規アカウントから署名済みドキュメントまで、ターミナルで4回の呼び出し、およそ10分です。開発者向けページに概要があり、すべてのフィールドが必要になったときにはAPIリファレンスがあります。