Offision の来訪者バッジでゲートを開ける
ターンスタイルが Offision の来訪者バッジを読み取り、いまこの瞬間に有効かどうかを Offision に尋ね、入館を記録します。API 呼び出しは 3 本、資格情報は 1 つ。返るのは 自分で解釈する状態ではなく、そのまま従える判定です。
建物が自前で持っている入退室管理 — ターンスタイル、ゲート、ロビーのリーダー、あるいは別の来訪者 管理システム — を Offision の来訪者管理と組み合わせる方法です。バッジを発行するのは Offision。 自社のリーダーがそれを読み取り、いまこの瞬間に有効かどうかを Offision に尋ね、バリアを開けるのは 自社側。そして同じ呼び出しが、その人が入館したことを記録します。

バッジは、誰かが到着する数日前にメールで来訪者の手元へ届きます。バリアでは 1 本の呼び出しが問い合わせと記録を同時に行い、自社のゲートは返ってきた判定で開きます。
準備するもの
- コードを読み取ったときに HTTPS API を呼び出し、その答えに従って動けるリーダーを備えた入退室管理システム
- そのシステムが発信する固定の送信元 IP アドレス
- Offision 側で 1 時間程度、加えて入退室管理ベンダー側の作業時間
- 実際に読み取れるバッジがあるよう、テスト用の訪問予定を Offision に 1 件登録しておく
1. API 資格情報を作成する
API 認証を開く追加 を選びます。名前は、それを使うシステムの名前にしてください。あとで監査証跡でこの名前を読む ことになるので、API キー 3 より ロビーのターンスタイル のほうが見分けがつきます。

新しい資格情報。APIスコープと IP制限が並びます。
APIスコープ は行で指定し、1 行がモジュールとアクセスレベルの組み合わせです。ゲートに必要なのは 1 行だけです。
| スコープ | 用途 |
|---|---|
visitor.readwrite | 読み取ったコードの照会と、入館・退館の記録 |
user.readwrite と bookableResource.read は、手順 4 の会議室のドアも扱う場合にだけ追加してください。
スコープは「未許可なら拒否」です。行のないモジュールを呼び出すと 403 が返り、トークン自体は正常なまま 見えます。IP制限 には、そのシステムが発信するアドレスを入力します。
クライアント ID と クライアントシークレット はこのフォームにはありません。Offision が生成し、 保存後に詳細パネルに表示されます。

