Build This Now
Build This Now
クロード・コードとは何か?Claude Code のインストールClaude Code ネイティブインストーラーClaude Code で最初のプロジェクトを作る
Claude Code v2.1.122 Release NotesClaude Code の Dynamic Workflows:実際のコードベースで 1,000 個の subagents を動かす方法Claude Code ベストプラクティスClaude Opus 4.7 ベストプラクティスVPS上でのClaude CodeGit 統合Claude Code レビューClaude Code WorktreesClaude CodeリモートコントロールClaude Code ChannelsChannels、Routines、Teleport、DispatchClaude Code スケジュールタスクClaude Code権限管理Claude Code オートモードClaude Code で Stripe 決済を組み込むフィードバックループTodoワークフローClaude Code タスク管理プロジェクトテンプレートClaude Code の料金とトークン使用量Claude Code の料金:実際にいくら払うことになるのかClaude Code Ultra Review 完全ガイドClaude Code で Next.js アプリを作るClaude Code With Supabase: Database, Auth, RLSVercel deepsec with Claude Codeエージェント型コマース:AI エージェントが支払えるアプリの作り方Claude Code 1M Context in Practice: When Bigger Isn't BetterClaude Code GitHub Actions Setup Guide (@claude + Cron)Claude Code Headless Mode: The Definitive Guide to claude -pClaude Code Max Plan vs API Cost: Break-Even GuideClaude Code Prompt Caching: The Token Discount Most People Never Turn OnRun a Team of AI Agents in Parallel with Git WorktreesPrompt Injection in Coding Agents: How to Not Get Pwned
speedy_devvkoen_salo
Blog/Handbook/Workflow/Adding Stripe Payments With Claude Code

Claude Code で Stripe 決済を組み込む

Claude Code を使って Next.js アプリに Stripe Checkout、webhook、カスタマーポータルを繋ぎ込みます。最初のプロンプトから本番決済まで 1 セッションで。

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

Published May 3, 20269 min readHandbook hubWorkflow index

問題:Stripe の連携には 7 つの可動部品があります。checkout、webhook、カスタマーポータル、環境変数、テストキー、本番キー、そして CLI です。たいていのチュートリアルはそのうち 3 つしか扱わず、残りは真夜中にデバッグさせられる羽目になります。

手っ取り早い解決策:Stripe MCP サーバーを 1 コマンドで Claude Code に追加すれば、ビルドしながら Claude がリアルタイムで顧客・価格・サブスクリプションを調べられます:

claude mcp add --transport http stripe https://mcp.stripe.com/

この 1 行で、Claude にあなたの Stripe アカウントへの直接アクセスを与えられます。ライブデータを読み、製品が存在することを確認し、設定ミスが webhook ハンドラに届く前に捕まえられます。

始める前に必要なもの

3 つそろえておく必要があります。

Stripe アカウント に、製品と価格を少なくとも 1 つ作っておきます。MCP サーバー経由で、Dashboard に触れずに Claude に作らせることもできます。MCP が接続されていれば、「$29/月 の継続価格で Pro Plan という製品を作って」というプロンプトで十分です。

Claude Code に Stripe MCP を接続したもの(上記のコマンド)。代替手段は Stripe のベストプラクティス skill で、これはセッションに Stripe のドキュメントを注入します:

npx skills add https://docs.stripe.com --yes

アクティブな開発には MCP サーバーのほうが良い選択です。Claude はセッションの途中でこれを呼び出し、価格を一覧したり、メールで顧客を検索したり、サブスクリプションの現在のステータスを取得したり、webhook シークレットが Dashboard の表示と一致するか確認したりできます。skill が与えるのはドキュメントのコンテキストだけです。アカウントへの問い合わせはしません。

この 2 つは排他的ではありません。両方を走らせるチームもあります。ライブの問い合わせには MCP、ベストプラクティスの指針には skill、という具合です。制限付き API キー(rk_test_...)を使った MCP は、テストモードではより安全な構成です。制限付きキーは Claude が触れる Stripe オブジェクトを限定するからです。

4 つの環境変数 を .env.local ファイルに:

STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_URL=http://localhost:3000

STRIPE_SECRET_KEY はクライアントには絶対に触れさせません。NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY は公開して問題ありません。STRIPE_WEBHOOK_SECRET は、ローカルのイベント転送を開始したときに Stripe CLI から得られます(テストの章で扱います)。NEXT_PUBLIC_URL は success_url と return_url のパラメータに使われます。

Checkout Sessions 対 Payment Intents

決済を受け取れる Stripe の API は 2 つあります。間違ったほうを選ぶと、何週間もの作業が上乗せされます。

