個人開発者のための Stripe Connect 実装ガイド (日本・2026 年版)
ClearNets が運営するチップ決済サービス Merci を本番稼働させるまでに、Stripe Connect Express の実装で得た知見をまとめました。「取引の場」を作る個人開発者にとって、決済プラットフォームを自作するときの現実的な選択肢と落とし穴を、実際の数字と手順で整理します。
1. なぜ Stripe Connect が必要なのか
個人開発者が「複数のユーザー間で金銭のやり取りを仲介するサービス」を作ろうとすると、法的にも技術的にも壁があります。日本では資金決済法により、運営が代金本体を長期間保持したり、独自ポイントを発行したりすると 「資金移動業」または「前払式支払手段発行者」として登録が必要になります。個人事業主が これらの登録をすることは実務上ほぼ不可能です。
これを避けるための一般的な設計が Stripe Connect の separate charges & transfers 方式です。Stripe が決済とマネーフローを管理し、運営は「手数料 (application_fee) のみを 受け取り、原資金は保持しない」立て付けにできます。この設計であれば個人でも合法的に マーケットプレイスやチップ決済を運営できます。
2. 実装コスト (実測)
Merci での Stripe Connect Express 実装に、実際にかかった時間・費用の目安です。
- 初回設計: Connect のアーキテクチャ理解と仕様整理に約 8-12 時間。 Stripe Docs (Connect Overview / Direct Charge vs Destination Charge vs Separate Charges & Transfers) を熟読する必要があります。
- Express アカウント作成 API: 約 2 時間。
accounts.createとaccountLinks.createの 2 段。 - Webhook 受信インフラ: 約 4-6 時間。
account.updated/checkout.session.completed/payment_intent.succeeded/transfer.*/charge.refundedの最低 5-6 イベントを扱う必要があります。二鍵署名検証 (アカウント Webhook + Connect Webhook) を最初から入れておくと後で楽です。 - 返金・係争・テイクダウン対応: 約 8-10 時間。
reverseTransferを正しく扱う設計と、Transfer 前後の状態管理が要点です。 - 本人確認 (KYC) フロー: 実装 4-6 時間 + 初回審査待ち 1-3 営業日。
account.updatedWebhook でcharges_enabled/payouts_enabledを同期して gate に使います。
合計 1-2 週間 (稼働日ベース) を見ておくと現実的です。ドキュメント読解と Webhook 実装が半分以上を占めます。
3. Connect のチャージ方式 3 種の使い分け
Stripe Connect には代表的な 3 種のチャージ方式があり、要件によって選び方が変わります。
- Direct Charge: 資金が Connect アカウント (販売者) に直接入る。運営が 「取り分」だけ application_fee で受ける。運営が原資を持たないため resource-efficient だが、返金・係争は販売者側で発生する。
- Destination Charge: 決済は運営で受けて、そのまま自動で販売者へ transfer される。返金は運営から発動できるが、原資は運営に「一瞬」通過する扱い。
- Separate Charges & Transfers: 決済は運営で受け、後で別途 transfer を実行する。返金や係争が起きた場合、transfer 前なら運営で解決できる。 クリアランス窓を設けられる = 悪意ある販売者や著作権侵害への対処余地が大きい。
ClearNets での選択: Merci はデジタル寄付性 (投げ銭) なので Direct Charge でも良かったが、将来のマーケットプレイス転用も見据えて Separate Charges & Transfers を 採用。teen-earn (スキ活マーケット) も同じ方式で、著作権侵害通報の際に transfer 前で 止められる利点があります。
4. 二鍵署名検証を最初から入れておく
Stripe Webhook の Signing Secret は、実は 2 種類 あります。
- アカウント Webhook:
checkout.session.completed/payment_intent.succeeded/charge.*/*.subscription.*などの通常イベント - Connect Webhook:
account.updated/transfer.*/payout.*などの Connect 固有イベント
両方を「同一 URL」に登録して、Webhook Handler 側で 両方の secret を順に試して verify する 実装にしておくと、Connect イベントが 401 で届かない不具合を防げます (実際に本番でハマった)。二鍵検証は 5 行程度のロジックで書けます。
5. Payment Link と Checkout Session の使い分け
マーケットプレイスや教員/塾向けライセンス販売のような 非ログイン購入者 向けには、Payment Link が便利です。運営側でリンクを作って educator に email で送ると、 educator は Stripe の Checkout に直接遷移して決済できます。ログインを要求しません。
- Payment Link: 永続 URL、教員 email 送付・複数タブで開ける・educator は非ログイン
- Checkout Session: 一回限りのセッション、ログイン済みユーザー向け・metadata が確定
両方とも metadata を payment_intent_data.metadata に載せておくと、 後段の payment_intent.succeeded Webhook で識別できます。Payment Link を使う 場合は restrictions.completed_sessions.limit = 1 にして使い捨てリンク化する のがお勧めです。
6. 冪等性 (Idempotency) は必須
Stripe Webhook は同じイベントを複数回配信することがあります (通常のリトライ・障害復旧など)。 以下の 3 点は必ず入れておくべきです。
- Webhook event の重複判定:
webhook_eventsテーブルにINSERT ... ON CONFLICT DO NOTHING RETURNINGで atomic に lock を取る。 RETURNING が空なら他リクエストが処理済み → skip。 - Transfer 作成の idempotencyKey: Stripe SDK の第 2 引数に
{ idempotencyKey: `transfer:${payoutId}` }を渡す。API 成功 → DB 更新失敗 が起きた場合の二重送金を Stripe 側で dedup。 - Fulfillment の順序: 「order の status 更新」を「download grants 発行」の後に置く。前後を間違えると status=paid だが grants がない中間状態で リトライが空回りする不具合になる (実際にハマった)。
7. 手数料の実効率と料金設計
Stripe (JP) の手数料は 2026 年 8 月時点で以下が目安 (詳細は Stripe 公式を参照):
- クレジットカード決済: 3.6% (国内発行)
- Connect Express: アカウント維持 0.25%/月 + $2/月 (使用時のみ発生)
- Transfer: 追加費用なし (Connect 手数料に含む)
つまり ¥1,000 のチップの場合、Stripe 手数料は約 ¥36。運営がapplication_fee = 15% (= ¥150) を取ると、seller の手取りは ¥1,000 − ¥36 − ¥150 = ¥814。JPY はゼロ小数通貨なので、Stripe API でunit_amount を そのまま円単位 で渡します (×100 しない)。
8. 未成年ユーザーを扱う時の要点
中高生向けサービスの場合、Stripe Connect の名義人は 18 歳以上の成人 である必要があります。保護者名義で Connect アカウントを開設し、実質の販売者 (中高生) は運営側 DB の seller_profiles に紐付け、KYC は保護者に接続する 2 層構造に します。民法 5 条の未成年者取消権にも対応するため、separate charges & transfers でクリアランス窓 (7 日) を設ける のが安全です。 保護者が同意撤回した場合、transfer 前なら運営で全額返金できます。
9. 実務でハマったこと 3 選
- Connect Webhook 二鍵: 最初はアカウント Webhook secret だけで verify していたので、
account.updatedが 401 で届かない不具合が本番で発生。 両 secret を順に試す実装で解決。 - Fulfillment 順序不整合: order.status = 'paid' を先に更新 → download_grants insert 失敗のケースで、購入者が永久 DL 不能になる中間状態が発生。 grants insert を先に、status 更新を後にする順序で解決。
- CSV formula injection: 販売履歴 CSV 出力で、商品名が
=SUM(...)で始まる場合 Excel/Sheets がフォーミュラとして実行してしまう OWASP 脆弱性。先頭=+-@\t\rを'で無害化するエスケープ関数を用意。
10. まとめ
個人開発者が Stripe Connect でマーケットプレイスや投げ銭を作るのは、技術的には 1-2 週間で構築可能、法的には資金決済法の登録不要 という現実的なパスがあります。ただし Webhook の冪等性・二鍵検証・fulfillment 順序・返金/係争の設計は初期から入れておかないと、 後で本番稼働中にバグとして表面化します。本記事の 6-9 節が特に効きます。
ClearNets では Merci でこの型を本番稼働させ、その知見を teen-earn (スキ活マーケット)・ C2 投げ銭・C3 教員向け販売にも横展開しています。同じ型を使い回せると開発コストが 大幅に減ります。
この記事を書いた背景
ClearNets は Merci (チップ決済 SaaS) を運営しており、本記事の内容は 2026 年 7 月に Merci 本番稼働・初回チップの end-to-end 検証を完了した際の実装知見に基づいています。 将来的な仕様変更や個別要件の適合性については Stripe 公式ドキュメントおよび弁護士 相談を推奨します。