第3回まで無料

Stripe 決済とサブスクリプション入門コース

カード情報を自分で持たない設計から、Customer・Price・Checkout、Webhook の署名検証と冪等性、支払い失敗と解約、そしてライブへの切り替えと売上の突き合わせまで。全30レッスンで「画面の戻りを信用せず、Webhook で課金の状態を正しく保てる」ところまで進みます。コードとテスト結果は Django 6.1.1・stripe 15.6.1 と Stripe 公式の stripe-mock で実際に動かしたもので、本物の鍵も課金アカウントも要りません。

カリキュラム

全30レッスンを6つの章に分けています。第1章から順に進めるのがおすすめですが、 気になるところだけ拾い読みしてもかまいません。 ※ Django と stripe-python はブラウザ内で実行できないため、手元の仮想環境と stripe-mock で試してください。署名の計算や鍵の点検など、標準ライブラリだけで書ける部分はブラウザ上でそのまま実行できます。

Chapter 1 — 決済の全体像(第1〜5回)

カード情報を自分で持たない設計を最初に決め、テストモードと本番モードの違い、Customer・Product・Price・Subscription の 4 つのオブジェクトを押さえます。最後は購読が指す price から自サイトのプランを逆引きする対応まで作ります。

Chapter 2 — 申し込みを通す(第6〜11回)

自サイトのプランを rank と動画の二軸で定義し、利用者と Stripe の顧客を ID で結んで、Checkout Session から決済画面へ送り出します。最後は client_reference_id で「支払ったのは誰か」を確定させるところまで進みます。

6

プランを rank と動画の二軸で定義する

自サイトのプランを「読める範囲(rank)」と「動画(video)」の二軸で持つ定義。同じ rank の basic と basic_video を plan_sort_key で比べる理由と、受付停止中のプランの扱い。

🔒 ベーシック
7

利用者と顧客をメールでなく ID で結ぶ

自サイトの利用者と Stripe の顧客を、メールアドレスではなく顧客 ID(cus_…)で結ぶ設計。決済のアドレスが登録と違っても、client_reference_id で本人を特定して紐づける流れ。

🔒 ベーシック
8

Checkout Session を作る

Stripe の決済画面への入り口になる Checkout Session。mode=subscription・price・戻り URL・client_reference_id を渡して cs_test_… と飛ばす先の url を受け取る手順と、price の無い free を弾く理由。

🔒 ベーシック
9

ボタンから Checkout へリダイレクトする

申し込みボタンから Checkout Session の url へ 302 で送り出すビュー。受付停止中や知らないプランを手前の 400 で弾く順番と、502・unknown plan のメッセージから原因を絞る読み方。

🔒 ベーシック
10

成功とキャンセルの戻りは表示だけにする

Checkout の後に戻ってくる success_url と cancel_url の扱い。成功画面を踏んでもプランを変えないことをテストで確かめ、反映を Webhook に一本化するための「戻りは表示だけ」という鉄則。

🔒 ベーシック
11

client_reference_id で支払った人を確定する

申し込み時に Checkout へ載せた本人 ID(client_reference_id)を、checkout.session.completed の Webhook でも使って利用者を特定する流れ。顧客 ID・購読 ID の保存と、該当者がいないときに落とさない二段構え。

🔒 ベーシック

Chapter 3 — Webhook で状態を受け取る(第12〜18回)

画面の戻りを信用せず反映を Webhook に一本化する理由から入り、署名検証・改ざんとリプレイの拒否・冪等性・再送の扱いを 1 つずつ固めます。最後は stripe listen を使い、本番の前に手元で通知を受け取れるようにします。

12

画面の戻りを信用しない理由

success_url への戻りが抱える「来ないことがある」「誰でも叩ける」という 2 つの弱点。成功画面では free のまま、Webhook が届いて初めて basic になることのテストと、反映を Webhook に一本化する原則。

🔒 ベーシック
13

Webhook の署名を検証する