クライアント ID とシークレット、そして新しいシークレットを発行する操作。
自社側はこれらを OAuth のトークンエンドポイントでアクセストークンに交換します。grant_type=client_credentials、
フォームエンコード、クライアント ID とシークレットは HTTP Basic 認証情報としても、フォームの項目としても
送れます。正確な形は API リファレンスの
トークンエンドポイント を参照してください。
2. 読み取ったコードを照会する
読み取った内容をそのまま 照会の呼び出し に、ゲートが設置されている建物とあわせて送ります。どの種類のコードを持っているかを自社側で判別する必要は ありません。QR の中のバッジ uid、バッジに印字された 6 桁の ビジターコード、自社システムが発行した コード、8 桁の長期バッジコード — どれも同じように解決されます。
返るのは、自分で解釈する状態ではなく判定です。
verify | 意味 |
|---|---|
valid | いま、この建物で有効 |
notYetValid | 実在するバッジだが、訪問がまだ始まっていない |
expired | 訪問が過ぎている |
cancelled | 訪問またはバッジが取り消された。自社システムからのコードをまだ待っているバッジもここに入る |
rejected | 承認者がこの来訪者を却下した |
waitingForApproval | まだ誰も承認していない |
wrongLocation | 実在する有効なバッジ — ただし別の建物のもの |
alreadyCheckedOut | この来訪者はすでに退館している |
notFound | 一致するものがない |
あわせて isGranted が返ります。バリアが実際に従うのはこの項目です。コードの背後にある来訪者とバッジも
返るので、ゲート脇の画面にコードではなく氏名を表示できます。
3. 来訪を記録する
いまの照会は何も変えません。この手順を省くと、すべてのバッジは 未訪問 のままです。受付には来訪者が到着した ことが表示されず、訪問先には通知が届かず、訪問レポートも空のままになります。
チェックインの呼び出し
は同じコードを受け取り同じ形で答え、判定が valid のときは来訪も記録します。つまり、入館の許可と記録を
両方行うゲートが呼ぶのは 1 本 であって 2 本ではありません。手順 2 の照会は、退館側のスキャナーや
ロビーの表示など、確認だけを行うリーダーのためのものです。
チェックアウトの呼び出し はその対で、入館だけでなく退館も読み取るゲート向けです。
どちらも、読み取るたびに呼び出して安全です。判定とあわせて、実際に何が記録されたかを示す action が返ります。
action | 返る場面 |
|---|---|
checkedIn | 最初の来訪 — バッジが 訪問中 になる |
alreadyCheckedIn | すでに館内にいた。何も書き込まれていない |
reCheckedIn | 退館したあと戻ってきた。チェックアウトが取り消された |
checkedOut | バッジが 退場 になる |
alreadyCheckedOut | すでに記録済み。退館時刻はそのまま |
none | 何も記録されていない — 拒否された読み取り、長期バッジ、またはチェックインしていない人の退館 |
ゲート側の処理を書く前に知っておきたい挙動が 2 つあります。
- 退館は入館より緩やかです。 チェックアウトは解決できるバッジをすべて受け付けます。期限切れのものも
含めてです。会議のあいだにパスが切れたからといって、館内に閉じ込められる人が出ないようにするためです。
退館が記録されるのは実際にチェックインした人だけで、していない人にはゲートは開きますが
actionはnoneになります。存在しなかった訪問を作り出さないためです。 - 退館後に戻ってきた人は再入館できます。 ただしその訪問がその建物を含んでいる場合に限ります。照会は
alreadyCheckedOutを返して拒否し、同じコードでのチェックインは訪問を開き直します。2 つの呼び出しが 意図的に食い違う唯一の場所であり、ゲートが照会の答えで自分で判断するのではなくチェックインを呼ぶべき 理由でもあります。
毎週のように訪れる人が持つ長期バッジには開くべき訪問がないので、action は常に none です。有効なもの
であればゲートは開き、それがこのバッジの目的です。長期バッジには
専用のエンドポイント
があり、有効化と無効化の操作で、人を削除せずにパスだけを止められます。
4. 予約から会議室のドアを開ける
これは別の問題なので、分けて考える価値があります。ロビーのゲートに立つ来訪者ではなく、会議室のドアの前に 立つ社員の話です。誰も何も読み取りません。ドアの側が、誰がいつその部屋を予約したのかをあらかじめ知って おく必要があります。
- 各人のカード番号を Offision のユーザーに保存します(
UserCard、UserCard2、UserCard3の 3 枚まで 持てます)。カードが返却されたら削除します。user.readwriteが必要です。 - 予約の変更を購読します。コールバック URL と対象のリソースを指定すると、それらの予約が作成・変更・ キャンセルされたときに Offision がその URL へ送信します。
- コールバックのたびに、予約可能リソースの ID を自社側が制御するドアに対応づけ、主催者と参加者を読み取り、 そのカード番号をその時間帯の権限に変換します。
- 自社側が再接続したときは、その日の予約を取得し直してください。コールバックはきっかけ、クエリが正、と 扱うのが基本です。取りこぼしたコールバックは、それ以外の方法では見えません。
会議室のドアがカードではなくコードを受け付ける場合は、予約可能リソースのアクセスキーがもう一つの道です。 部屋のワンタイム、日次、固定のキーを読み取り、日次とワンタイムのキーは購読しておけば、更新されるたびに 新しいものが届きます。
5. 動作を確認する
次の 4 つは独立して壊れるので、すべて試してください。
- 正常なバッジ。 期間内に実物を読み取ります。
valid、isGrantedが true、来訪者の氏名が返り、 バリアが開くはずです。 - 書き戻し。 そのあと Offision でそのバッジを見ます。訪問中 に変わり、訪問先へ通知が届いている はずです。
- 同じバッジをもう一度。 2 回目も入館が認められ、
alreadyCheckedInが返り、チェックイン時刻が まったく動いていないことを確認します。 - 不正なバッジ。 キャンセル済みのバッジと、明日のバッジをわざと読み取ります。どちらも拒否されなければ なりません。
省かれがちなのは最後の 1 つです。正常なバッジでしか試していないリーダーは、誰でも通すリーダーです。
うまくいかないとき
| 症状 | よくある原因 |
|---|---|
トークン取得で invalid_client | クライアント ID かシークレットを前後の空白ごとコピーした、またはその後シークレットを再生成した |
| 期限切れや取り消し済みのものまで含め、すべて入館できてしまう | ゲートが HTTP のステータスで判断している。拒否された読み取りも 200 で、答えは本文の isGranted |
| トークンは通るのにゲートの呼び出しがすべて 403 | 資格情報が visitor.read どまりで visitor.readwrite がない。3 本とも POST なので読み取り専用は拒否される |
| あるサーバーからは通り、別のサーバーからは 401 | 資格情報の IP制限に、そのサーバーの送信元アドレスが入っていない |
バッジに印字されているコードなのに notFound | 途中でコードが変形している — 前後を詰めた、大文字に変換した、スキャナーがコードではなく URL 全体を送っている。呼び出し自体は 4 種類のどれでも受け付ける |
| どの来訪者もチェックイン時刻が「最後にゲートを通った時刻」になっている | 読み取りではなく定期的にチェックインを呼んでいる。再入館時の読み取りは alreadyCheckedIn を返して何も書き込まない |
| すべてのバッジが 未訪問 のままで、受付に誰も到着しない | ゲートが呼んでいるのが照会でチェックインではない。照会は読み取りを記録するだけ |
| 戻ってきた来訪者が拒否される | 退館した人には照会が alreadyCheckedOut を返す。チェックインを呼べば再入館できる |
| 来訪は記録されるのに Offision のドアが開かない | ドアの解錠は Offision のパネルで行われたチェックインにのみ続く |
| 長期バッジでゲートは開くのに何も記録されない | 想定どおりです。長期バッジには開くべき訪問がないので action は常に none |
| 予約のコールバックが 1 時間で止まる | 購読の期限切れ。既定 60 分、最長 1 日で、更新が必要 |
| 会議室のドアが主催者には開くが参加者には開かない | ユーザーにカード番号が保存されているのが主催者だけ |

