Cloudflare workersでstripeを使う時はverifyHeaderAsyncを使おう
Cloudflareなどのエッジ環境でStripeのWebhookを実装する際、同期処理でエラーが発生する可能性があります。その対策として、非同期版の`verifyHeaderAsync`メソッドを使うことで、エッジ環境でも安全にWebhookの署名検証ができます。
広告ここから
広告ここまで
目次
Cloudflareなどのエッジコンピューティング環境でStripeを使おうとすると、Webhookの実装でハマることがあります。今回はハマった部分についての簡単な解説と対策を紹介します。
Cloudflare他エッジ環境でハマるコード
結論から言うと、Webhookの署名検証処理がエッジ環境だと転けやすくなっています。Stripeのドキュメントにもあるコードですが、だいたいこんな感じですね。
try {
stripe.webhooks.signature.verifyHeader(body, signature, STRIPE_APP_SECRET);
} catch (error) {
return c.json({ message: (error as Error).message }, 400);
}
これがエッジ環境では以下のエラーになることがあります。
{"message":"SubtleCryptoProvider cannot be used in a synchronous context."}
Claudeにエラー内容を解説させてみると、「WebCrypto API (SubtleCrypto) は非同期APIなので、すべての操作は Promise を返します。Cloudflare Workersでは、これらの暗号操作は非同期で行う必要があります。」とのことでした。同期処理で行おうとしているのが間違いだよーということですね。
ちなみにSDKの実装を見てみると、こんな感じになっています。
const expectedSignature = cryptoProvider.computeHMACSignature(
makeHMACContent(payload, details),
secret
);
async版のメソッドを使おう
この問題の解決策は実はとてもシンプルです。非同期版のメソッドであるverifyHeaderAsync
が用意されているので、それを使いましょう。こちらは非同期でCrypto系を呼び出しています。
const expectedSignature = await cryptoProvider.computeHMACSignatureAsync(
makeHMACContent(payload, details),
secret
);
ということで、このように作りましょう。
try {
await stripe.webhooks.signature.verifyHeaderAsync(body, signature, STRIPE_APP_SECRET);
} catch (error) {
return c.json({ message: (error as Error).message }, 400);
}
あまりドキュメントやブログで紹介されることのないメソッドですが、エッジ環境での開発では欠かせない実装なので、覚えておきましょう。