Stripe-Signature ヘッダ(t と v1=HMAC-SHA256)の中身と、署名の対象になる「t.本文」。stripe.Webhook.construct_event による検証と、正しい署名なら 200 を返すビュー、本文を作り直さない注意。

🔒 ベーシック
14

署名検証の失敗を 400 で突き返す

署名ヘッダなし・秘密鍵違い・本文の改ざんを、すべて 400 か例外で弾く検証。偽の通知でプランを書き換えさせない理由と、本番で 400 が続くときに疑う 3 か所。

🔒 ベーシック
15

タイムスタンプの許容とリプレイ対策

正しい署名の古い通知を送り直すリプレイ攻撃と、署名に含まれるタイムスタンプによる対策。既定 300 秒の許容、時刻を注入して待たずに書くテスト、サーバの時計ずれの注意。

🔒 ベーシック
16

冪等性で同じ通知の二重処理を防ぐ

Stripe が同じ通知を再送する前提で作る冪等性。処理済みの event.id を ProcessedEvent に記録し、2 回目を duplicate として処理しない仕組みと、冪等性が無いときに起きる二重反映。

🔒 ベーシック
17

再送は 500、対象外は 200 ignored で返す

Webhook の応答コードの意味。反映に失敗したら 500 を返して Stripe に再送させ、対象外のイベントは 200 の ignored で受け流す使い分けと、失敗を握りつぶして 200 を返す誤り。

🔒 ベーシック
18

stripe listen で手元で通知を受け取る

ローカルに届かない Webhook を Stripe CLI の stripe listen で中継する手順。listen が表示する whsec とダッシュボードの whsec の違い、stripe trigger での試し方、受け取る 6 つのイベント。

🔒 ベーシック

Chapter 4 — 購読の一生を扱う(第19〜23回)

購読の開始から、アップグレードと解約予定、支払い失敗の past_due、解約で free へ戻すまでを、届く Webhook ごとに反映します。最後は解約や変更を利用者自身に任せる顧客ポータルを開きます。

19

購読の開始からプラン反映まで

申し込みから有料プランが反映されるまでを、checkout.session.completed と customer.subscription.created の 2 つのイベントでたどる流れ。price からプランを逆引きして active にする反映と、到着順に頼らない作り。

🔒 ベーシック
20

アップグレードと解約予定を受け取る

customer.subscription.updated で届く購読の変化。price の変更でプランを差し替えるアップグレードと、cancel_at_period_end が立った「期末で解約予定」を即解約と取り違えない扱い。

🔒 ベーシック
21

支払い失敗と past_due の猶予

カードの期限切れなどで支払いが失敗したときの扱い。past_due の間はプランを維持して状態だけ写す「すぐ締め出さない」判断と、free に落とすタイミング。

🔒 ベーシック
22

解約で free へ戻す

customer.subscription.deleted を受けて free へ戻す後片付け。プラン・状態・購読 ID を戻しつつ顧客 ID は残す理由と、画面を触らずに free へ戻ることで Webhook の到着を確かめる方法。

🔒 ベーシック
23

顧客ポータルで解約と変更を任せる

解約・プラン変更・カード更新・領収書の取得を利用者自身に任せる Stripe の顧客ポータル。セッションを作って送り出すビューと、rank と動画の二軸による出し分け、先にダッシュボードで設定しておく注意。

🔒 ベーシック

Chapter 5 — 実務の周辺(第24〜27回)

クーポンと割引、請求書から今期の終わりを読む方法、法人向けの別線、特定商取引法の表記と、課金の周りで必ず出てくる実務を扱います。最後は特商法の必須項目の抜けを機械で見つけられるようにします。

Chapter 6 — 本番へ出す(第28〜30回)

テストからライブへの切り替えを機械で点検し、鍵の管理と漏洩したときの手順を決めます。最後は Stripe を正として自サイトのプランとのズレを拾う、売上の突き合わせでコースを締めくくります。

全30レッスンを終えたら、次は課金できるようになったサービスを世に出して回す サービス公開と運用 へ。メンバーシップで全コースが解放されます。