サイトが「見せる」、Kai が「受け取る」
カレンダーと申込フォームは、サイト側が自分の見た目で描きます。Kai は宿泊者名簿・取引条件の開示・キャンセル規定・カード決済を持ちます。
01 口は 4 つ
GET /api/calendar- 空きと料金
POST /api/quote- 見積(総額とキャンセルの段)
POST /api/book- 申し込み(Idempotency-Key 対応)
GET /api/booking/:id- 予約の照会
画面と同じ経路を通ります。見積と在庫の規則を 2 か所に置いていません。 片方だけ直すと「画面では断るのに API では通る」が静かに生まれ、金額と在庫に効くので請求が起きるまで気づけないためです。
02 「取れない」を 1 つに丸めません
断りには理由が付き、どの日かも返します。
available- 売れる
occupied- 売り切れ。正常
unpriced- 料金が入っていない。宿が直せば売れる
ambiguous- 同じ優先度のプランが 2 つ当たっている
closed- 意図して閉めている
overbooked- 二重予約。0 に丸めない
既製の予約システムには、料金未設定も満室も同じ「空きなし」で返すものがあります。呼び出し側で区別できず、宿の入れ忘れがお客さまには満室として見えます。 ここを分けているので、サイト側で「料金を入れてください」と出せます。
03 組み込みの形
いまはサーバ側から叩く形を想定しています。 CORS ヘッダを出していないため、ブラウザから直接は叩けません。WordPress のようにバックエンドを持つサイトが対象になります。
画面が移るのはカードを入れる瞬間だけです。 そこは他社の決済画面と同じ体験で、別ドメインに移る方がむしろ安心されます。Kai 側の見た目はテンプレートを選べるので、色と書体は揃います。
静的サイトから直接叩けるようにするかは検討中です。必要でしたら、お問い合わせのときにお書き添えください。
04 断りには、打つ手が付きます
理由の名前だけ返されても、呼ぶ側は何をすればよいか分かりません。Kai は理由を 6 つに分類して返します。
input- 送った内容が違う。直して送り直す
state- 何度出しても通りません。 満室・料金なし・期限切れなど
retry- 混んでいただけ。もう一度で通ります
auth- 資格の問題
payment- 決済側の問題
internal- 当社側の問題
retry と state を混ぜていません。 ここを一緒にすると、永久に通らない要求を延々と再試行することになります。分岐は文言ではなく分類で書いてください。
POST /api/book は Idempotency-Key を受け取ります。ヘッダ名は決済事業者に合わせてあります。再送しても二重に予約が入りません。
05 名簿はサイト側に出せません
「決済だけ Kai」という形は採っていません。理由が 3 つあります。
- 名簿は料金計算に繋がっています。 子供料金の段が年齢で決まるため、法令の話をする前に見積もりが計算できなくなります。
- 間違え方が特殊で、しかも正しく見えます。 旅券番号が要るのは「外国籍の方」ではなく「国内に住所を有しない外国人」です。取り違えても画面は正常に動き、法令には違反しています。
- 3 年保存の主体と、誰が見たかの記録が消えます。 サイトを作り直したときに一緒に消えてしまいます。