mcpField
S
stripe-integration

stripe-integration

github.com/davila7開発33.1k392 回インストール今日更新
リポジトリ

stripe-integration について

stripe-integrationは、Stripe決済を実装する開発者向けのスキルで、APIの選択、注文処理、サブスクリプション、キーの保護、テストを扱います。Webhookと冪等性を重視し、詳細の確認にはStripeのドキュメントを参照するよう案内します。

主な機能

  1. 01決済場面に応じたStripe APIの選択
  2. 02Webhookによる注文処理とサブスクリプション同期
  3. 03署名検証と重複イベントへの対応
  4. 04重複作成を防ぐ冪等性キーの利用
  5. 05キー、サンドボックス、決済テストの管理

活用シーン

  1. 01Webアプリでの単発決済やサブスクリプションの実装
  2. 02遅延決済、Webhook再試行、イベント順序への対応
  3. 03Stripeキーの保護と連携のテスト

MCP 対応

Stripeの詳細を確認するため、Stripe MCP serverのsearch_stripe_documentationツールを利用するよう案内しています。Stripe MCP serverはAgentにアカウントデータとドキュメント検索を提供し、書き込み操作には確認を求めます。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/davila7/claude-code-templates --skill stripe-integration

インストール後、Claude Code で/stripe-integrationを入力して読み込まれたか確認します。

詳細

Stripe 連携

注文の消失や二重請求、キーの漏えいを防ぐ決済コードを構築するためのガイダンスです。2026 年 10 月時点の Stripe 独自の推奨事項に従っています(パラメーター、イベント名、API バージョンなどの)詳細が重要な場合は、記憶に頼らず、docs.stripe.com または Stripe MCP サーバーの search_stripe_documentation ツールで確認してください。

バージョン

  • 最新の API バージョン:2026-09-30.endive。アカウントのデフォルト設定が変更されてもレスポンス形式が変わらないよう、クライアントで明示的に固定してください。
  • 最新のサーバー SDK:Node.js 23、Python 16、Ruby 20、PHP 22、Java 34、Go 87、.NET 53。クライアントインスタンスを作成してください。グローバルキーのパターン(stripe.api_key = …、Stripe.setApiKey)は、すべての SDK で非推奨です。
  • 既存の連携を新しいバージョンに移行するには、まずAPI バージョンのアップグレードをお読みください。
// lib/stripe.ts
import Stripe from 'stripe';

export const stripe = new Stripe(process.env.STRIPE_API_KEY!, {
  apiVersion: '2026-09-30.endive',
});

API を選ぶ

構築するもの使用するもの
一回限りの決済、シンプルな商品Payment Links(コード不要)または Checkout Sessions
ウェブアプリでの一回限りの決済Checkout Sessions(ホスト型または埋め込み型)
カスタム決済フォームCheckout Sessions と ui_mode: 'custom' + Payment Element
後で使うためにカードを保存Setup Intents
オフセッションでの請求(顧客がその場にいない場合)保存済みの支払い方法を使用する Payment Intents
サブスクリプション、シート、トライアルBilling APIs + Checkout mode: 'subscription' + Customer Portal
新しい従量課金Metronome(Stripe の使用量課金プラットフォーム)。生の Billing Meters は使用しないでください
マーケットプレイスまたはプラットフォームConnect、Accounts v2(/v2/core/accounts)、Stripe ホスト型オンボーディング

Charges API、Sources API、Tokens API、Card Element、plan オブジェクトは使用しないでください。これらは非推奨またはレガシーです。上の表と Prices を使用してください。

ルール

成功ページではなく、ウェブフックから処理を実行する

