はじめに
Claude CodeにStripe決済を実装してもらった場合でも、AIだけに頼らず裏側のワークフローを理解しておくことが重要です。AIのモデル性能が一時的に落ちたり、複雑な実装でうまくいかなかったりする場面では、基礎知識があることで的確な指示出しやトラブルシューティングが可能になります。
この記事では、Stripe買い切り決済の裏側でどのようなやり取りが行われているのかを、シーケンス図をもとに解説します。
シーケンス図の全体像
Stripe決済のワークフローには、以下の4つの登場人物が関わります。
- ユーザー(クライアント) — Next.jsのフロントエンド。ブラウザで表示されるUI
- サーバー — Next.jsのバックエンド。APIエンドポイントを処理
- データベース — Turso。セッション情報やユーザー情報を保持
- Stripe — 決済サービス。カード情報の管理や決済処理を担当
これらが時系列でどのようにやり取りしているかを、順を追って見ていきましょう。
ステップ1:購入ボタンのクリック
ユーザーが料金プランページの「購入する」ボタンをクリックします。これがワークフロー全体の起点です。
ステップ2:APIエンドポイントへのフェッチ
ボタンをクリックすると、クライアント側の実装で/api/checkoutというエンドポイントに対してフェッチ関数が呼び出されます。サーバーに対して「決済を開始したい」というリクエストを送信します。
ステップ3:セッション情報の取得
サーバー側はリクエストを受け取ると、まずデータベースからセッション情報を取得します。
Tursoのデータベースにはsessionテーブルがあり、ユーザーID、トークン、ユーザーエージェント(使用端末)、IPアドレスなどの情報が保存されています。この情報をもとに、誰が決済しようとしているのかを特定します。
ステップ4:Stripeチェックアウトセッションの作成
セッション情報を取得したら、Stripeが提供するライブラリのcheckout.sessions.create()関数を呼び出します。このとき渡す主な情報は以下の通りです。
- mode —
payment(1回払い) - client_reference_id — データベースから取得したユーザーID
- price — 商品の価格(例:19,800円)
Stripeはこの情報を受け取り、ユーザーをStripe側でも管理します。どのユーザーが何を購入したのかを記録しておく必要があるためです。
ステップ5:チェックアウトURLの返却とリダイレクト
Stripeが処理を受け付けると、チェックアウトURLをサーバーに返します。サーバーはそのURLを使って、クライアントをStripeの決済ページにリダイレクトします。
このStripe決済ページは、Stripe側であらかじめ用意されているUIです。テスト時に4242 4242 4242 4242のカード番号を入力したあのページがこれにあたります。
ステップ6:カード情報の入力と決済
ユーザーが決済ページでカード番号を入力し、決済を完了します。
ここで重要なのは、カード番号などの決済情報はすべてStripe側で管理されるという点です。自前のデータベースにカード情報を保存する必要はありません。もしデータベースが漏洩した場合にカード情報まで流出してしまうリスクを避けるため、決済情報の管理はすべてStripeに任せるのが正しい設計です。
ステップ7:成功ページでの決済確認
Stripeが決済の成功を確認すると、成功ページへのリダイレクトURLとともにセッションIDをクライアントに返します。
成功ページ側では、このセッションIDを使ってStripeのretrieve関数を呼び出し、決済が本当に成功したのかを確認します。ステータスがpaid(支払い済み)であれば、データベースを更新してユーザーをノーマルからプレミアムに昇格させます。
これにより、以降はプレミアムユーザーとして全講座を閲覧できるようになります。
キャッシュが原因で起きた不具合
前回の動画でAIに何度聞いても決済後にすぐレッスンを閲覧できなかった原因は、クッキーのキャッシュ設定にありました。
具体的には、BetterAuthライブラリのクッキーキャッシュ設定がClaude Codeによってtrueに設定されており、30分間キャッシュが有効になっていました。このキャッシュが古いセッション情報を保持していたため、決済が完了してもNext.jsは古い(非プレミアム)状態を参照してしまい、レッスンが閲覧できない状態になっていたのです。
なぜキャッシュ・クッキーが存在するのか
毎回データベースに対してユーザーの状態を問い合わせると、読み取り(リード)のコストがかかります。クエリの実行回数が増えると費用も増加するため、キャッシュやクッキーを活用してデータベースへの問い合わせ回数を抑えるのが一般的です。
今回の解決策
今回はBetterAuthのクッキーキャッシュを無効化し、代わりにNext.jsのサーバーサイドキャッシュを利用する方針に変更しました。Next.jsにはキャッシュの設定が簡単にでき、決済後にキャッシュを更新(古い情報を新しくする)するための専用関数も用意されているため、不具合が起きにくい設計になっています。