Stripe CLIは、Stripeが公開しているコマンドラインツールです。WebhookをローカルのPCへ転送するstripe listen、テスト用のイベントを発生させるstripe trigger、APIリクエストのログを流し見るstripe logs tailが中心の機能で、公開URLを用意しなくても決済まわりの受信処理を手元で確かめられます。この記事では、2026年10月時点の最新版v1.54.0の公式リファレンスをもとに、インストールと認証、Webhookの転送と署名検証、イベントの再現、失敗時の調べ方までを実行できるコマンド付きで解説します。
まとめ|Stripe CLIでWebhookを手元で検証する手順と本番前の注意点
手順は4つです。インストールしてstripe loginで接続し、stripe listen --forward-toで自分のサーバーへイベントを転送し、表示されたwhsec_の署名シークレットをアプリに設定し、別のターミナルからstripe triggerでイベントを送ります。
詰まりやすいのは3点です。v1.50.0より新しい版では、管理者がダッシュボードでCLIアクセスを許可しないとログインできません。listenが出す署名シークレットはダッシュボードに登録したエンドポイントの値とは別物で、取り違えると署名検証が必ず失敗します。triggerは本物のAPIリクエストでイベントを起こすため、顧客や決済のデータがサンドボックスに残ります。
CLIで確かめられるのは、自分のハンドラーの分岐までです。公開URLへの配信と再試行、TLSの設定はステージング環境で別に確かめます。
Stripe CLIのインストールとstripe loginでアカウントへ接続する手順
最初の作業は、CLIを入れて自分のStripeアカウントかサンドボックスに接続することです。
Stripe CLI導入:npm・Homebrew・WinGet・aptの使い分け
Stripe CLIのGitHubリポジトリはGo製のオープンソース(Apache-2.0ライセンス)で、READMEにOS別の導入方法がまとまっています。Node.js 18以上が入っていればnpmが手早く、OSのパッケージ管理に揃えたい場合は次のいずれかを使います。
# npm(macOS・Linux・Windows共通。Node.js 18以上)
npm install -g @stripe/cli
# macOS(Homebrew)
brew install stripe
# Windows(WinGet)
winget install Stripe.StripeCLI
# 導入できたかを確かめる
stripe version
Debian・Ubuntuはapt、RedHat系はyumのリポジトリ登録手順がREADMEにあり、Docker版はstripe/stripe-cliイメージで配布されています。公式のインストール手順によると、スクリプトで導入した場合は同じメジャー版の範囲で自動更新が既定で有効です。チームで版を固定したいときは環境変数STRIPE_NO_AUTO_UPDATE=1で止めます。リリース一覧では2026年10月16日公開のv1.54.0が最新で、9月末から月に数回のペースで版が上がっています。
stripe loginのペアリングコードとv1.50.0超で必要な管理者のCLI許可
stripe loginを実行するとペアリングコードが表示され、ブラウザでStripeダッシュボードが開きます。同じコードであることを確かめて承認すれば接続は完了です。loginコマンドのリファレンスによると、認証情報はOSの安全な資格情報ストアに保存され、セッションは自動で更新されます。
ここで止まる人が多い条件があります。v1.50.0より新しい版では、AdministratorかIAM Adminが、ダッシュボードの「設定」→「チームとセキュリティ」→「MCP and CLI access」でCLIアクセスを有効にしていないと認証できません。開発者が自分の権限だけでログインを試して失敗する場合は、まずこの設定を管理者に確認してもらいます。
ブラウザが使えないCIやコンテナでAPIキーを渡す4つの方法と優先順位
CIやDockerコンテナではブラウザで承認できません。APIキーの渡し方の公式解説は、stripe login --interactiveでの手入力、stripe config --set test_mode_api_keyでの保存、コマンドごとの--api-key、環境変数の4つを挙げています。環境変数STRIPE_API_KEYは他のどの設定よりも優先されます。
CIでは、権限を絞った制限付きキー(rk_test_で始まるキー)をシークレットとして環境変数に入れる運用が安全です。Stripeアカウントがまだ無い段階なら、sandboxコマンドの説明にあるstripe sandbox createで、アカウント登録なしにテスト用キー付きのサンドボックスを作れます。ただし7日で失効するため、stripe sandbox claimで正式なアカウントに移さないとデータは残りません。
stripe listenでWebhookをローカルへ転送し署名検証まで通す手順
CLIの中心機能です。listenコマンドのリファレンスにあるとおり、CLIはStripeのAPIと直接つながってイベントを受け取るため、ダッシュボードにエンドポイントを登録する必要もngrokのようなトンネルも要りません。
–forward-toでlocalhostへ転送し署名用のwhsec_を取得する
アプリがポート4242でPOST /webhookを受ける前提なら、次のように起動します。
stripe listen --forward-to localhost:4242/webhook
# > Ready! Your webhook signing secret is whsec_xxxxxxxx (^C to quit)
# シェルスクリプトから署名シークレットだけを取り出す場合
export STRIPE_WEBHOOK_SECRET=$(stripe listen --print-secret)
表示されるwhsec_の値を、アプリの署名検証用シークレットに設定します。リファレンスによると、この値はlistenを再起動しても変わりません。.envに一度書けば、毎朝の起動のたびに貼り替える作業は要らないということです。--print-secretは値を表示して終了するので、開発用の起動スクリプトに組み込めます。
Node.jsとExpressで生の本文を受けて署名検証するハンドラーの例
StripeのWebhookガイドは、署名検証には加工前のリクエスト本文が必要だと明記しています。Expressで先にexpress.json()を通すと本文がオブジェクトに変換され、検証は必ず失敗します。Webhookのルートだけexpress.raw()で受けるのが要点です。
const express = require('express');
const Stripe = require('stripe');
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
const app = express();
// Webhookのルートだけ生の本文(Buffer)で受ける
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers['stripe-signature'],
process.env.STRIPE_WEBHOOK_SECRET // stripe listen が表示した whsec_
);
} catch (err) {
console.error('署名検証に失敗しました');
return res.status(400).end();
}
if (event.type === 'payment_intent.succeeded') {
// 注文確定などの重い処理はキューへ渡す
}
res.status(200).end();
});
app.listen(4242);
ガイドは、複雑な処理を始める前に2xxを返すよう求めています。同じイベントが2回届いても注文を二重に確定しない作りは、決済Webhookの署名検証と冪等な注文確定で設計から解説しています。
–eventsと–load-from-webhooks-apiで本番受信設定に揃える
何も指定しないlistenは、アカウントのすべてのイベントを転送します。本番で受け取るイベントが限られているなら、--events payment_intent.succeeded,checkout.session.completedのように、カンマ区切りでの絞り込みが可能です。本番に無いイベントが届いて、未対応の分岐ログが大量に出るのを防げます。
ダッシュボードに本番用のエンドポイントを登録済みなら、--load-from-webhooks-apiを付けると、その登録内容に沿ったイベントを受け取れます。Connectのプラットフォームを作っている場合は、連結アカウントのイベントを--forward-connect-toで別のURLへ振り分けられます。
stripe triggerとfixturesでテストイベントを発生させる手順
listenを起動したまま、別のターミナルでイベントを起こします。
payment_intent.succeededを発生させると一緒に届くイベントの確認
triggerコマンドのリファレンスによると、triggerは本物のAPIオブジェクトをもとにイベントを発生させます。payment_intent.succeededを起こすとpayment_intent.createdも届き、invoice.payment_succeededなら顧客・請求明細・請求書が順に作られます。
stripe trigger payment_intent.succeeded
stripe trigger checkout.session.completed
stripe trigger invoice.payment_failed
# 発生させられるイベントの一覧を表示する
stripe trigger --help
listen側の画面には、受け取ったイベントと、自分のサーバーが返したステータスコードが1行ずつ出ます。ここで確かめる対象は、ハンドラーが想定しないイベントで500を返していないかという点です。Webhookガイドは配信順序を保証しないと明記しているため、届いた順に依存した処理になっていないかもこの段階で見ておきます。
–overrideと–addで金額・通貨・顧客を差し替えて日本円で試す
triggerが送る値は、CLIのリポジトリに同梱されたfixtureの既定値です。payment_intent.succeededの場合はamountが2000、currencyがusd(20米ドル)になっています。日本円の決済として受け取りたいときに値を差し替える指定が、--overrideです。日本円は小数点以下の無い通貨なので、500円はamount=500と書きます。
stripe trigger payment_intent.succeeded \
--override payment_intent:amount=500 \
--override payment_intent:currency=jpy
# 既存の顧客に紐づけて発生させる
stripe trigger payment_intent.succeeded --add payment_intent:customer=cus_xxxxxxxx
配列の要素を書き換える場合は"checkout_session:line_items[0].quantity=10"のように角かっこで指定し、シェルが角かっこを解釈しないよう引用符で囲みます。--editを付けると、送る前のfixtureをエディタで直接書き換えられます。
stripe fixturesのJSONで拒否と成功を混ぜたシナリオを再現する
triggerの組み合わせで足りない流れは、fixturesコマンドで自分のJSONに書きます。各リクエストにnameを付けると、後のリクエストで${name:id}のように前の応答を参照できる仕組みです。expected_error_typeを指定したリクエストは、その種類のエラーが返っても止まらずに次へ進みます。
{
"_meta": { "template_version": 0 },
"fixtures": [
{
"name": "customer",
"path": "/v1/customers",
"method": "post",
"params": { "name": "検証用顧客" }
},
{
"name": "pi_declined",
"expected_error_type": "card_error",
"path": "/v1/payment_intents",
"method": "post",
"params": {
"customer": "${customer:id}",
"amount": 500,
"currency": "jpy",
"payment_method_types": ["card"],
"payment_method": "pm_card_visa_chargeDeclined",
"confirm": true
}
},
{
"name": "pi_succeeded",
"path": "/v1/payment_intents",
"method": "post",
"params": {
"customer": "${customer:id}",
"amount": 500,
"currency": "jpy",
"payment_method_types": ["card"],
"payment_method": "pm_card_visa",
"confirm": true
}
}
]
}
stripe fixtures ./retry.jsonで実行すると、拒否の後に再入力で成功するという、決済画面でよく起きる流れのイベントがまとめて届きます。JSONをリポジトリに置けば、チームの全員が同じ順序のイベントで動作を確かめられる形です。pm_card_*の種類と拒否理由の対応はStripeテストカード一覧と使い方にまとめています。
stripe logs tailとevents resendでリクエスト失敗を調べる手順
イベントが届かない、APIが失敗するといった場面では、CLIからログと再送を扱えます。
logs tailのフィルタで4XXのPOSTリクエストだけを抽出する方法
logs tailのリファレンスによると、このコマンドはサンドボックスのAPIリクエストログをリアルタイムに流します。フィルタは組み合わせると全条件に一致したものだけが出るため、失敗した書き込みに絞るなら次の形が実用的です。
stripe logs tail --filter-http-method POST --filter-status-code-type 4XX
# 決済作成のリクエストだけをJSONで出す
stripe logs tail --filter-request-path /v1/payment_intents --format JSON
ログの各行に付くのは、req_で始まるリクエストIDです。ダッシュボードで同じIDを開けば、送ったパラメータとエラーの詳細を確認できます。本番のリクエストログはこのコマンドでは見られないため、本番の調査はダッシュボードで行います。
events resendで過去30日以内のイベントを修正後のハンドラーへ再送
ハンドラーのバグで処理に失敗したイベントは、修正後に同じイベントを送り直して確かめるのが確実です。events resendのリファレンスによると、stripe events resend evt_xxxxxxxxで再送でき、対象は作成から30日以内のイベントに限られます。特定の登録済みエンドポイントへ送り直すときは--webhook-endpoint=we_xxxxxxxxを付けます。
Webhookガイドによると、ダッシュボードの再送ボタンが使えるのは作成から15日までです。16日目以降はCLIを使います。
Stripe CLIの検証で起きる署名エラーと本番との差に関する落とし穴
CLIでの検証が通ったのに本番で失敗する原因は、たいてい次の4つのどれかです。
ダッシュボードとlistenの署名シークレットを取り違えて400になる
最も多い失敗です。Webhookガイドによると、署名シークレットはエンドポイントごとに一意で、同じURLでもテスト用と本番用で値が異なります。listenが出すwhsec_はさらに別の値です。ローカルでは成功していたのに、ステージングで全件400になる場合は、環境変数がlistenの値のまま残っていないかを最初に確かめます。
環境ごとの値をSTRIPE_WEBHOOK_SECRETという同じ名前で管理し、ローカルだけstripe listen --print-secretの出力を入れる運用にすると、取り違えが起きにくくなります。
triggerで作られた顧客や決済がサンドボックスに溜まり続ける
triggerのリファレンスは、イベントをAPIリクエストで起こすため、必要なオブジェクトがすべて実際に作られると注意しています。何度も試すと、顧客一覧や決済一覧が検証用データで埋まります。
レポートや一覧画面の確認も同じサンドボックスで行うなら、Webhook検証用とは別のサンドボックスを用意します。loginのリファレンスにあるstripe switchで、承認済みのアカウントとサンドボックスを切り替えられます。
サンドボックスと本番で異なるWebhook再試行の間隔と回数を見落とす
Webhookガイドによると、本番環境では配信に失敗したイベントを指数バックオフで最長3日間再試行します。サンドボックスでは数時間のうちに3回です。ローカルで確かめているのはハンドラーの分岐であって、本番の再試行の間隔とは別物と考えます。
本番では、障害から復旧した直後に3日分の再試行がまとめて届くことがあります。冪等性の確認は、同じイベントIDをevents resendで2回送る方法で済ませておきます。
–liveを付けたコマンドが本番データを書き換える危険と防ぎ方
listen・trigger・events resendなど多くのコマンドは、既定ではサンドボックスに向きます。--liveを付けると本番へのリクエストになり、stripe customers deleteのような書き込みも本番データに対して実行されます。
開発者の端末には本番の権限を持つセッションを置かないのが基本です。どうしても本番を参照する担当者は、読み取り専用の制限付きキーを--api-keyで都度渡す運用に限ります。
Stripe CLIでの検証を内製するか決済開発の専門会社に任せるかの判断
CLIそのものは無料で、手順も公開されています。分かれ目は、検証すべきイベントの組み合わせの数です。
内製で足りる構成:Checkoutの単発決済とWebhook2〜3種の受信
Checkoutで単発の決済を受け、checkout.session.completedとpayment_intent.payment_failed程度を処理するだけなら、内製で十分です。listenとtriggerで3〜4本のイベントを通し、署名検証と二重処理の防止を確かめれば足ります。実装の流れはStripe Checkoutのセッション作成とWebhookでの注文確定で解説しています。
Stripeでどの実装方式を選ぶかの全体像は、親記事のStripeとは?仕組み・手数料・実装パターンで比べています。
外部に任せる方がよい構成:サブスク・Connect・複数エンドポイント
サブスクの更新と失敗、プラン変更、Connectの連結アカウントのイベント、複数のエンドポイントへの振り分けが重なると、検証すべきイベントは数十種類になります。triggerの既定シナリオでは足りず、fixturesのJSONを業務の流れごとに書き起こす作業が必要です。順序が入れ替わったときの状態遷移まで含めると、設計の段階で決めることが一気に増えます。
決済のイベント設計とテストの経験が社内に無いなら、決済開発の経験がある外部へ任せる方が、リリース後の障害対応より安く済みます。一創では決済・サブスクリプションシステムの開発として、Stripeを使った決済の実装とWebhookの検証設計を支援しています。
Stripe CLIのよくある質問|料金・ngrokとの違い・本番での利用
Stripe CLIを使い始めるときによく出る質問をまとめました。
Stripe CLIは無料で使えますか?
無料で使えます。Stripe CLIはGitHubでApache-2.0ライセンスのオープンソースとして公開されており、CLIの利用料はかかりません。サンドボックスでの決済は実際のお金が動かないため、triggerやfixturesで何度イベントを起こしても費用の発生は無い仕組みです。費用がかかるのは本番環境での実際の決済手数料だけで、これはCLIを使うかどうかとは関係ありません。
ngrokとStripe CLIはどちらでWebhookを試すべきですか?
開発中のハンドラーの分岐を確かめるならStripe CLIで足ります。CLIはStripeのAPIと直接つながるため、ダッシュボードへのエンドポイント登録もトンネルも要りません。一方、公開URLへの実際の配信、TLS証明書、ファイアウォールでのIP許可まで含めて確かめたい場合は、ngrokなどで公開URLを用意するか、ステージング環境にエンドポイントを登録して試します。
stripe listenの署名シークレットは起動のたびに変わりますか?
変わりません。公式リファレンスによると、listenが表示するwhsec_の署名シークレットは再起動しても同じ値です。一度.envに設定すれば使い続けられます。ただし、ダッシュボードに登録したエンドポイントの署名シークレットとは別の値なので、ステージングや本番には持ち込まないでください。
Stripe CLIは本番環境でも使えますか?
使えます。多くのコマンドは--liveを付けると本番へのリクエストになります。ただしstripe logs tailはサンドボックスのログにしか対応していません。本番で書き込みを伴うコマンドを実行すると実データが変わるため、通常の運用では読み取り専用の制限付きキーを使い、調査はダッシュボードと組み合わせて行うのが安全です。
stripe triggerに無いイベントはどうやってテストしますか?
stripe trigger --helpで対応イベントの一覧を確認し、無いものはstripe fixturesで必要なAPIリクエストをJSONに書いて発生させます。たとえば請求書の確定や決済の取り消しは、該当するAPIの呼び出しを並べれば起こせます。既存のtriggerを少し変えたいだけなら、--editで送る前のfixtureを書き換える方法が手早いです。
関連記事
- 決済Webhookとは?仕組み・主要イベントと署名検証・冪等な注文確定の実装を開発視点で解説:listenで受けたイベントを処理する側の設計。
- Stripeテストカード一覧と使い方:3Dセキュア・決済拒否・不審請求をテストする手順:fixturesで指定するpm_card_*と拒否理由の対応。
- Stripe APIの使い方:PaymentIntentの作成・APIキー認証・冪等キーをNode.jsとcurlで実装:triggerが内部で呼ぶAPIの実装方法。
- Stripe Billingの実装手順:Price設計・従量課金・カスタマーポータルのコード:サブスク系イベントをtriggerで確かめる対象の実装。
- Stripe Connectとは:アカウント種別・3つの支払い方式と資金フローの実装手順:–forward-connect-toで受ける連結アカウントのイベント。