jpskill.com
🛠️ 開発・MCP コミュニティ

stripe-payments

Stripeを活用し、決済処理、定期購入、チェックアウト機能などをアプリケーションに組み込むSkill。

📜 元の英語説明(参考)

Stripe integration for payments, subscriptions, and checkout. Use when user mentions "stripe", "payment processing", "checkout", "subscriptions", "stripe webhooks", "payment intent", "stripe CLI", "billing", "stripe elements", or integrating payments into an application.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Stripeを活用し、決済処理、定期購入、チェックアウト機能などをアプリケーションに組み込むSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-17
取得日時
2026-05-17
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Stripe Payments

セットアップ

APIキー

Stripeは、公開可能(クライアントサイド)と秘密(サーバーサイド)の2つのキーペアを使用します。

  • ダッシュボード: https://dashboard.stripe.com/apikeys
  • テストキーは pk_test_sk_test_ で始まります
  • ライブキーは pk_live_sk_live_ で始まります
  • 秘密キーは環境変数に保存し、ソースコードには決して含めないでください
  • 制限付きキー: 特定のサービスに対して限定された権限を持つキーを作成します
export STRIPE_SECRET_KEY="sk_test_..."
export STRIPE_PUBLISHABLE_KEY="pk_test_..."

SDKのインストール

# Node.js
npm install stripe

# Python
pip install stripe

テストモード

テストキーで行われたすべてのAPI呼び出しは、テスト環境にヒットします。実際の課金は発生しません。開発とCIにはテストモードを使用してください。本番環境でのみライブキーに切り替えてください。

Stripe CLI

# インストール
brew install stripe/stripe-cli/stripe

# ログイン
stripe login

# ローカルでWebhookをリッスン
stripe listen --forward-to localhost:4242/webhook

# テストイベントをトリガー
stripe trigger payment_intent.succeeded
stripe trigger customer.subscription.created

# 最近のログを表示
stripe logs tail

# リソースを一覧表示
stripe customers list --limit 5
stripe payments list --limit 5
stripe subscriptions list --limit 3

# CLIからリソースを作成
stripe customers create --email="test@example.com"
stripe prices create --unit-amount=2000 --currency=usd --recurring[interval]=month --product=prod_xxx

チェックアウトセッション

1回限りの支払い

const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: { name: 'Widget' },
      unit_amount: 2000, // $20.00 in cents
    },
    quantity: 1,
  }],
  success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: 'https://example.com/cancel',
});

サブスクリプションチェックアウト

const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  success_url: 'https://example.com/success',
  cancel_url: 'https://example.com/cancel',
  customer: 'cus_xxx', // optional, attach to existing customer
});

組み込みチェックアウト

// Server
const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  ui_mode: 'embedded',
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  return_url: 'https://example.com/return?session_id={CHECKOUT_SESSION_ID}',
});
// Return session.client_secret to the frontend

支払いインテント

作成と確認

const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd',
  payment_method: 'pm_card_visa',
  confirm: true,
  automatic_payment_methods: { enabled: true, allow_redirects: 'never' },
});

手動キャプチャ(承認後にキャプチャ)

const intent = await stripe.paymentIntents.create({
  amount: 5000,
  currency: 'usd',
  capture_method: 'manual',
});
// Later, capture the authorized amount
await stripe.paymentIntents.capture(intent.id);

顧客

// 作成
const customer = await stripe.customers.create({
  email: 'user@example.com',
  name: 'Jane Doe',
  metadata: { user_id: '123' },
});

// 更新
await stripe.customers.update('cus_xxx', { name: 'Jane Smith' });

// 支払い方法を紐付け
await stripe.paymentMethods.attach('pm_xxx', { customer: 'cus_xxx' });

// デフォルトの支払い方法を設定
await stripe.customers.update('cus_xxx', {
  invoice_settings: { default_payment_method: 'pm_xxx' },
});

サブスクリプション

作成

const subscription = await stripe.subscriptions.create({
  customer: 'cus_xxx',
  items: [{ price: 'price_xxx' }],
  default_payment_method: 'pm_xxx',
  payment_behavior: 'default_incomplete',
  expand: ['latest_invoice.payment_intent'],
});

更新、キャンセル、トライアル

// プラン変更(日割り計算は自動的に処理されます)
await stripe.subscriptions.update('sub_xxx', {
  items: [{ id: 'si_xxx', price: 'price_new' }],
  proration_behavior: 'create_prorations',
});

