← atelier-kyo-manager OpenClaw →

reserve-optimizer

整骨院向けLINE予約管理Bot。LINE Bot + GASGoogle Apps Script(グーグル・アップス・スクリプト)の略。Googleが提供する、Gmailやスプレッドシート等のGoogleサービスを自動化するための簡易プログラミング環境 + Cloudflare Workers世界中に分散したサーバー上で小さなプログラムを動かす仕組み(Cloudflare社のサービス)。使った分だけの課金なので、アクセスが少ないサービスなら実質無料で運用できる + Stripe決済の サーバーレス構成で、24時間自動受付・決済・AIチャット対応を実現。

なぜ作ったか

整骨院の予約管理は電話・紙ベースが多く、スタッフの負担が大きいという課題がありました。LINE Botで24時間自動受付・Stripe決済・AIチャット対応を実現し、予約業務をゼロにするために開発しました。

アーキテクチャ

レイヤー構成

[LINEユーザー] ←→ [LINE Messaging API]
                      ↓ Webhook
                 [Cloudflare Worker] ← 署名検証 + 即座に200 OK返却
                      ↓ waitUntil で転送
                 [GAS Web App] ← 会話ステートマシン実行
                      ↓
                 [Google Spreadsheets] ← データ保存
                      ↓
                 [Stripe Checkout] ← デポジット決済(1,000円)

設計上の判断と理由

Q: なぜCloudflare Workerを挟んでいるのか?GASに直接Webhookウェブフック。「イベントが起きたら指定URLに自動で通知を送る」仕組み。GitHubで更新があればDiscordに通知が飛ぶ、等の連携に使うしない理由

LINEのWebhookは5秒以内に200 OKを返さないとタイムアウトします。しかしGASの起動は遅く(コールドスタートしばらく使われていなかったプログラムを、次に利用が来た時にゼロから起動すること。この起動時間が長いと利用者が待たされる。Cloudflare Workersはこの起動が速いとされるで3〜5秒)、処理も含めるとタイムアウトする可能性があります。そこで:

  1. Cloudflare Workerが即座に200 OKを返す(LINEタイムアウト回避)
  2. waitUntil非同期1つの処理の完了を待たずに、他の処理を同時に進める方式。ファストフードで注文を受けて番号で呼ぶイメージ。Webサーバーが多数の利用者を同時に捌く時に効くにGASへ転送
  3. WorkerでHMAC-SHA256署名検証も行う(セキュリティ層)

Q: なぜデータベースにGoogle Spreadsheetsを選んだのか?

Q: なぜデポジット制(前払い1,000円)なのか?

Q: なぜGAS + Workersという構成を選んだのか(長期的視点)

3つの軸で判断しました。

  1. コスト: 整骨院は零細事業者でランニングコストを極小にしたかった。GASもWorkersも無料枠で動き、月額0円で本番稼働できる
  2. セキュリティ: LINEとStripeのWebhookをインターネットに晒す必要があるが、GASのWeb Appは認証が弱い。だからWorkersを前段に置いて署名検証をエッジ(高速)で通し、検証済みリクエストだけを独自トークンAIにとっての「文字数」のようなもの。AIは文章をトークンという小片に区切って処理する。課金や入力上限はこの単位で数えられる付きでGASに転送し、GASのエンドポイント自体は隠す二段構えにした
  3. 移行前提: GASは「現在の小規模(1日数十件)に対する選択」であって永遠の答えではない。Phase 2でスケール・SaaS化する段階で Next.js + Vercel + Supabase に移す前提と割り切っている

💡 一言で: 「安く済ませる部分(中身)」と「絶対に手を抜けない部分(入り口の守り)」を分けて考え、大きくなったら移る、という規模に応じた段階的な選択です。

会話ステートマシン

LINE Botの会話フローを状態管理する仕組みです:

初期状態 → 日付選択 → 時間枠選択 → 予約確認 → Stripe決済 → 予約完了
                                                        ↓ キャンセル
                                                    予約取消

各状態でQuickReply(選択肢ボタン)を表示し、ユーザーが迷わないように設計しています。

AIチャット(代替プロバイダー M2.7)

整骨院に関する質問に回答するAIチャット機能:

重視したテスト戦略

「壊れたら最悪(お金の消失・個人情報・二重処理)の箇所」と「一番複雑でバグが出やすい箇所」に、テストのリソースを集中させました。

① Webhook署名検証(なりすまし防止の生命線)

