Next.js 13 App Router中如何获取原始请求体计算SHA-256签名?
在Next.js 13 App Router中验证Lemon Squeezy Webhook签名
要解决这个问题,核心是获取原始请求体字节流——因为Lemon Squeezy的签名是基于原始请求的原始内容计算的,而你之前用JSON.stringify(body)生成的内容,会和原始请求体存在格式差异(比如空格、键顺序、换行符),导致签名验证失败。
解决步骤
- 直接读取原始请求体的Buffer,避免解析后再序列化
- 用原始Buffer计算HMAC签名,和请求头的
x-signature做对比 - 验证通过后再解析原始Buffer为JSON(用于后续业务逻辑)
完整代码示例
// app/api/webhooks/lemonsqueezy/route.ts import { NextResponse } from 'next/server'; import crypto from 'crypto'; // 签名验证工具函数 const validateSignature = (rawBody: Buffer, requestSignature: string | null): boolean => { const secret = process.env.LMS_SECRET ?? ''; if (!secret || !requestSignature) return false; // 基于原始请求体计算HMAC const hmac = crypto.createHmac('sha256', secret); const calculatedHash = hmac.update(rawBody).digest('hex'); // 用timingSafeEqual避免时序攻击 const digest = Buffer.from(calculatedHash, 'utf8'); const signature = Buffer.from(requestSignature, 'utf8'); return digest.length === signature.length && crypto.timingSafeEqual(digest, signature); }; export async function POST(request: Request) { try { // 1. 读取原始请求体的Buffer const rawBody = await request.arrayBuffer(); const rawBodyBuffer = Buffer.from(rawBody); // 2. 获取请求头中的签名 const requestSignature = request.headers.get('x-signature'); // 3. 验证签名 const isValid = validateSignature(rawBodyBuffer, requestSignature); if (!isValid) { console.error('签名验证失败'); return NextResponse.json({ error: '无效签名' }, { status: 403 }); } // 4. 验证通过后,解析原始Buffer为JSON(用于业务逻辑) const body = JSON.parse(rawBodyBuffer.toString('utf8')); // 这里处理你的Webhook业务逻辑,比如更新订单状态、触发通知等 console.log('Webhook数据:', body); return NextResponse.json({ success: true }, { status: 200 }); } catch (error) { console.error('处理Webhook失败:', error); return NextResponse.json({ error: '服务器内部错误' }, { status: 500 }); } }
关键说明
- 不能用
request.json():因为该方法会读取并解析流,且ReadableStream只能被读取一次;同时解析后的JSON对象再序列化,会改变原始请求的格式细节,导致签名不匹配。 - 必须用
arrayBuffer()读取原始内容:转换成Buffer后直接用于HMAC计算,才能和Lemon Squeezy生成签名时的原始内容完全一致。 - 始终使用
crypto.timingSafeEqual对比签名:避免时序攻击,保证验证的安全性。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