// 期間終了時にキャンセル
await stripe.subscriptions.update('sub_xxx', { cancel_at_period_end: true });

// 即時キャンセル
await stripe.subscriptions.cancel('sub_xxx');

// トライアル期間
await stripe.subscriptions.create({
  customer: 'cus_xxx',
  items: [{ price: 'price_xxx' }],
  trial_period_days: 14,
});

従量課金

// 従量制料金の利用状況を報告
await stripe.subscriptionItems.createUsageRecord('si_xxx', {
  quantity: 100,
  timestamp: Math.floor(Date.now() / 1000),
  action: 'increment', // or 'set'
});

Webhook

セットアップ (Node.js / Express)

const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  switch (event.type) {
    case 'checkout.session.completed':
      handleCheckoutComplete(event.data.object);
      break;
    case 'invoice.paid':
      handleInvoicePaid(event.data.object);
      break;
    case 'customer.subscription.deleted':
      handleSubscriptionCanceled(event.data.object);
      break;
  }
  res.json({ received: true });
});

一般的なイベント

  • checkout.session.completed -- 支払いまたはサブスクリプションのチェックアウトが完了しました
  • payment_intent.succeeded -- 支払いが確認されました
  • payment_intent.payment_failed -- 支払いが拒否されました
  • invoice.paid -- サブスクリプションの請求書が支払われました
  • invoice.payment_failed -- サブスクリプションの支払いが失敗しました
  • customer.subscription.created -- 新しいサブスクリプション
  • customer.subscription.updated -- プラン変更、トライアル終了など
  • customer.subscription.deleted -- サブスクリプションがキャンセルされました

リトライロジック

Stripeは、失敗したWebhook配信を72時間にわたって指数関数的バックオフでリトライします。2xxを素早く返してください。時間のかかる処理は非同期で実行してください。冪等性を使用してください。

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Stripe Payments

Setup

API Keys

Stripe uses two key pairs: publishable (client-side) and secret (server-side).

  • Dashboard: https://dashboard.stripe.com/apikeys
  • Test keys start with pk_test_ and sk_test_
  • Live keys start with pk_live_ and sk_live_
  • Store secret keys in environment variables, never in source code
  • Restricted keys: create keys with limited permissions for specific services
export STRIPE_SECRET_KEY="sk_test_..."
export STRIPE_PUBLISHABLE_KEY="pk_test_..."

Install SDKs

# Node.js
npm install stripe

# Python
pip install stripe

Test Mode

All API calls made with test keys hit the test environment. No real charges occur. Use test mode for development and CI. Switch to live keys only in production.

Stripe CLI

# Install
brew install stripe/stripe-cli/stripe

# Login
stripe login

# Listen for webhooks locally
stripe listen --forward-to localhost:4242/webhook

# Trigger test events
stripe trigger payment_intent.succeeded
stripe trigger customer.subscription.created

# View recent logs
stripe logs tail

# List resources
stripe customers list --limit 5
stripe payments list --limit 5
stripe subscriptions list --limit 3

# Create resources from CLI
stripe customers create --email="test@example.com"
stripe prices create --unit-amount=2000 --currency=usd --recurring[interval]=month --product=prod_xxx

Checkout Sessions

One-Time Payment

const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: { name: 'Widget' },
      unit_amount: 2000, // $20.00 in cents
    },
    quantity: 1,
  }],
  success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: 'https://example.com/cancel',
});

Subscription Checkout

const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  success_url: 'https://example.com/success',
  cancel_url: 'https://example.com/cancel',
  customer: 'cus_xxx', // optional, attach to existing customer
});

Embedded Checkout

// Server
const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  ui_mode: 'embedded',
  line_items: [{ price: 'price_xxx', quantity: 1 }],
  return_url: 'https://example.com/return?session_id={CHECKOUT_SESSION_ID}',
});
// Return session.client_secret to the frontend

Payment Intents

Create and Confirm

const paymentIntent = await stripe.paymentIntents.create({
  amount: 2000,
  currency: 'usd',
  payment_method: 'pm_card_visa',
  confirm: true,
  automatic_payment_methods: { enabled: true, allow_redirects: 'never' },
});

Manual Capture (authorize then capture)

const intent = await stripe.paymentIntents.create({
  amount: 5000,
  currency: 'usd',
  capture_method: 'manual',
});
// Later, capture the authorized amount
await stripe.paymentIntents.capture(intent.id);

Customers