LINE / Stripe 両方のWebhookで HMAC-SHA256 による署名検証をしています。偽の通知を送りつけられて虚偽の予約や「決済完了」を捏ねじ曲げられるのを防ぐためです。比較にはタイミングセーフ比較を採用し、比較にかかる時間の差から正解を推測する「タイミング攻撃」も塞いでいます。

② 会話ステートマシンの遷移網羅

LINE Botの会話は15以上の状態を行き来します(初期状態 → 日付選択 → 時間枠 → 予約確認 → 決済 → 完了、加えてキャンセル・変更・待機リストの分岐)。ここが一番ビジネスロジックが詰まっていてバグが出やすいため、入力と状態遷移の組み合わせを網羅するテストを多数用意しました。

③ 決済の冪等性(リプレイ攻撃対策)

同じWebhookが複数回送られても二重決済・二重予約にならないよう、処理済みのリクエストは20分間キャッシュで記憶して重ねて処理しない仕組み(冪等性)を持たせています。

④ 複数LLMクロスレビュー

単一のLLMは自分の出力に甘くなる(同じ盲点を共有する)ため、2機の異なるLLMで独立にコードレビュー書かれたコードを、書いた本人以外の視点で読んで問題を指摘する作業。バグ・読みにくさ・危険な書き方を第三者が見つけるのに有効させ、出た指摘を優先度順に潰す運用にしています。

💡 一言で: 「AIが書いたから正しい」ではなく、独立した検証層を何重に挟むかが品質を決める、というのが実感です。

面接で聞かれそうなポイント

「なぜサーバーレス構成?EC2等のサーバーではない理由」

「Stripe Checkoutの選定理由」

「本番運用していて不安な点・技術的負債は」

正直に3つあります。いずれもレビュー議事録に文書化済みで、改善案を把握しているものです。

  1. Workers → GAS 間の通信がGASの302リダイレクト仕様に依存している点。GASのWeb AppはPOSTを受けると302を返してPOSTをGETに変換する仕様で、それをWorkers側で吸収する工夫をしています。Google側の仕様変更の影響を受ける可能性があり、Apps Script APIApplication Programming Interface(エーピーアイ)の略。あるプログラムの機能を、別のプログラムから呼び出せるようにした「窓口」。予約システムがLINE社の機能とやり取りするのもAPI経由(実行可能API)化すれば依存を外せる認識で移行を検討中。※署名検証・認証・冪等性などセキュリティの核はWorkers内で別途堅牢に実装済みで、ここが壊れてもデータ漏洩・不正アクセスには直結せず、予約機能の停止(可用性問題)に留まります。

  2. 顧客の個人情報(氏名・電話番号)がスプレッドシートに平文で保存されている点。現在はGoogleアカウントの権限管理で守っていますが、Phase 2のSupabase移行で暗号化と細かなアクセス権限(RBAC)を整える前提です。

  3. 3件の失敗テストが未解明の点(回数券の有効期限・セグメント配信の非アクティブ判定)。実GASの挙動とすり合わせる残課題として認識しています。

💡 ポイント: 自分で弱みを挙げられる=技術的負債を把握・管理している証拠。隠す欠陥ではなく、改善案付きの「見える化された課題」として扱っています。

技術スタック


用語の平易な解説(専門用語を読み解く)

☁️ サーバーレス・EC2

一言で: 「サーバーを常に立てず、必要な時だけ動かす仕組み」と「常に動くサーバー」。

🔔 Webhook(ウェブフック)

一言で: 「イベントが起きた時に、別のサービスへ自動で連絡する仕組み」。

⚡ Cloudflare Workers(クラウドフレアワーカーズ)・コールドスタート・waitUntil

一言で: 「世界中に散らばるサーバーで高速に処理を動かす仕組み」と「初回起動のもたつき」。

🔐 HMAC-SHA256・署名検証(しょめいかんしょう)

一言で: 「メッセージが本当に正規の送り主からかを確かめる仕組み」。

⏱️ タイミング攻撃(タイミングこうげき)・タイミングセーフ比較

一言で: 「処理にかかる時間の差で正解を当てる攻撃」と、それを防ぐ比較方法。

🔁 冪等性(べきとうせい)

一言で: 「同じ操作を何度繰り返しても、結果が同じになる性質」。

📊 GAS(Google Apps Script)・Web App

一言で: 「Googleのサービスを自動化するプログラム」と「Webから呼べる形にしたもの」。

💳 Stripe Checkout(ストライプチェックアウト)・デポジット・PCI DSS

一言で: 「安全な決済を簡単に組み込む仕組み」と「カード情報保護の国際基準」。