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

stripe-connect

Stripe Connectを活用し、二者間取引のプラットフォーム構築、購入者・販売者間の決済分割、販売者の支払い受け入れ設定、手数料処理、プラットフォームのアカウント管理などを効率化するSkill。

📜 元の英語説明(参考)

Build marketplace and platform payment flows with Stripe Connect. Use when: building two-sided marketplaces, splitting payments between buyers and sellers, onboarding sellers/providers to accept payments, handling platform fees and payouts, or managing connected accounts for a platform.

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

一言でいうと

Stripe Connectを活用し、二者間取引のプラットフォーム構築、購入者・販売者間の決済分割、販売者の支払い受け入れ設定、手数料処理、プラットフォームのアカウント管理などを効率化するSkill。

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

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o stripe-connect.zip https://jpskill.com/download/15426.zip && unzip -o stripe-connect.zip && rm stripe-connect.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15426.zip -OutFile "$d\stripe-connect.zip"; Expand-Archive "$d\stripe-connect.zip" -DestinationPath $d -Force; ri "$d\stripe-connect.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して stripe-connect.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → stripe-connect フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

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

🎯 この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-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

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

Stripe Connect

概要

Stripe Connect を使用すると、プラットフォームは買い手、売り手、およびプラットフォームの間で支払いをルーティングできます。これは、接続されたアカウントの規制遵守 (KYC)、支払い、および税務報告を処理します。

アカウントの種類: | 種類 | オンボーディング | ブランディング | 最適な用途 | |------|------------|----------|----------| | Express | Stripe ホスト | Stripe UI | マーケットプレイス (推奨) | | Standard | OAuth リダイレクト | 売り手のブランディング | 売り手が既存の Stripe アカウントを持っているプラットフォーム | | Custom | 完全にカスタム | あなたの UI | 完全な制御を必要とする大規模なプラットフォーム |

請求の種類: | 種類 | Stripe 手数料を誰が支払うか | 使用する場面 | |------|---------------------|----------| | Direct | 接続されたアカウント | 売り手が完全な制御を望む場合 | | Destination | プラットフォーム | プラットフォームが UX を管理する場合 | | Separate charges + transfers | プラットフォーム | 複雑なルーティングの場合 |

セットアップ

npm install stripe
// lib/stripe.ts
import Stripe from "stripe";

export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: "2024-06-20",
});

// プラットフォームアカウントキー (あなたの Stripe アカウント)
// 接続されたアカウントは、アカウント ID で識別されます

Express アカウント (推奨)

1. 接続されたアカウントを作成する

// POST /api/sellers/onboard
import { stripe } from "@/lib/stripe";

export async function createExpressAccount(email: string) {
  const account = await stripe.accounts.create({
    type: "express",
    email,
    capabilities: {
      card_payments: { requested: true },
      transfers: { requested: true },
    },
    business_type: "individual",
  });

  return account.id; // これを DB の seller.stripeAccountId として保存します
}

2. オンボーディングリンクを生成する

export async function createOnboardingLink(accountId: string, userId: string) {
  const accountLink = await stripe.accountLinks.create({
    account: accountId,
    refresh_url: `${process.env.BASE_URL}/sellers/onboard/refresh?userId=${userId}`,
    return_url: `${process.env.BASE_URL}/sellers/onboard/complete?userId=${userId}`,
    type: "account_onboarding",
  });

  return accountLink.url; // 売り手をここにリダイレクトします
}

// 完全なフロー:
app.post("/api/sellers/onboard", async (req, res) => {
  const { email, userId } = req.body;
  const accountId = await createExpressAccount(email);

  // accountId を DB に保存します
  await db.sellers.update(userId, { stripeAccountId: accountId });

  const url = await createOnboardingLink(accountId, userId);
  res.json({ url });
});

3. オンボーディングステータスを確認する

export async function isSellerOnboarded(accountId: string): Promise<boolean> {
  const account = await stripe.accounts.retrieve(accountId);
  return account.details_submitted && !account.requirements?.currently_due?.length;
}

app.get("/sellers/onboard/complete", async (req, res) => {
  const { userId } = req.query;
  const seller = await db.sellers.findById(userId);
  const onboarded = await isSellerOnboarded(seller.stripeAccountId);

  if (onboarded) {
    await db.sellers.update(userId, { status: "active" });
    res.redirect("/dashboard?onboarded=true");
  } else {
    // 売り手が完了しなかった場合 — 完了プロンプトを表示します
    res.redirect("/sellers/onboard/pending");
  }
});

