如何用ElysiaJS正确处理Stripe Webhook?解决签名验证报错问题
ElysiaJS 处理 Stripe Webhook 签名验证失败解决方案
问题描述
使用ElysiaJS处理Stripe Webhook时,已获取到请求体字符串reqText,但调用constructEventAsync时触发以下错误:
Webhook payload must be provided as a string or a Buffer instance representing the raw request body.Payload was provided as a parsed JavaScript object instead. Signature verification is impossible without access to the original signed material.
问题根源
- 错误地将请求处理逻辑放在了Elysia的
parse钩子中——该钩子仅用于解析请求体,而非直接返回响应,导致流程混乱。 - Elysia默认会自动将JSON请求体解析为JavaScript对象,破坏了Stripe签名验证必需的原始请求体内容。
修复后的代码
import { Elysia, t } from 'elysia' import { env } from '@/config/env.config' import { stripeClient } from '@/lib/stripe.lib' export const stripeWebhook = new Elysia().post( '/integrations/stripe/webhook', async ({ body, headers }) => { return webhookHandler(body as string, headers['stripe-signature']) }, { headers: t.Object({ 'stripe-signature': t.String(), 'content-type': t.String(), }), // 手动接管请求体解析,获取原始文本 async parse({ request }) { return await request.text() }, body: t.String(), }, ) const webhookHandler = async (reqText: string, signature: string) => { const endpointSecret = env.STRIPE_WEBHOOK_SECRET if (!signature) { console.error('Stripe签名缺失') return new Response(JSON.stringify({ error: 'Stripe签名缺失' }), { status: 400 }) } if (!stripeClient) { console.error('Stripe客户端未初始化') return new Response(JSON.stringify({ error: 'Stripe客户端未初始化' }), { status: 500 }) } try { const event = await stripeClient.webhooks.constructEventAsync( reqText, signature, endpointSecret, ) if (event.type === 'payment_intent.succeeded') { console.log(event.object) console.log('PaymentIntent支付成功!') } return new Response(JSON.stringify({ received: true }), { status: 200 }) } catch (error) { console.error(error) return new Response(`Webhook Error: ${error}`, { status: 400 }) } }
关键修改点
- 移除
parse钩子中的请求处理逻辑,仅保留原始请求体的获取逻辑,确保传递给Stripe的是未被解析的原始字符串。 - 将Webhook处理逻辑移至路由的handler函数中,遵循Elysia的正常请求处理流程。
- 使用标准
Response对象返回结果,符合HTTP响应格式规范。
内容的提问来源于stack exchange,提问作者Sandro Nolasco
相关产品推荐
相关产品推荐

