はじめに
一棟貸しの宿は在庫が1つしかありません。同じ日程を2人が同時に予約しようとしたら、どちらか一方だけを通す必要があります。しかも公式サイトだけでなく、AirbnbなどのOTAからも同時に予約が入る可能性があります。
この記事では、決済の途中で他のチャネルに横取りされることなく予約を確定させるための、処理の順序について解説します。技術的な難しさよりも、「何を先にやるか」という判断が肝になります。
順序がすべてを決める
3ステップの順番に理由がある
予約ボタンが押されてから決済画面に飛ぶまでの間に、サーバーは次の3つを順番に実行します。
画面に表示されていた金額は信用せず、予約管理システムに再確認する
「空室確認つき」で仮予約を作成。ここで初めて部屋が確保される
部屋が押さえられて初めて、決済サービスの画面を作る
この順番には明確な理由があります。もしカード登録を先にしてしまうと、カード情報を預かったのに部屋が取れていないという最悪の状態が起こり得ます。逆にこの順序なら、最悪でも「部屋を無駄に押さえた」で済み、時間が経てば自動で解放されます。
「確認してから押さえる」では間に合わない
自分で「空いているか確認 → 空いていたら押さえる」と2段階でやると、その2つの処理の間にOTAから予約が入る可能性があります。ほんの数百ミリ秒でも、可能性がある以上いつか起きます。
そこで、予約管理システム側が持つ「空室確認と仮予約作成を同時に行う」機能を使いました。空きがなければ仮予約自体が作られずエラーが返るので、隙間がありません。
在庫の確保は在庫の持ち主にやらせる
自社で「確認 → 確保」を組むと必ず隙間ができます。在庫の正本を持っているシステムに、確認と確保をひとまとめで依頼するのが唯一確実な方法です。
仮押さえには期限をつける
30分+猶予5分
仮押さえたまま決済されなければ、部屋は永遠に売れなくなります。そこで決済画面の有効期限を30分とし、それに5分の猶予を足した35分で仮押さえが切れる設計にしました。
期限の管理は自社データベース側で行い、10分ごとに動く定期処理が期限切れの仮押さえを解放します。決済サービスからの「期限切れ通知」も受け取りますが、それはあくまで補助です。
外部からの通知を唯一の頼りにしない
決済サービスからの通知が届かない事故が、実際に100回以上連続で発生したことがありました。通知が来なければ部屋が解放されない設計だったら、その間の予約はすべて取り逃していたことになります。自分で持っている期限を主、外部通知を従とする構成が安全です。
ブラウザバックにも即対応する
決済画面から「戻る」を押したお客様のために、35分も部屋を押さえておく必要はありません。戻ってきたことを検知したら、決済画面をその場で無効化し、仮押さえも即座に解放するようにしました。
「気が変わってやめた」がすぐ在庫に反映されれば、次のお客様がその日程を予約できます。
同じ人の重複を整理する
お客様が「8月1日〜2日」で検索してやめ、「8月1日〜3日」で再検索する。よくある行動ですが、素直に作ると1人で2つの仮押さえを持ち、自分自身と在庫を奪い合ってしまいます。
そこで新しい仮押さえを作る前に、同じメールアドレスの古い仮押さえを解放する処理を入れました。また、同じ人が同じ条件でもう一度予約に進んだ場合は、新しく作らず既存の決済画面に戻します。
悪意ある利用も想定する
同時に押さえられる数を制限する
予約ボタンを連打したり、プログラムで大量に予約を開始したりすると、在庫を押さえ続けて営業妨害ができてしまいます。そこで同一アクセス元から同時に保持できる仮押さえを5件までに制限しました。
大事なのは「試行回数」ではなく「現在押さえている数」で数えることです。正常に予約を完了した人や、途中でやめた人がカウントに残り続けると、まっとうな再訪問者まで弾いてしまいます。
応答が想定と違っても諦めない
APIの応答形式が想定と異なる場合、普通ならエラーにして終わりです。しかし予約登録では実際には登録に成功しているのに応答だけ壊れている可能性があります。ここでエラー扱いにすると、お客様には「失敗しました」と表示されるのに部屋は押さえられたまま、という状態になります。
そこで応答が読めなかったときは、その日程の予約一覧を取得し直し、自社の予約番号を持つ予約が存在するか確認するようにしました。存在すれば成功として扱います。
予約の登録はやり直さない
通信が不安定なとき、失敗したリクエストを自動で再送信するのはよくある工夫です。ただし予約の登録では絶対にやりません。1回目が実際には成功していた場合、同じ予約が2件できてしまうからです。
情報を取得するだけの処理は再試行してよく、何かを作る処理は再試行しない。この線引きを明確にしておくことが、地味ですが重要です。
まとめ
ダブルブッキングを防ぐために大事にしたのは、次の3点です。
- 順序で守る — 在庫の確保を先に、カード登録を後に。逆にすると事故の被害が大きい
- 確保は正本に任せる — 空室確認と仮押さえを一体の処理として依頼し、隙間をなくす
- 期限は自分で管理する — 外部通知は補助に留め、自社の定期処理を主にする
決済側の設計は「宿泊予約のStripe決済設計」で、予約後の変更検知は「Webhookと毎時突合で崩れない同期を作る」で解説しています。