Checkout Sessions(stripe.checkout.sessions.create())は、ユーザーを Stripe ホストのページ、またはあなたのドメイン上の埋め込みフォームへリダイレクトします。Stripe がカード入力、3D セキュア、Apple Pay、通貨表示、税金を扱います。たいていの SaaS 製品では、これが正しい選択です。一度きりの購入もサブスクリプションも、どちらもこれで動きます。

Payment Intents(stripe.paymentIntents.create())はより低レベルです。Stripe Elements で自分でフォームを作り、カードデータを集め、API を呼びます。コントロールは増えますが、コードも増え、メンテナンスも増えます。ホストされたページでは実現できない完全カスタムの checkout UI が必要なときだけ使ってください。

2026 年の Checkout Sessions の推奨パターンは Embedded Checkout です。ui_mode: 'embedded' はユーザーをあなたのドメインに留め、@stripe/react-stripe-js の EmbeddedCheckoutProvider と EmbeddedCheckout コンポーネントを使い、あなたが設定した return_url に戻します。Hosted Checkout(stripe.com へのリダイレクト)も依然として動きますが、Stripe が新しい連携で勧めているのは Embedded です。

Checkout フローを作る

Claude にルートの雛形を作らせ、それからリリース前に mode パラメータを確認します。

ここで Claude に与えると良いプロンプトはこうです:「app/api/checkout/route.ts に Stripe Checkout Sessions のルートを作って。一度きりの購入には mode: payment を使い、セッション URL を JSON で返し、すべての URL は環境変数から読んで」。

一度きりの購入なら、ルートはこうなります:

// app/api/checkout/route.ts
import { NextResponse } from 'next/server'
import Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-11-20.acacia',
})

export async function POST(request: Request) {
  const { priceId } = await request.json()

  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    line_items: [{ price: priceId, quantity: 1 }],
    success_url: `${process.env.NEXT_PUBLIC_URL}/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.NEXT_PUBLIC_URL}/pricing`,
  })

  return NextResponse.json({ url: session.url })
}

サブスクリプションなら、変えるのはちょうど 1 か所です。mode: 'payment' の代わりに mode: 'subscription' を設定します。priceId は Stripe の継続価格(一度きりの価格ではなく)を指している必要があります。ルートのそれ以外はまったく同じです。

Embedded Checkout に切り替えるには、ui_mode: 'embedded' を加え、success_url を return_url に置き換えます。レスポンスは session.url の代わりに session.client_secret を返し、これをフロントエンドで EmbeddedCheckoutProvider が使います。

Webhook:みんなが間違える部分

webhook は Stripe があなたのアプリに返事をする場所です。プロビジョニングの判断(アクセスの付与、剥奪、レシートの送信)はすべて、checkout 成功時のリダイレクトではなく webhook ハンドラに置くべきです。ユーザーはタブを閉じたり、戻るボタンを押したりします。リダイレクトは信頼できません。webhook は必ず発火します。

Next.js App Router における致命的な問題は、生のボディのパースです。Stripe の署名検証(stripe.webhooks.constructEvent)は、生のリクエストボディを文字列として必要とします。App Router はハンドラが見る前にボディをパースしてしまいます。request.json() を呼ぶと、ストリームが消費され、検証は毎回失敗します。

Claude に正確な制約を与えてください:「app/api/stripe-webhook/route.ts に Stripe の webhook ハンドラを作って。生のボディには request.json() ではなく request.text() を使い、イベントを処理する前に署名を検証して」。

代わりに request.text() を使います:

// app/api/stripe-webhook/route.ts
import { NextResponse } from 'next/server'
import Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-11-20.acacia',
})

export async function POST(request: Request) {
  const rawBody = await request.text()
  const sig = request.headers.get('stripe-signature')!

  let event: Stripe.Event

  try {
    event = stripe.webhooks.constructEvent(
      rawBody,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    )
  } catch (err) {
    return NextResponse.json(
      { error: 'Webhook signature verification failed' },
      { status: 400 }
    )
  }

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session
      // Provision access, send welcome email
      await grantAccess(session.customer as string)
      break
    }
    case 'customer.subscription.updated': {
      const sub = event.data.object as Stripe.Subscription
      // Update tier in DB
      await updateSubscription(sub.customer as string, sub.status)
      break
    }
    case 'customer.subscription.deleted': {
      const sub = event.data.object as Stripe.Subscription
      // Revoke access
      await revokeAccess(sub.customer as string)
      break
    }
    case 'invoice.payment_failed': {
      const invoice = event.data.object as Stripe.Invoice
      // Send dunning email, flag in DB
      await handleFailedPayment(invoice.customer as string)
      break
    }
  }

  return NextResponse.json({ received: true })
}

最低限ハンドリングすべき 4 つのイベントは下の表のとおりです。残りは課金ロジックが育つにつれて追加できます。