買い手への請求

Destination Charges (プラットフォームが回収し、売り手に送信)

// POST /api/payments/charge
export async function chargeWithDestination({
  amount,          // セント単位
  currency = "usd",
  paymentMethodId,
  customerId,
  sellerAccountId,
  platformFeePercent = 15,
}: {
  amount: number;
  currency?: string;
  paymentMethodId: string;
  customerId: string;
  sellerAccountId: string;
  platformFeePercent?: number;
}) {
  const platformFee = Math.round(amount * (platformFeePercent / 100));

  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency,
    customer: customerId,
    payment_method: paymentMethodId,
    confirm: true,
    transfer_data: {
      destination: sellerAccountId, // 純額を売り手にルーティングします
    },
    application_fee_amount: platformFee, // プラットフォームがこれを保持します
    automatic_payment_methods: { enabled: true, allow_redirects: "never" },
  });

  return paymentIntent;
}

Direct Charges (売り手の Stripe アカウント)

// 請求は売り手の Stripe ダッシュボードに表示されます。プラットフォームは手数料を受け取ります
export async function directCharge({
  amount,
  paymentMethodId,
  sellerAccountId,
  platformFeePercent = 10,
}: {
  amount: number;
  paymentMethodId: string;
  sellerAccountId: string;
  platformFeePercent?: number;
}) {
  const platformFee = Math.round(amount * (platformFeePercent / 100));

  const paymentIntent = await stripe.paymentIntents.create(
    {
      amount,
      currency: "usd",
      payment_method: paymentMethodId,
      confirm: true,
      application_fee_amount: platformFee,
    },
    {
      stripeAccount: sellerAccountId, // 売り手の代わりに作成します
    }
  );

  return paymentIntent;
}

Separate Charges + Transfers (最も柔軟)

// 1. プラットフォームアカウントで買い手に請求する
const paymentIntent = await stripe.paymentIntents.create({
  amount: 10000, // $100
  currency: "usd",
  payment_method: paymentMethodId,
  confirm: true,
});

// 2. 後で: 売り手に送金する (例: サービス提供後)
export async function payoutToSeller(
  paymentIntentId: string,
  sellerAccountId: string,
  amount: number // 売り手に送る金額 (プラットフォーム手数料後)
) {
  const transfer = await stripe.transfers.create({
    amount,
    currency: "usd",
    destination: sellerAccountId,
    source_transaction: paymentIntentId, // 送金を元の請求にリンクします
  });
  return transfer;
}

支払い

自動支払い (デフォルト)

デフォルトでは、Stripe は売り手の支払いスケジュールに基づいて、売り手に自動的に支払います。追加のコードは必要ありません。


// 接続されたアカウントの支払いスケジュールを確認する
const account = await stripe.accounts.retrieve(sellerAccountId);
console.log(account.settings?.payouts?.schedule);
// { interval: "daily" | "weekly" | "m

(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Stripe Connect

Overview

Stripe Connect enables platforms to route payments between buyers, sellers, and your platform. It handles regulatory compliance (KYC), payouts, and tax reporting for connected accounts.

Account types: | Type | Onboarding | Branding | Best for | |------|------------|----------|----------| | Express | Stripe-hosted | Stripe UI | Marketplaces (recommended) | | Standard | OAuth redirect | Seller's branding | Platforms where sellers have existing Stripe accounts | | Custom | Fully custom | Your UI | Large platforms needing full control |

Charge types: | Type | Who pays Stripe fees | Use when | |------|---------------------|----------| | Direct | Connected account | Seller wants full control | | Destination | Platform | Platform manages UX | | Separate charges + transfers | Platform | Complex routing |

Setup

npm install stripe
// lib/stripe.ts
import Stripe from "stripe";

export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: "2024-06-20",
});

// Platform account key (your Stripe account)
// Connected accounts are identified by their account ID

Express Accounts (Recommended)

1. Create a connected account

// POST /api/sellers/onboard
import { stripe } from "@/lib/stripe";

export async function createExpressAccount(email: string) {
  const account = await stripe.accounts.create({
    type: "express",
    email,
    capabilities: {
      card_payments: { requested: true },
      transfers: { requested: true },
    },
    business_type: "individual",
  });

  return account.id; // Store this as seller.stripeAccountId in your DB
}

2. Generate onboarding link

