目次
Stripe は何についてもメールを送ってきますが、それは結局「何も知らせていない」のとほとんど同じです。決済の成功、サブスクリプション更新の失敗、チャージバック。どれも同じ受信箱に同じ顔で届き、読むころにはその違いは失われています。
必要なのは通知を増やすことではありません。Stripe の各イベントに、それが本当に持つべき緊急度を与えることです。誰かが支払ったときは静かなプッシュ、更新が失敗したときは時間指定通知、そして回答期限つきの異議申し立てが来たときは電話です。
本当にあなたを必要とする Stripe イベント
すべてのイベントが通知に値するわけではありませんし、値するものどうしも緊急度は同じではありません。
| Stripe イベント | なぜ重要か | 緊急度 |
|---|---|---|
payment_intent.succeeded | 誰かが支払った。知っておきたいが、急ぎではない。 | 通常 |
invoice.payment_failed | 更新に失敗。サブスクリプションが失効する前に再試行の猶予がある。 | 時間指定 |
charge.dispute.created | チャージバック。Stripe はカードネットワークが定めた回答期限を示し、それを逃すと自動的に敗れる。 | 着信 |
payment_intent.payment_failed | 単発の決済が失敗。件数としては有用だが、1 件ずつだとうるさい。 | 通常、または通知しない |
電話に値するのは異議申し立てだけです。それ以外は、あなたが自分で端末を手に取るまで待てます。1 週間後に気づいたチャージバックは、そもそも守れなかったお金です。
ステップ 1 —— 緊急度ごとにチャンネルを作る
Echobell でチャンネルを 3 つ作ります。緊急度はチャンネル単位の設定だからです。
- Stripe · 売上 —— 通常通知。決済成功用
- Stripe · 決済失敗 —— 時間指定
- Stripe · 異議申し立て —— 着信
各チャンネルの設定から webhook URL をコピーしてください。Stripe からはこの 3 つすべてに向けます。
ついでに、それぞれで POST のみ を有効にしておきましょう。Stripe は必ず POST で送信するので、リンクプレビューやアドレスバーの補完によってチャンネルが誤って発火するのを防げます。
ステップ 2 —— Stripe 側にエンドポイントを追加する
Stripe ダッシュボードで Developers → Webhooks → Add endpoint を開き、チャンネル URL を貼り付けて、そのチャンネルが扱うべきイベントだけを選びます。
すべてを 1 つのエンドポイントにまとめるのではなく、チャンネルごとに 1 つ作るのがおすすめです。Stripe はエンドポイントごとにイベントを選べるので、振り分けが Stripe 側で完結し、チャンネル側はシンプルなままにできます。
どうしてもエンドポイントを 1 つにしたい場合は、1 つのチャンネルに向けて条件で絞り込みます。
type == "charge.dispute.created"
条件はテンプレートで使う {{ }} の囲みなしで書きます。
ステップ 3 —— payload を読める形に整える
Stripe が送ってくる JSON はおおよそこの形です。
{
"type": "charge.dispute.created",
"data": {
"object": {
"amount": 4900,
"currency": "usd",
"reason": "fraudulent",
"status": "warning_needs_response"
}
}
}
そこでチャンネルのテンプレートは data.object の中を参照します。
タイトル
異議申し立て:{{data.object.reason}}
本文
{{data.object.amount}} {{data.object.currency}} が異議申し立ての対象
ステータス:{{data.object.status}}
ほぼ全員がはまる落とし穴: Stripe の金額はその通貨の最小単位です。4900 は 49.00 ドルであって、4,900 ドルではありません。Echobell のテンプレートは値をそのまま差し込むので、送信前に割るか、通貨を後ろに書いて「セント」として読むかのどちらかにしてください。数字がひと目で正しくある必要があるなら、割り算は Stripe と Echobell のあいだにあるもの(Worker、自動化ツール、自前のエンドポイント)に置きます。
売上チャンネルは、同じ考え方をもっと短く。
タイトル
+{{data.object.amount}} {{data.object.currency}}
本文
{{data.object.description}}
ステップ 4 —— 実際の入金を待たずにテストする
Stripe CLI から、本物と同じ形のイベントをエンドポイントに撃ち込めます。
stripe trigger payment_intent.succeeded
stripe trigger charge.dispute.created
本番で頼る前にこれをやっておきましょう。「あるはずだと思っていたフィールドが null だったときにテンプレートがどう描画されるか」を確認する一番早い方法でもあります。
この構成でできないこと
売上の前に置く前に、知っておくべき制約が 2 つあります。
Echobell は Stripe の署名を検証しません。 Stripe はすべての webhook に Stripe-Signature ヘッダーで署名し、その検証にはエンドポイントシークレットが必要です。Echobell の webhook はこの検証を行わないため、チャンネルを守っているのは URL だけです。これは秘密情報として扱い、POST のみ を有効なままにし、公開リポジトリやスクリーンショットに貼らないでください。
条件で弱いチェックを足すことはできます。
header["stripe-signature"] != ""
これは「Stripe の形をしたリクエストを何かが送っている」ことは確認できますが、「それが Stripe である」ことは確認できません。偽の通知が(一瞬の混乱ではなく)実害につながるなら、前段に自前のエンドポイントを置いてそこで署名を検証し、そこから Echobell を呼んでください。
これは通知経路であって台帳ではありません。 Stripe は失敗した webhook 配信を再試行しますが、通知は「何が起きたか」の記録ではありません。突合は通知履歴ではなく Stripe に対して行ってください。
よくある質問
Stripe から直接電話をかけてもらえますか?
できません。Stripe が送るのはメールと webhook です。電話にするには、電話を発信できるサービスへ webhook を回す必要があります。
異議申し立ての通知で本当に目が覚めますか?
チャンネルを着信モードにしていれば、はい。着信として届き、集中モードやおやすみモードを貫通して鳴ります。詳しくは重要な通知で iOS の集中モードを貫通させる方法をご覧ください。
共同創業者も同じ通知を受け取れますか?
受け取れます。チャンネルを共有すれば、購読者ごとに通知タイプを選べます。同じイベントについて、あなたは電話で受け、相手は静かなプッシュで受ける、といった使い分けができます。
テストモードはどうなりますか?
Stripe のテストモードのイベントは、テストモードで登録されたエンドポイントにのみ届きます。テストのトラフィックも見たいなら両方に登録し、構成を信頼できるまではテストモードだけに登録しておくのもよいでしょう。
まとめ
チャンネル 3 つ、エンドポイント 3 つ、それぞれにテンプレートが 1 つ。要点は「Stripe から通知が来るようになる」ことではありません——それは元から来ていました。要点は、チャージバックが領収書とまったく同じ顔をするのをやめる、ということです。
iPhone 版 Echobell をダウンロード、または Google Play で入手して、stripe trigger charge.dispute.created を一度実行し、わざと電話を鳴らしてみてください。