// Create
const customer = await stripe.customers.create({
  email: 'user@example.com',
  name: 'Jane Doe',
  metadata: { user_id: '123' },
});

// Update
await stripe.customers.update('cus_xxx', { name: 'Jane Smith' });

// Attach a payment method
await stripe.paymentMethods.attach('pm_xxx', { customer: 'cus_xxx' });

// Set default payment method
await stripe.customers.update('cus_xxx', {
  invoice_settings: { default_payment_method: 'pm_xxx' },
});

Subscriptions

Create

const subscription = await stripe.subscriptions.create({
  customer: 'cus_xxx',
  items: [{ price: 'price_xxx' }],
  default_payment_method: 'pm_xxx',
  payment_behavior: 'default_incomplete',
  expand: ['latest_invoice.payment_intent'],
});

Update, Cancel, Trials

// Change plan (proration handled automatically)
await stripe.subscriptions.update('sub_xxx', {
  items: [{ id: 'si_xxx', price: 'price_new' }],
  proration_behavior: 'create_prorations',
});

// Cancel at period end
await stripe.subscriptions.update('sub_xxx', { cancel_at_period_end: true });

// Cancel immediately
await stripe.subscriptions.cancel('sub_xxx');

// Trial period
await stripe.subscriptions.create({
  customer: 'cus_xxx',
  items: [{ price: 'price_xxx' }],
  trial_period_days: 14,
});

Metered Billing

// Report usage for a metered price
await stripe.subscriptionItems.createUsageRecord('si_xxx', {
  quantity: 100,
  timestamp: Math.floor(Date.now() / 1000),
  action: 'increment', // or 'set'
});

Webhooks

Setup (Node.js / Express)

const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  try {
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  switch (event.type) {
    case 'checkout.session.completed':
      handleCheckoutComplete(event.data.object);
      break;
    case 'invoice.paid':
      handleInvoicePaid(event.data.object);
      break;
    case 'customer.subscription.deleted':
      handleSubscriptionCanceled(event.data.object);
      break;
  }
  res.json({ received: true });
});

Common Events

  • checkout.session.completed -- payment or subscription checkout finished
  • payment_intent.succeeded -- payment confirmed
  • payment_intent.payment_failed -- payment declined
  • invoice.paid -- subscription invoice paid
  • invoice.payment_failed -- subscription payment failed
  • customer.subscription.created -- new subscription
  • customer.subscription.updated -- plan change, trial end, etc.
  • customer.subscription.deleted -- subscription canceled

Retry Logic

Stripe retries failed webhook deliveries over 72 hours with exponential backoff. Return 2xx quickly. Process long-running work asynchronously. Use idempotency checks to handle duplicate deliveries.

Products and Prices

// Create a product
const product = await stripe.products.create({
  name: 'Pro Plan',
  description: 'Full access to all features',
});

// One-time price
await stripe.prices.create({
  product: product.id,
  unit_amount: 4999,
  currency: 'usd',
});

// Recurring price
await stripe.prices.create({
  product: product.id,
  unit_amount: 1999,
  currency: 'usd',
  recurring: { interval: 'month' },
});

// Metered price
await stripe.prices.create({
  product: product.id,
  currency: 'usd',
  recurring: { interval: 'month', usage_type: 'metered' },
  billing_scheme: 'per_unit',
  unit_amount: 10, // $0.10 per unit
});

Stripe Elements

Payment Element (recommended)

// Client-side
const stripe = Stripe('pk_test_...');
const elements = stripe.elements({
  clientSecret: 'pi_xxx_secret_xxx',
  appearance: {
    theme: 'stripe', // 'stripe', 'night', 'flat'
    variables: { colorPrimary: '#0570de' },
  },
});
const paymentElement = elements.create('payment');
paymentElement.mount('#payment-element');

// On form submit
const { error } = await stripe.confirmPayment({
  elements,
  confirmParams: { return_url: 'https://example.com/complete' },
});

Card Element (legacy, simpler)

const cardElement = elements.create('card');
cardElement.mount('#card-element');

const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, {
  payment_method: { card: cardElement },
});

Refunds

// Full refund
await stripe.refunds.create({ payment_intent: 'pi_xxx' });

// Partial refund
await stripe.refunds.create({ payment_intent: 'pi_xxx', amount: 500 });

// With reason
await stripe.refunds.create({
  payment_intent: 'pi_xxx',
  reason: 'requested_by_customer', // or 'duplicate', 'fraudulent'
});