イベントいつ発火するかアクション
checkout.session.completed決済またはサブスクリプション開始アクセスを付与、ウェルカムメール送信
customer.subscription.updatedプラン変更、更新、トライアル終了DB のティアを更新
customer.subscription.deletedキャンセルアクセスを剥奪
invoice.payment_failed継続課金の失敗督促メール送信、DB にフラグ

もう 1 つ。このルートは、ボディを読む Next.js のミドルウェアからは除外しなければなりませんし、アプリの認証チェックで包んではいけません。Stripe は未認証のリクエストとしてここに POST します。署名検証だけで保護してください。

カスタマーポータルのセットアップ

カスタマーポータルは、ユーザーが自分でサブスクリプションを管理できるようにします。キャンセル、支払い情報の更新、請求書の閲覧です。1 つのステップがほとんどの開発者をつまずかせます。

ポータルのセッションを作る前に、Stripe Dashboard でポータルを設定しておかなければなりません。 保存された設定がないと、billingPortal.sessions.create() の呼び出しはすべてエラーを返します。テストモードの設定 URL は https://dashboard.stripe.com/test/settings/billing/portal です。本番モードには別の URL https://dashboard.stripe.com/settings/billing/portal があります。どちらもデプロイ前に設定が必要です。

設定のステップは、ユーザーに許可するアクションを決める場所です。サブスクリプションのキャンセル、支払い方法の更新、プランの切り替え、請求書のダウンロードなどです。Dashboard でこれらのオプションを設定し、設定を保存すれば、API 呼び出しが動くようになります。

設定さえ済めば、セッションを作るルートは短いものです:

// app/api/portal/route.ts
import { NextResponse } from 'next/server'
import Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-11-20.acacia',
})

export async function POST(request: Request) {
  const { customerId } = await request.json()

  const session = await stripe.billingPortal.sessions.create({
    customer: customerId,
    return_url: `${process.env.NEXT_PUBLIC_URL}/account`,
  })

  return NextResponse.json({ url: session.url })
}

フロントエンドは session.url にリダイレクトします。ユーザーは自分の Stripe 課金ページを見て、変更を行い、終わったら /account に戻ります。変更は customer.subscription.updated または customer.subscription.deleted イベントとして発火し、これはあなたの webhook ハンドラがすでにカバーしています。

注意:テストモードと本番モードのポータル設定は完全に別物です。テストモードでポータルを設定しても、本番モードのセットアップにはなりません。本番に出す前に、両方の環境で同じ設定手順を踏んでください。

フロー全体をテストする

Stripe CLI は、Stripe からローカルサーバーへライブのイベントを転送します。決済をテストする前に、別のターミナルでこれを実行してください:

stripe listen --forward-to localhost:3000/api/stripe-webhook

CLI は起動時に webhook 署名シークレットを表示します。その値が .env.local の STRIPE_WEBHOOK_SECRET に入ります。リスナーを再起動するたびに変わるので、ハードコードしないでください。

決済フォームをクリックして通さずに特定のイベントを発火させるには、stripe trigger を使います:

stripe trigger checkout.session.completed
stripe trigger customer.subscription.deleted
stripe trigger invoice.payment_failed

シナリオ別のテストカード:

シナリオカード番号
決済成功4242 4242 4242 4242
拒否4000 0000 0000 0002
3D セキュアが必要4000 0025 0000 3155
残高不足4000 0000 0000 9995

有効期限は任意の未来の日付、CVC は任意の 3 桁、ZIP コードも任意で構いません。結果を変えるのはカード番号だけです。

推奨のテスト手順はこうです。CLI のリスナーを起動し、checkout ページを開き、カード 4242 4242 4242 4242 で決済を完了し、checkout.session.completed イベントがターミナルに届くのを見て、ハンドラが走ったことを確認します(DB かログをチェック)。次に stripe trigger invoice.payment_failed を発火させ、実際の決済失敗を待たずに督促のパスが動くことを確認します。3D セキュアのカード(4000 0025 0000 3155)は最後に扱ってください。Stripe は認証ステップへリダイレクトし、それをフロントエンドが処理しなければなりません。リダイレクトが静かに失敗すると、セッションは完了せず、webhook も発火しません。

本番移行チェックリスト

テストモードから本番モードへの切り替えは、キー 1 つの差し替えではなく 4 ステップです。

第一に、本番環境の環境変数で、テストキー(sk_test_、pk_test_)を本番キー(sk_live_、pk_live_)に置き換えます。

第二に、https://dashboard.stripe.com/settings/billing/portal で本番モードのカスタマーポータルを設定します。テストモードと本番モードのポータル設定は完全に別物です。テストモードで設定したものは引き継がれません。