export async function createOnboardingLink(accountId: string, userId: string) {
  const accountLink = await stripe.accountLinks.create({
    account: accountId,
    refresh_url: `${process.env.BASE_URL}/sellers/onboard/refresh?userId=${userId}`,
    return_url: `${process.env.BASE_URL}/sellers/onboard/complete?userId=${userId}`,
    type: "account_onboarding",
  });

  return accountLink.url; // Redirect seller here
}

// Full flow:
app.post("/api/sellers/onboard", async (req, res) => {
  const { email, userId } = req.body;
  const accountId = await createExpressAccount(email);

  // Save accountId to your DB
  await db.sellers.update(userId, { stripeAccountId: accountId });

  const url = await createOnboardingLink(accountId, userId);
  res.json({ url });
});

3. Check onboarding status

export async function isSellerOnboarded(accountId: string): Promise<boolean> {
  const account = await stripe.accounts.retrieve(accountId);
  return account.details_submitted && !account.requirements?.currently_due?.length;
}

app.get("/sellers/onboard/complete", async (req, res) => {
  const { userId } = req.query;
  const seller = await db.sellers.findById(userId);
  const onboarded = await isSellerOnboarded(seller.stripeAccountId);

  if (onboarded) {
    await db.sellers.update(userId, { status: "active" });
    res.redirect("/dashboard?onboarded=true");
  } else {
    // Seller didn't finish — show completion prompt
    res.redirect("/sellers/onboard/pending");
  }
});

Charging Buyers

Destination Charges (Platform collects, sends to seller)

// POST /api/payments/charge
export async function chargeWithDestination({
  amount,          // in cents
  currency = "usd",
  paymentMethodId,
  customerId,
  sellerAccountId,
  platformFeePercent = 15,
}: {
  amount: number;
  currency?: string;
  paymentMethodId: string;
  customerId: string;
  sellerAccountId: string;
  platformFeePercent?: number;
}) {
  const platformFee = Math.round(amount * (platformFeePercent / 100));

  const paymentIntent = await stripe.paymentIntents.create({
    amount,
    currency,
    customer: customerId,
    payment_method: paymentMethodId,
    confirm: true,
    transfer_data: {
      destination: sellerAccountId, // Route net to seller
    },
    application_fee_amount: platformFee, // Platform keeps this
    automatic_payment_methods: { enabled: true, allow_redirects: "never" },
  });

  return paymentIntent;
}