Invoices

// Create a draft invoice
const invoice = await stripe.invoices.create({ customer: 'cus_xxx' });

// Add line items
await stripe.invoiceItems.create({
  customer: 'cus_xxx',
  invoice: invoice.id,
  amount: 2500,
  currency: 'usd',
  description: 'Consulting (1 hour)',
});

// Finalize
await stripe.invoices.finalizeInvoice(invoice.id);

// Send to customer
await stripe.invoices.sendInvoice(invoice.id);

// Pay an invoice directly
await stripe.invoices.pay(invoice.id);

Python Integration

import stripe
stripe.api_key = "sk_test_..."

# Checkout session
session = stripe.checkout.Session.create(
    mode="payment",
    line_items=[{"price": "price_xxx", "quantity": 1}],
    success_url="https://example.com/success",
    cancel_url="https://example.com/cancel",
)

# Payment intent
intent = stripe.PaymentIntent.create(amount=2000, currency="usd")

# Customer
customer = stripe.Customer.create(email="user@example.com")

# Webhook verification (Flask)
import flask
@app.route("/webhook", methods=["POST"])
def webhook():
    payload = flask.request.data
    sig = flask.request.headers.get("Stripe-Signature")
    try:
        event = stripe.Webhook.construct_event(payload, sig, endpoint_secret)
    except stripe.error.SignatureVerificationError:
        return "Invalid signature", 400
    if event["type"] == "payment_intent.succeeded":
        handle_payment(event["data"]["object"])
    return "", 200

Testing

Test Card Numbers

Card Number Behavior
Visa (success) 4242424242424242 Succeeds
Visa (decline) 4000000000000002 Generic decline
Auth required 4000002500003155 Requires 3DS
Insufficient 4000000000009995 Insufficient funds
Expired 4000000000000069 Expired card

Use any future expiry date, any 3-digit CVC, and any postal code.

Test Clocks (Subscriptions)

// Create a test clock to simulate time progression
const clock = await stripe.testHelpers.testClocks.create({
  frozen_time: Math.floor(Date.now() / 1000),
});

// Create a customer attached to the test clock
const customer = await stripe.customers.create({
  email: 'test@example.com',
  test_clock: clock.id,
});

// Advance time to trigger renewals, trial ends, etc.
await stripe.testHelpers.testClocks.advance(clock.id, {
  frozen_time: Math.floor(Date.now() / 1000) + 86400 * 32, // +32 days
});

Error Handling

Decline Codes

Handle err.code values: card_declined, expired_card, incorrect_cvc, processing_error, insufficient_funds. Display user-friendly messages; do not expose raw error details.

Idempotency Keys

await stripe.paymentIntents.create(
  { amount: 2000, currency: 'usd' },
  { idempotencyKey: 'order_123' }
);

Use idempotency keys for any create or update operation to prevent duplicate charges on retries. Keys expire after 24 hours.

General Error Pattern

try {
  await stripe.paymentIntents.create({ amount: 2000, currency: 'usd' });
} catch (err) {
  if (err.type === 'StripeCardError') {
    // Card was declined
  } else if (err.type === 'StripeInvalidRequestError') {
    // Invalid parameters
  } else if (err.type === 'StripeAPIError') {
    // Stripe-side issue, retry with backoff
  } else if (err.type === 'StripeRateLimitError') {
    // Too many requests, retry with backoff
  }
}

Common Patterns

SaaS Billing

  1. Create product and recurring prices for each tier.
  2. Use Checkout in subscription mode or create subscriptions directly.
  3. Listen for invoice.paid and customer.subscription.updated webhooks to provision/deprovision access.
  4. Handle upgrades/downgrades via subscriptions.update with proration.
  5. Use cancel_at_period_end for graceful cancellation.

One-Time Purchase

  1. Create a Checkout Session in payment mode.
  2. On checkout.session.completed, fulfill the order.
  3. Store the payment_intent ID for refund reference.

Marketplace (Connect)

  1. Create connected accounts with stripe.accounts.create({ type: 'express' }).
  2. Use payment_intents with transfer_data or on_behalf_of.
  3. Take platform fees via application_fee_amount.
  4. Handle payouts to connected accounts.

Usage-Based Billing

  1. Create a metered price with recurring.usage_type: 'metered'.
  2. Create a subscription with the metered price.
  3. Report usage via subscriptionItems.createUsageRecord.
  4. Stripe invoices at the end of each billing period based on reported usage.