第三に、Stripe Dashboard で webhook エンドポイントを本番 URL に設定します。Developers > Webhooks > Add endpoint に進み、https://yourdomain.com/api/stripe-webhook を指定します。本番の webhook 署名シークレットをコピーし、本番環境の STRIPE_WEBHOOK_SECRET に設定します。

第四に、価格 ID を確認します。テストモードの価格(price_test_...)は本番モードには存在しません。ハードコードされた価格 ID は、本番の価格 ID に更新するか、環境変数から読むようにする必要があります。

連携を完了とする前に、実際のカードで本物の決済を 1 回行い(その後で返金して)ください。CLI のトリガーはハンドラのテストには良いものですが、実際の課金ほどフロー全体を確かめてくれるものはありません。

Build This Now が初めから組み込んで出荷するもの

このフローを書いてデバッグするのは、たいていの開発者にとって丸一日かかります。Stripe の checkout エッジ関数、webhook ハンドラ、カスタマーポータルのルート、そして 4 つの環境変数はすべて、Build This Now で初日から事前に配線されています。連携は Supabase Edge Functions にデプロイされ、テスト済みで、あなたが最初のカスタム機能を書く前から動いています。

Stripe は難しい部分ではありません。すべてのピースを正しい順番で繋ぐことが難しいのです。一度やってしまえば、どこに落とし穴があるかわかります。

Continue in Workflow

  • エージェント型コマース:AI エージェントが支払えるアプリの作り方
    2026年のエージェント型コマースをわかりやすく解説するガイド。x402、ACP、Machine Payments Protocol が何をするのか、そして AI エージェントが購入できる有料 API を週末で出荷するための手順を紹介します。
  • Claude Code ベストプラクティス
    Claude Codeで成果を出すエンジニアを分ける5つの習慣: PRD、モジュラーなCLAUDE.mdのルール、カスタムスラッシュコマンド、/clearリセット、そしてシステム進化の思考法。
  • Claude Code オートモード
    2つ目の Sonnet モデルが、Claude Code のすべてのツール呼び出しを実行前に審査します。オートモードがブロックするもの・許可するもの、そして settings.json に追加される許可ルールについて解説します。
  • Channels、Routines、Teleport、Dispatch
    Anthropic が2026年3月と4月に出荷した4つの Claude Code 機能。これらは CLI を、スマホ・ウェブ・デスクトップをまたぐイベント駆動の調整レイヤーに変えます。
  • Claude Code 1M Context in Practice: When Bigger Isn't Better
    The 1M-token context window is GA at flat pricing, but bigger isn't always better. A decision framework, token-cost math, and when to use /compact, subagents, and dynamic workflows instead.
  • Claude Code Channels
    プラグイン MCPサーバーを使って Claude Code を Telegram、Discord、iMessage に接続する方法。セットアップの手順と、接続する価値のある非同期モバイルワークフローを解説します。

More from Handbook

  • エージェントの基礎
    Claude Codeでスペシャリストエージェントを構築する5つの方法:タスクサブエージェント、.claude/agents YAML、カスタムスラッシュコマンド、CLAUDE.mdペルソナ、パースペクティブプロンプト。
  • エージェント・ハーネス・エンジニアリング
    ハーネスとは、AIエージェントを構成するモデル以外のすべての層のことです。5つの制御レバー、制約のパラドックス、そしてなぜハーネス設計がモデルよりもエージェントのパフォーマンスを左右するのかを学びましょう。
  • エージェントパターン
    オーケストレーター、ファンアウト、バリデーションチェーン、スペシャリストルーティング、プログレッシブリファインメント、ウォッチドッグ。Claude Code のサブエージェントを組み合わせる6つのオーケストレーション形状。
  • エージェントチームのベストプラクティス
    Claude Code エージェントチームの実証済みパターン。コンテキストが豊富なスポーンプロンプト、適切なサイズのタスク、ファイルオーナーシップ、デリゲートモード、v2.1.33〜v2.1.45 の修正内容。

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。

Claude Code オートモード

2つ目の Sonnet モデルが、Claude Code のすべてのツール呼び出しを実行前に審査します。オートモードがブロックするもの・許可するもの、そして settings.json に追加される許可ルールについて解説します。

フィードバックループ

コードを書き、テストまたは開発コマンドを実行し、出力を読み取り、壊れたものを修正し、スイートがグリーンになるまでループするプロンプトをClaude Codeに一つ渡す。

On this page

始める前に必要なもの
Checkout Sessions 対 Payment Intents
Checkout フローを作る
Webhook:みんなが間違える部分
カスタマーポータルのセットアップ
フロー全体をテストする
本番移行チェックリスト
Build This Now が初めから組み込んで出荷するもの

設定をやめて、構築を始めよう。

AIオーケストレーション付きSaaSビルダーテンプレート。