最初の一通を、決済が失敗した直後に送ってはいけない。
設計で一番迷ったのが、ここだった。
直後に送ると、何もしていない人を疑うことになる
決済が落ちる理由には、一度きりのものがある。通信が切れた。カード会社側で一時的に弾かれた。処理が混んでいた。
こういうときは、Stripe が自動でリトライすれば通る。本人は何も気づかないまま、何もしないまま解決する。
Smart Retries の推奨設定は、2 週間のあいだに 8 回だ。いつ叩き直すかは Stripe が決める。ダッシュボードで自前のスケジュールに切り替えることもできるが、そちらは最大 3 回までしか組めない。
そこに「お支払いができませんでした」と送ったらどうなるか。
何もしていない人に、支払えていないと告げることになる。
放っておけば通る失敗に、わざわざ 1 通を割いたことになる。相手からすると「一瞬止まったらしいが、もう直っているらしい」という意味のない通知が届いただけだ。
この手のツールで一番信用を落とすのは、たぶんこれだ。だから DAY 0 は何も送らない。
送らない判断ができることが、送るツールの信頼性そのものだと思っている。
待っても通らない失敗が、混ざっていた
ここまで書いてから公式ドキュメントを読み直して、前提がひとつ崩れた。
Stripe は、カード会社が「ハードデクライン」を返した失敗をリトライしない。正確には、リトライの予定は入るし attempt_count も増えるのだが、新しい決済手段が登録されるまで、その予定は実行されない。
該当するコードは 9 つある。
incorrect_number
lost_card
pickup_card
stolen_card
revocation_of_authorization
revocation_of_all_authorizations
authentication_required
highest_risk_level
transaction_not_allowed
カードを紛失して止めた。盗難で再発行した。番号を打ち間違えている。この人たちは、何日待っても通らない。
つまり「待てば直る失敗」と「待っても直らない失敗」が、同じ invoice.payment_failed で飛んでくる。
DAY 0 を空けるという設計そのものは変えない。ただ、後者に対して 1 日待つのは、ただの遅れだ。
決済手段が 1 つも登録されていない場合と、インド発行のカード、Connect アカウントの連携が切れている場合も、Stripe はリトライしない。予定が残るのかどうかまでは書かれていないが、待っても通らないことは変わらない。
設計メモには「attempt_count が増えていればリトライが走っている」と書いていた。増えているのに一度も叩かれていない状態があるとは、思っていなかった。
Stripe が先に送っていた
もうひとつ、設計の前提を壊すものが見つかった。
Stripe には「カード支払いが失敗した場合にメールを送信」という設定がある。売上回収の設定ページにある。これを有効にしていると、Stripe 自身が、失敗のたびに顧客へメールを送る。
DAY 0 に何も送らない、と決めたところで、Stripe の側から DAY 0 の一通が出ていく。
churndown を入れるなら、この設定を切ってもらうことになる。導入手順に 1 行増えた。
ただし切る順番は間違えないようにする。churndown 側の送信が落ちている状態で Stripe の通知も切ってあると、顧客には何も届かない。最初はしばらく二重で送らせて、こちらが確実に動いているのを見てから切ってもらう。
ついでに、カードの有効期限切れは期限の 1 か月前に Stripe が自動で通知している。失敗する前に手を打てる経路が、実はもともとある。
DAY 1 — リンクは 1 つだけ置く
翌日、まだ通っていなければ 1 通目を送る。
書くことは 3 つに絞った。何が起きたか。いくらの請求か。どこを押せば直るか。
リンクは 1 つだけ置く。
「カードを更新する」と「ログインして確認する」と「よくある質問」を並べたくなる。親切に見える。でも選択肢が増えるほど、人はどれも押さない。
直してほしいなら、直す場所だけを出す。
DAY 3 — 読まれていなければ、別のところに送る
同じ場所に同じものを二度送っても、届かない相手には届かない。
メールを開いていないなら、次は LINE に送る。LINE が未読なら、次はメールに送る。チャネルを変える。
日本のサブスクやオンラインサロンでは、お客さんと LINE で繋がっている運営者が少なくない。すでにある接点なら、そこに送るほうが届く。
(LINE 連携は churndown の Phase 2 で、まだ作っていない。最初のバージョンはメールだけで動かす)
DAY 7 — 止まることを、正直に伝える
7 日目が最後の一通になる。
ここでは、このままだとサービスが止まることを書く。脅すのではなく、事実として書く。いつ止まるのか、止まったらどうなるのか、まだ間に合うのか。
ただし、本当に止まるかどうかは Stripe の設定次第だった。リトライを使い切ったあとの遷移は 3 択で、canceled にするか、unpaid にするか、past_due のまま置くかを選ぶ。3 つ目を選んでいる人には、Stripe の側では何も起きない。
そもそも Stripe が決めているのはサブスクリプションの状態と請求書の扱いだけで、実際にサービスへのアクセスを止めるかどうかはアプリ側が書くことだ。止まると書く前に、その人の設定と実装を見る必要がある。
そして、ここで動かない人は追わない。
本当に辞めたい人に 4 通目を送るのは、ただのしつこい業者だ。
回収できる分を取り切ろうとして、辞めたい人まで追いかけ始めると、ツールの性質が変わる。そこは線を引いておく。
更新された瞬間に、全部止める
これが一番大事かもしれない。
カードが更新されたら、送信予定の連絡をすべて取り消す。次の請求日を待たずに、未払いの請求をその場で通し直す。
更新済みの人に催促が届くのが、いちばん印象を悪くする。
「直したのにまだ言ってくる」は、最初から何も送らないより悪い。
ここにも罠があった。Stripe は前回失敗したのと同じフィールドでリトライする。サブスクリプションに default_payment_method が入っているのに、customer.invoice_settings.default_payment_method の側だけ新しいカードで更新すると、Stripe は古いほうを叩き続ける。
顧客から見れば、カードは更新した。システムから見れば、更新されていない。
更新画面をどこに向けるかを間違えると、この状態が作れてしまう。
督促ではなく、案内として書く
文面のトーンをどうするかで、だいぶ迷った。
同じ事実を伝えるのでも、書き方で相手の受け取り方が変わる。
督促は「あなたが払っていない」と書く。案内は「カードが止まっているようだ」と書く。
前者は相手の行為を責める。後者は状況を伝える。**実際、多くの場合は本人の行為ではない。**有効期限が切れただけだ。再発行したまま登録を直していないだけだ。
責められる筋合いのないことで責められると、人は直す気をなくす。
まだ 1 通も送っていない
ここまで書いておいて何だが、churndown はまだコードが存在しない。
この設計が正しいかどうかは、実際に送ってみるまで分からない。DAY 1 が早すぎるかもしれないし、DAY 7 まで待つ必要はないのかもしれない。
だから間隔も文面も、管理画面から変えられるようにするつもりでいる。業種によって適切な距離感が違うはずだ。
決めたのは 1 つだけだ。
失敗した直後には、送らない。
自分の Stripe を開いて、invoice.payment_failed の attempt_count が増えている請求書を 1 件だけ見てほしい。その回数、本当に叩かれているだろうか。
churndown — Stripe の決済失敗を検知して、日本語で連絡し、カードの更新画面まで案内するツールです。まだコードはありません。
30 日後に、作るか作らないかを登録数で決めます。どちらに転んでも結果はこの連載に書きます。
この記事について
一人会社で SaaS を作りながら、経営の判断を Claude Code に手伝わせている記録の続きです。決済リカバリーのツールを作る(か、やめる)ところまでを書いています。
前: 【#14】Stripe の「Connect で繋ぐ」は、もう新規では勧められていなかった
arecore.net の中の人です。受託開発・SES・自社プロダクト開発をやっています。ご相談・フィードバックは arecore.net からどうぞ。