顧客は決済後、成功ページが読み込まれる前にタブを閉じることがあります。アクセス権の付与、メールの送信、注文の記録は、ウェブフックハンドラー内でのみ行ってください。

  • checkout.session.completed と checkout.session.async_payment_succeeded を処理してください。session.payment_status !== 'unpaid' の場合にのみ、注文を処理してください。銀行口座からの引き落としなど、決済に時間がかかる方法では、未払いのまま completed が送信されます。
  • これらの決済失敗には checkout.session.async_payment_failed を処理してください。
  • サブスクリプションでは、customer.subscription.created|updated|deleted、invoice.paid、invoice.payment_failed が必要です。更新、督促、キャンセルは、この方法でのみ通知されます。
  • ウェブフックはリリース前に必須です。後回しにしないでください。
すべてのウェブフック署名を未加工のボディで検証する

署名の検証には、Stripe が送信した正確なバイト列が必要です。ボディ解析ミドルウェアを使うと検証できなくなります。

// Next.js App Router: app/api/stripe/webhook/route.ts
import Stripe from 'stripe';
import { stripe } from '@/lib/stripe';

export async function POST(req: Request) {
  const body = await req.text(); // raw body, do not use req.json()
  const signature = req.headers.get('stripe-signature');
  if (!signature) return new Response('missing signature', { status: 400 });

  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      process.env.STRIPE_WEBHOOK_SECRET!,
    );
  } catch {
    return new Response('invalid signature', { status: 400 });
  }

  switch (event.type) {
    case 'checkout.session.completed':
    case 'checkout.session.async_payment_succeeded': {
      // Re-fetch instead of trusting the payload snapshot.
      const session = await stripe.checkout.sessions.retrieve(event.data.object.id);
      // fulfillOrder must be idempotent: the same event can arrive twice.
      if (session.payment_status !== 'unpaid') await fulfillOrder(session.id);
      break;
    }
    case 'checkout.session.async_payment_failed':
      await markPaymentFailed(event.data.object.id);
      break;
  }
  return new Response(null, { status: 200 });
}
  • Cloudflare Workers、Deno、Bun では await stripe.webhooks.constructEventAsync(...) を使用してください。
  • Express では、ウェブフックルートのみに express.raw({ type: 'application/json' }) をマウントし、グローバルな express.json() より前に配置してください。
  • ライブモードでは、Stripe は最大 3 日間再試行し、同じイベントを複数回、または順不同で配信することがあります。fulfillOrder を冪等にしてください(処理済みのイベント ID またはセッション ID を一意制約付きで保存します)。イベントの順序ではなく、オブジェクトの現在の状態に基づいて判断してください。
  • 速やかに 2xx を返し、時間のかかる処理はキューに移してください。
すべての作成処理で冪等性キーを使用する

ネットワークの再試行時に冪等性キーがないと、請求やサブスクリプションが二重に作成される可能性があります。

await stripe.paymentIntents.create(
  { amount: 2000, currency: 'usd', customer: customerId },
  { idempotencyKey: `order-${orderId}-charge` },
);

キーは試行ごとのランダム値ではなく、自分のレコード(注文 ID、ユーザー ID + アクション)から導出してください。そうしないと、再試行時に新しいキーが使われます。

支払い方法の選択は Stripe に任せる

payment_method_types(['card'] も含む)を渡さないでください。省略すると、ダッシュボードで設定した動的な支払い方法が有効になります。リストを絞るには、Payment Intents と Setup Intents で payment_method_configuration、excluded_payment_method_types、または allowed_payment_method_types を使用してください。例外は Terminal のみです。payment_method_types: ['card_present'] を使用してください。

Stripe オブジェクトを ID で自分のレコードに紐付ける

Stripe Customer、Subscription、Checkout Session の ID を独自の行に保存し、それらの ID を使って Webhook イベントを照合してください。metadata(たとえば、セッションの client_reference_id や metadata.orderId)はフォールバックとして使用し、主な紐付けには使わないでください。

サブスクリプションの状態を同期する

