使用Deno处理Stripe Webhook时签名匹配错误排查求助
Stripe Webhook签名验证失败问题排查(Deno环境)
可能的错误原因及解决方法
1. 请求体转码导致签名计算不匹配
Stripe的Webhook签名是基于原始二进制请求体计算的,你当前将arrayBuffer转成字符串的操作可能引入编码差异,导致传递给constructEvent的payload和Stripe签名时的原始内容不一致。
解决方法:直接传递原始二进制数据,无需转码。修改代码如下:
// 移除转码步骤,直接使用Uint8Array格式的原始请求体 event = stripe.webhooks.constructEvent( new Uint8Array(webhookRawBody), webhookStripeSignatureHeader, stripeWebhookSecret );
2. 请求体被重复读取
Deno中request.body是可读流,仅能读取一次。如果在调用request.arrayBuffer()之前,有其他代码先调用了request.text()、request.json()等读取方法,会导致后续读取到空数据,签名验证必然失败。
验证方式:检查代码中是否存在提前读取请求体的逻辑,确保arrayBuffer()是第一个读取请求体的操作。
3. 签名秘钥或API版本不匹配
- 确认Stripe控制台中Webhook的签名秘钥(
whsec_开头)与代码中stripeWebhookSecret完全一致,且对应正确的环境(测试/生产); - 确认代码中指定的
apiVersion与Stripe控制台Webhook配置的API版本完全相同,版本不一致会导致签名计算逻辑差异。
确保请求体正确传递的关键要点
- 直接使用原始二进制数据:始终将
Uint8Array格式的原始请求体传递给constructEvent,避免任何转码、格式化操作; - 保证请求体仅读取一次:确保
request.arrayBuffer()是请求体的首次读取操作,防止流被耗尽; - 字节级对比验证:调试时可将收到的原始二进制数据保存为文件,与Stripe控制台中对应事件的payload做字节级对比,确认内容完全一致。
修改后的完整代码示例
import "jsr:@supabase/functions-js/edge-runtime.d.ts"; import Stripe from 'https://esm.sh/stripe@11.1.0?target=deno'; import { config } from "https://deno.land/x/dotenv/mod.ts"; const env = config(); const stripeApiKey = env.STRIPE_API_KEY; const stripeWebhookSecret = env.STRIPE_WEBHOOK_SIGNING_SECRET; const stripe = new Stripe(stripeApiKey as string, { apiVersion: '2022-11-15', httpClient: Stripe.createFetchHttpClient(), }); Deno.serve(async (request) => { const webhookStripeSignatureHeader = request.headers.get('Stripe-Signature'); if (!webhookStripeSignatureHeader) { return new Response('Missing Stripe signature', { status: 400 }); } const webhookRawBody = await request.arrayBuffer(); let event; try { event = stripe.webhooks.constructEvent( new Uint8Array(webhookRawBody), webhookStripeSignatureHeader, stripeWebhookSecret ); } catch (err) { console.error(`Webhook Error: ${err.message}`); return new Response(err.message, { status: 400 }); } console.log(`🔔 Event received: ${event.id}`); return new Response(JSON.stringify({ ok: true }), { status: 200 }); });
内容的提问来源于stack exchange,提问作者vizeusuario
相关产品推荐
相关产品推荐

