無料で相談する
決済・サブスク

GASでStripe Webhookを受けると詰まる2箇所

署名検証と302ループ、別構成に切り替えた判断

2025-03-30

GASでStripe Webhookを受けると詰まる2箇所

最初の相談文がそのまま問題を言い表していました。

STRIPEからのリクエスト署名が検証できない模様 302で繰り返しリクエストがきてしまう GASはヘッダー情報取得できないからどう対処すべきか

この一文に、GASとStripe Webhookを組み合わせたときの詰まり所が全部入っています。署名が取れない、302が止まらない。2つで、原因はひとつです。


GASのヘッダー制限

Stripe(注:オンライン決済のサービス)は、Webhookの通知を送るとき、ヘッダーに署名情報を付けてきます。「この通知は本物のStripeから来たもの」だと受け取り側が確認するための仕組みです。

GAS(注:Googleのスクリプト実行環境。スプレッドシートに紐づいたサーバーレスな処理基盤)には、このヘッダーを読む方法がありません。

仕様の問題です。GASのWebアプリとして公開したエンドポイントは、リクエストのボディは取れます。でもHTTPヘッダーは取れない。Stripeが署名を送ってきても、受け取る窓口がない。

署名を照合するコードをどれだけ丁寧に書いても、データが届いていないので永遠に失敗します。


JSONPで回避、でも302が残る

ヘッダーが取れないなら署名検証を諦めて、イベントIDを使ってStripe側に「このイベントは本物か」と問い合わせる方式に切り替えました。Stripeに確認さえできれば、ヘッダーの署名は要らない。

あー、これでたJSONPで対応して

これで署名の問題は一応回避できました。ただ今度は302が残ります。

GASのエンドポイントへのPOSTリクエストは、デフォルトでリダイレクトが発生します。Stripeが通知を送ると302が返ってくる。Stripeはそれをエラーとみなして、同じ通知を何度も再送します。

結果として、過去の購入イベントが繰り返し飛んでくる状態になります。


302は受け取れていても出る

混乱しやすいのはここです。

302エラー出ても、処理できていれば問題ない?

この確認が出てきた背景は、「302が返っているのに、データはスプレッドシートに書けている」という状態でした。処理は動いている。でもStripeは成功とみなしていない。

GASが302を返すのは、処理の失敗ではなくGASのリダイレクト仕様によるものです。Stripeがその挙動を「応答がなかった」と解釈して再送する。処理は動いているのに通知だけが積み重なる。

回避策はあります。doPostの中で即座に200を返す処理を先に書いて、実際の処理を後続で動かす。でもこれはGASの設計上、確実に動く保証がない書き方です。


GASを諦めた判断

GAS以外でならどう実装するのが楽かな?

この質問が出たのは、回避策を試してもう一段の問題が出てきた時点でした。

GASは無料で、設定も少なくて、スプレッドシートとの連携が簡単です。だから最初に選ぶことが多い。でも「ヘッダーが取れない」「リダイレクトが制御できない」の2つが重なると、Stripe Webhookの受け口として使い続けるのはしんどい。

代替として整理したのはこの選択肢でした。

ヘッダーが取れる → 署名検証を本来の方法でできる
リダイレクトが起きない → Stripeが成功とみなす
スプレッドシートへの書き込みは後から連携できる

これを満たす構成に切り替えると、署名検証のコードがシンプルになります。GASを介してスプレッドシートに書く処理は残しつつ、Webhookの受け口だけ別にする。Webhookを受けるだけの小さな関数を外側に置いて、そこからGASを呼ぶ形です。


GASはWebhookの受け口に向かない

これはGASが悪いという話ではありません。GASは用途が合えばとても便利です。スプレッドシートをデータストアとして使う、定期実行を管理する、フォームを受け取る。これらはGASが得意な領域です。

ただStripeのWebhookを受けるという用途には向いていない。ヘッダー制限と302の2つが、どちらもStripeが求める仕様と噛み合わない。

「GASで受けてみて詰まった」なら、諦めるタイミングを早めたほうが結局工数が少ないです。回避策を積み上げて動く状態にはなるかもしれませんが、安定しません。Webhookの受け口だけ別の場所に切り出して、スプレッドシートへの書き込みはそこから呼ぶ構成にしたほうが、後から直しにくいコードが残りません。


AIへの頼み方

このケースで使った指示はだいたいこういう流れでした。

GASを使うとかならずリダイレクトされちゃうからstripeで302エラーになる。いったんredirectをnofollowにした上で、locationヘッダーを読んで、再リクエストするように改修できますか

まず現象をそのまま渡す。技術的な言葉を整理してから渡す必要はありません。「こういう状況になっている」「こうしたい」を日本語で渡せば、原因の候補と選択肢が返ってきます。

ただGASの仕様上の制約は、あらかじめ渡しておいた方が的外れな提案が減ります。「GASはHTTPヘッダーが取れない前提で考えてほしい」と一行添えると、GASでの回避策とGAS以外での実装案を両方出してくれます。GASでどこまで頑張るか切り替えるかは、材料が揃ってから自分で判断できます。

同じような業務課題はありませんか?

御社の状況に合わせて、最適なAI活用のかたちをご提案します。要件が固まっていなくても大丈夫です。

無料で相談する