上記のサブスクリプション Webhook で更新されるデータベースからアクセス権を読み取り、判断にサブスクリプションの状態が関わる場合は、Stripe からサブスクリプションを再取得してください。アップグレード、ダウングレード、解約、カード情報の更新には、それらの画面を自作せず、Customer Portal を使用してください。プランごとに 1 つの Product を作成し、複数の Price を関連付けるのは、同一プランのバリエーション(月次、年次、通貨)の場合に限ってください。Payment Intents のみを使った更新処理を構築しないでください。リトライと督促は Billing が処理します(Dashboard で Smart Retries とメールを設定してください)。

const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  customer: stripeCustomerId,
  line_items: [{ price: priceId, quantity: 1 }],
  subscription_data: { trial_period_days: 14 },
  success_url: `${baseUrl}/billing/success?session_id={CHECKOUT_SESSION_ID}`,
  cancel_url: `${baseUrl}/pricing`,
});
税金

automatic_tax: { enabled: true } を設定しても、顧客の管轄区域に対するアカウントの税務登録が有効になるまでは、税金は徴収されず、エラーも返されません。税金が有効だと伝える前に、登録状況を確認してください。

キーとセキュリティ

  • 完全なシークレットキー(sk_)よりも、各サービスに必要な権限のみを付与した制限付き API キー(rk_)を優先してください。環境ごとに別のキーを使用してください。
  • キーはプラットフォームのシークレットストア(Cloudflare と Vercel のシークレット、AWS Secrets Manager、GCP Secret Manager、Azure Key Vault)に保管してください。ソースコード、クライアントコード、モバイルアプリ、ログ、エラーメッセージには絶対に含めないでください。リポジトリ内で [sr]k_live_ に一致する文字列は本番キーです。直ちにローテーションしてください。
  • Webhook 署名シークレット(whsec_)は API キーと同様に扱ってください。
  • sk_ および rk_ の文字列を対象とした、コミット前のシークレットスキャンを追加してください。
  • script-src、frame-src、connect-src で https://*.stripe.com を許可する Content-Security-Policy を送信してください。
  • Connect OAuth フローでは、ランダムな state 値を送信して検証してください。

テスト

  • アカウントで共有されるテストモードではなく、開発者または CI ジョブごとに 1 つの sandbox を使って開発してください。stripe sandbox create を実行すると、サインアップせずに作成できます。
  • イベントをローカルに転送します:stripe listen --forward-to localhost:3000/api/stripe/webhook(使用する whsec_ が表示されます)。続けて stripe trigger checkout.session.completed を実行します。
  • テストカード:4242 4242 4242 4242 は成功します。4000 0025 0000 3155 は 3D Secure が必要です。4000 0000 0000 9995 は拒否されます(残高不足)。
  • テストクロックを使って、サブスクリプションの更新や支払い失敗をシミュレートしてください。
  • リリース前に go-live checklist を確認し、処理するイベントのみを設定した本番 Webhook エンドポイントを登録してください。

ツール

  • Stripe MCP サーバー(https://mcp.stripe.com、OAuth)を使うと、エージェントがアカウントデータやドキュメント検索を利用できます:npx claude-code-templates@latest --mcp devtools/stripe。
  • MCP 経由で書き込みや資金移動を行う前に確認するよう設定してください: npx claude-code-templates@latest --setting permissions/stripe-mcp-confirm-writes。
  • 会社の設立:Stripe Atlas(Delaware C corp または LLC)は、MCP(atlas_company_formation)または CLI(stripe plugin install tools を実行し、続けて stripe tools create_atlas_application を実行)から開始できます。Atlas はすべての入力値を検証します。本人確認、支払い、署名、申請は Stripe Dashboard で行います。法人形態、株式、ベスティングに関する創業者の決定を記録してください。ユーザーに代わって決定しないでください。
  • Stripe は、自社で保守するエージェントスキル(npx skills add https://docs.stripe.com または stripe agent setup)も公開しています。これには stripe-best-practices と upgrade-stripe が含まれます。

関連スキル

相性の良いスキル:nextjs-supabase-auth、nextjs-app-router-patterns、supabase-postgres-best-practices、api-security-best-practices

コメント