◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-04-20上級

Claude Code × Stripe で作るサブスクリプションSaaSの実装 — Webhook・権限管理・本番ハマりポイントの全記録

Claude Code と Stripe でサブスクリプションSaaSを本番投入するまでの実装記録。Cloudflare Workers での Webhook 署名検証、KV+Cookie の2層権限管理、verify-session の設計、Cookie 取得の正規表現が静かに失敗していた実測をコード付きで。

Claude Code265Stripe15SaaS14Cloudflare Workers16Webhook4サブスクリプション8課金6

✦ プレミアム記事

Stripe の Dashboard に「最初の課金成功」通知が届いたとき、思わず声が出てしまいました。Claude Code と2週間格闘しながら実装したサブスクリプションシステムが、本番でようやく動き出した瞬間でした。

構築したのは、月額プランと永久ライセンスを両方扱えるSaaSの課金システムです。Stripe Checkout → Webhook → Cloudflare KV → Cookie という一連のフローを、Cloudflare Workers 環境でゼロから動かすまでに、なかなかのデバッグ時間を費やしました。

ここではその過程で学んだことをすべて書き出しています。公式ドキュメントには書かれていないハマりポイントや、Claude Code と一緒に設計を固めていくプロセスも含めて、できるだけ正直に記録しています。

課金フロー全体を設計してから実装を始める理由

Stripe の実装でよくある失敗が、「とりあえず Checkout を動かしてから考える」というアプローチです。私自身、最初はそうやって実装を始めてしまいました。

結果、Webhook の処理ロジックと権限管理の設計が後から追加した形になり、コードが複雑に絡み合ってしまいました。Claude Code に「このコードをリファクタリングしてほしい」と頼んだところ、「設計から見直した方が早いです」と返ってきたのが正直なところです。

実装を始める前に、以下の6ステップのフローを確認しておくことをお勧めします。

  • フロントエンドの購入ボタン → /api/checkout API
  • /api/checkout → Stripe Checkout セッション生成 → ユーザーをリダイレクト
  • Stripe Checkout での支払い → checkout.session.completed Webhook 発火
  • Webhook ハンドラー → Cloudflare KV への権限情報書き込み
  • 支払い完了後リダイレクト → /api/verify-session でのCookie発行
  • Cookie → コンテンツへのアクセス制御

この6ステップを先に整理しておくと、実装中に「今どこを作っているのか」が常に明確になります。Claude Code に「このフロー図を見て、実装の順番と依存関係を整理して」と投げると、どの部分を先に実装すべきかを具体的に提案してくれます。

Claude Code に設計レビューを頼む価値

実装を始める前の段階で、Claude Code との対話が特に効果を発揮します。「この課金フローで設計上のリスクはあるか?」と質問すると、べき等性の問題や Race Condition のリスクを指摘してくれます。

課金システムは一度動き始めると変更しにくい部分が多いため、設計段階でのレビューが後々の修正コストを大幅に下げます。

pricing.ts による課金プランの一元管理

課金プランの価格・Stripe の priceId・UI 表示テキストは、必ず1ファイルで管理することをお勧めします。各コンポーネントに直書きし始めると、価格変更のたびに全ファイルを修正することになります。

// src/config/pricing.ts
 
// 全 priceId を一元管理
// as const で型安全にしつつ、ヘルパー関数でアクセスする設計
export const STRIPE_PRICE_IDS = {
  ja: {
    tip: "price_xxxxxxxxxxxx",     // ¥150
    article: "price_yyyyyyyyyyyy", // ¥250(記事単体)
    pro: "price_zzzzzzzzzzzz",     // ¥580/月(月額)
    premium: "price_wwwwwwwwwwww", // ¥2,480(永久ライセンス)
  },
  en: {
    tip: "price_aaaaaaaaaaaa",
    article: "price_bbbbbbbbbbbb",
    pro: "price_cccccccccccc",
    premium: "price_dddddddddddd",
  },
} as const;
 
// as const 型の落とし穴を回避するヘルパー関数
// string 型の locale で直接インデックスアクセスはできないため
export const getPriceIds = (locale: string) => {
  const localeKey = locale === "ja" ? "ja" : "en";
  return STRIPE_PRICE_IDS[localeKey];
};
 
// SingleArticleCTA のテキストも同じファイルで管理
export const ARTICLE_LABELS = {
  ja: {
    heading: "この記事の全文を読む",
    description: "詳細な実装コードと解説の続きをご覧ください",
    button: "¥250 で購入",
    separator: "または",
    membershipText: "月額メンバーシップで全記事を読み放題",
  },
  en: {
    heading: "Read the Full Article",
    description: "Access the complete implementation code and detailed explanations",
    button: "Buy for $1.75",
    separator: "or",
    membershipText: "Get unlimited access with a monthly membership",
  },
};

as const の落とし穴

STRIPE_PRICE_IDS を as const で定義すると、string 型の locale 変数でインデックスアクセスができずエラーになります。

// ❌ これは TypeScript エラー(string で as const 型にアクセス不可)
const priceId = STRIPE_PRICE_IDS[locale].premium;
 
// ✅ ヘルパー関数を経由してアクセスする
const priceId = getPriceIds(locale).premium;
 
// ✅ サーバーコンポーネントで使う場合は、明示的な型注釈付きで再宣言
const PRICE_IDS: Record<string, { tip: string; article: string; pro: string; premium: string }> = STRIPE_PRICE_IDS;
const priceId = PRICE_IDS[locale]?.premium;

Claude Code に「as const で定義した型を locale 変数でインデックスアクセスしたい」と相談すると、上記のどちらのパターンが適切かを使用場所に応じて提案してくれます。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦Checkout → Webhook → KV → Cookie の課金フロー全体を、Cloudflare Workers 環境でゼロから動かすまでの設計と実装手順
✦Webhook 署名検証・タイムアウト・重複配信・イベント順序の入れ替わりなど、本番でだけ起きる落とし穴と、それぞれの具体的な対処コード
✦KV + Cookie の2層フォールバックで deny-by-default を守るアクセス制御と、その入口の parseCookie が2つ目以降の Cookie を取りこぼしていた実測4パターン
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⟐ Claude Code2026-05-03
Claude × Stripe Meter Events で従量課金 SaaS を構築する実装ガイド
Claude API のトークン消費量を Stripe Meter Events で従量課金として回収する、本番運用可能なアーキテクチャと実装コードを公開します。冪等性・上限制御・ダッシュボード可視化までカバーします。
⟐ Claude Code2026-08-19
一度キャッシュに載った500ページは、直しても消えません
修正をデプロイしたのに壊れたページが出続けたことがあります。原因はコードではなくエッジキャッシュでした。ステータスコードだけを見る保存判定が、200で返る壊れたHTMLを通していたのです。本文の完全性で保存可否を決めるガードの実装と、運用で調整した誤検知の線引きを、実際に踏んだ経緯とともに書きました。
⟐ Claude Code2026-04-15
Claude Code と作る StoreKit 2 × SwiftUI の課金実装 — 審査を通る最小構成と運用の落とし穴
Claude Code を設計パートナーにした StoreKit 2 × SwiftUI の課金実装を、PurchaseManager・サーバー検証・ペイウォールUIまで通しで組み立てます。Ask to Buy や Transaction.updates の遅延など、公式ドキュメントが触れない運用の詰まりどころも扱います。