Direct Charges (Seller's Stripe account)

// Charge appears on seller's Stripe dashboard; platform gets fee
export async function directCharge({
  amount,
  paymentMethodId,
  sellerAccountId,
  platformFeePercent = 10,
}: {
  amount: number;
  paymentMethodId: string;
  sellerAccountId: string;
  platformFeePercent?: number;
}) {
  const platformFee = Math.round(amount * (platformFeePercent / 100));

  const paymentIntent = await stripe.paymentIntents.create(
    {
      amount,
      currency: "usd",
      payment_method: paymentMethodId,
      confirm: true,
      application_fee_amount: platformFee,
    },
    {
      stripeAccount: sellerAccountId, // Create on behalf of seller
    }
  );

  return paymentIntent;
}

Separate Charges + Transfers (most flexible)

// 1. Charge buyer on platform account
const paymentIntent = await stripe.paymentIntents.create({
  amount: 10000, // $100
  currency: "usd",
  payment_method: paymentMethodId,
  confirm: true,
});

// 2. Later: transfer to seller (e.g., after service delivered)
export async function payoutToSeller(
  paymentIntentId: string,
  sellerAccountId: string,
  amount: number // amount to send seller (after platform fee)
) {
  const transfer = await stripe.transfers.create({
    amount,
    currency: "usd",
    destination: sellerAccountId,
    source_transaction: paymentIntentId, // Links transfer to original charge
  });
  return transfer;
}

Payouts

Automatic payouts (default)

By default, Stripe automatically pays out to sellers based on their payout schedule. No extra code needed.

// Check payout schedule for a connected account
const account = await stripe.accounts.retrieve(sellerAccountId);
console.log(account.settings?.payouts?.schedule);
// { interval: "daily" | "weekly" | "monthly", ... }

Manual / triggered payouts

// Trigger an instant payout (seller must have instant payouts enabled)
export async function triggerPayout(sellerAccountId: string, amount: number) {
  const payout = await stripe.payouts.create(
    {
      amount,
      currency: "usd",
      method: "instant", // or "standard"
    },
    {
      stripeAccount: sellerAccountId,
    }
  );
  return payout;
}

Check seller balance

export async function getSellerBalance(sellerAccountId: string) {
  const balance = await stripe.balance.retrieve({
    stripeAccount: sellerAccountId,
  });

  return {
    available: balance.available[0]?.amount ?? 0,
    pending: balance.pending[0]?.amount ?? 0,
  };
}

Webhooks for Connect

Connect webhooks can fire for your platform account or for events on connected accounts.

// POST /webhooks/stripe
import { stripe } from "@/lib/stripe";

app.post("/webhooks/stripe", express.raw({ type: "application/json" }), async (req, res) => {
  const sig = req.headers["stripe-signature"] as string;

  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch (err) {
    return res.status(400).send(`Webhook Error: ${(err as Error).message}`);
  }

  // For Connect events, check event.account
  const connectedAccountId = (event as any).account as string | undefined;

  switch (event.type) {
    // Connected account completed onboarding
    case "account.updated": {
      const account = event.data.object as Stripe.Account;
      if (account.details_submitted) {
        await db.sellers.update(
          { stripeAccountId: account.id },
          { status: "active" }
        );
      }
      break;
    }

    // Payment succeeded
    case "payment_intent.succeeded": {
      const pi = event.data.object as Stripe.PaymentIntent;
      await db.orders.update(
        { stripePaymentIntentId: pi.id },
        { status: "paid" }
      );
      break;
    }

    // Payment failed
    case "payment_intent.payment_failed": {
      const pi = event.data.object as Stripe.PaymentIntent;
      await db.orders.update(
        { stripePaymentIntentId: pi.id },
        { status: "failed", failureReason: pi.last_payment_error?.message }
      );
      break;
    }

    // Transfer to seller completed
    case "transfer.created": {
      const transfer = event.data.object as Stripe.Transfer;
      console.log(`Transferred ${transfer.amount} to ${transfer.destination}`);
      break;
    }

    // Payout to seller's bank
    case "payout.paid": {
      const payout = event.data.object as Stripe.Payout;
      console.log(`Payout ${payout.id} paid to ${connectedAccountId}`);
      break;
    }

    // Dispute opened
    case "charge.dispute.created": {
      const dispute = event.data.object as Stripe.Dispute;
      await handleDispute(dispute);
      break;
    }
  }

  res.json({ received: true });
});

Listen to connected account events

// To receive events from connected accounts, configure in Stripe Dashboard:
// Dashboard → Developers → Webhooks → Add endpoint
// Check "Listen to events on Connected accounts"

// Or via API:
const webhookEndpoint = await stripe.webhookEndpoints.create({
  url: "https://myapp.com/webhooks/stripe",
  enabled_events: [
    "account.updated",
    "payment_intent.succeeded",
    "payment_intent.payment_failed",
    "transfer.created",
    "payout.paid",
    "charge.dispute.created",
  ],
  connect: true, // Receive Connect events
});

Refunds

// Refund a payment (from platform to buyer)
export async function refundPayment(
  paymentIntentId: string,
  amount?: number, // omit for full refund
  reason?: "duplicate" | "fraudulent" | "requested_by_customer"
) {
  const refund = await stripe.refunds.create({
    payment_intent: paymentIntentId,
    ...(amount && { amount }),
    ...(reason && { reason }),
    refund_application_fee: true, // Refund your platform fee too
    reverse_transfer: true,       // Reverse transfer to seller
  });
  return refund;
}

OAuth for Standard Accounts

// 1. Redirect seller to Stripe OAuth
export function getStripeOAuthUrl(state: string) {
  return `https://connect.stripe.com/oauth/authorize?` +
    `response_type=code&client_id=${process.env.STRIPE_CLIENT_ID}` +
    `&scope=read_write&state=${state}`;
}

// 2. Handle OAuth callback
app.get("/auth/stripe/callback", async (req, res) => {
  const { code, state } = req.query;

  const response = await stripe.oauth.token({
    grant_type: "authorization_code",
    code: code as string,
  });

  const connectedAccountId = response.stripe_user_id!;
  // Save connectedAccountId to seller record
  res.redirect("/dashboard");
});

Testing

# Use test mode keys (sk_test_...)
# Test card numbers:
# 4242 4242 4242 4242 — success
# 4000 0000 0000 9995 — insufficient funds
# 4000 0025 6000 0001 — requires authentication (3DS)

# Trigger webhooks locally:
stripe listen --forward-to localhost:3000/webhooks/stripe
stripe trigger payment_intent.succeeded

Environment Variables

STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_CLIENT_ID=ca_...  # Only for Standard OAuth
BASE_URL=http://localhost:3000