You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 13 + Stripe 请求签名验证失败求助

Stripe Webhook签名验证失败求助

错误信息

No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?

环境信息

  • Next.js 13.3.2
  • Stripe SDK 12.4.0

复现步骤

  1. 创建端点 /pages/api/p/test,代码如下:
import Stripe from 'stripe';
import { NextApiRequest, NextApiResponse } from 'next';
import safe from 'colors/safe';
import { buffer } from 'micro';

const handler = async (
    req: NextApiRequest,
    res: NextApiResponse
): Promise<void> => {
    const stripe = new Stripe(process.env.STRIPE_SECRET as string, {
        apiVersion: '2022-11-15',
    });

    const webhookSecret: string = "whsec_33244....";

    if (req.method === 'POST') {
        const sig = req.headers['stripe-signature'] as string;
        const buf = await buffer(req);
        const body = buf.toString();

        let event: Stripe.Event;

        try {
            console.log(safe.bgGreen(body))
            event = stripe.webhooks.constructEvent(body, sig, webhookSecret);
        } catch (err) {
            // On error, log and return the error message
            console.log(`❌ Error message: ${err.message}`);
            res.status(400).send(`Webhook Error: ${err.message}`);
            return;
        }

        // Successfully constructed event
        console.log('✅ Success:', event.id);

        // Cast event data to Stripe object
        if (event.type === 'payment_intent.succeeded') {
            const stripeObject: Stripe.PaymentIntent = event.data
                .object as Stripe.PaymentIntent;
            console.log(`💰 PaymentIntent status: ${stripeObject.status}`);
        } else if (event.type === 'charge.succeeded') {
            const charge = event.data.object as Stripe.Charge;
            console.log(`💵 Charge id: ${charge.id}`);
        } else {
            console.warn(`🤷‍♀️ Unhandled event type: ${event.type}`);
        }

        // Return a response to acknowledge receipt of the event
        res.json({ received: true });
    } else {
        res.setHeader('Allow', 'POST');
        res.status(405).end('Method Not Allowed');
    }
};

export const config = {
    api: {
        bodyParser: false,
    },
};

export default handler;
  1. 启动开发服务器和Stripe监听器:
stripe listen --forward-to localhost:3000/api/p/test
  1. 复制生成的webhook签名密钥并粘贴到代码中
  2. 触发模拟事件:
stripe trigger payment_intent.succeeded

已尝试的解决方案

  • 使用micro包的buffer获取原始请求体
  • 手动验证HMAC签名
  • 参照Stripe文档示例实现buffer函数

请求体解析情况

日志显示请求体解析正常,内容如下:

{  
  "id": "evt_3NIzhvEcQkKxoTiV1xjEMh02",  
  "object": "event",  
  "api_version": "2022-11-15",  
  "created": 1686772219,  
  "data": {  
    "object": {  
      "id": "pi_3NIzhvEcQkKxoTiV1kuXEmH6",  
      "object": "payment_intent",  
      "amount": 2000,  
      "amount_capturable": 0,  
      "amount_details": {  
        "tip": {  
        }  
      },  
      "amount_received": 0,  
      "application": null,  
      "application_fee_amount": null,  
      "automatic_payment_methods": null,  
      "canceled_at": null,  
      "cancellation_reason": null,  
      "capture_method": "automatic",  
      "client_secret": "pi_3NIzhvEcQkKxoTiV1kuXEmH6_secret_ZRnfaga3uRF5EhNXE0KwZpDpp",  
      "confirmation_method": "automatic",  
      "created": 1686772219,  
      "currency": "usd",  
      "customer": null,  
      "description": "(created by Stripe CLI)",  
      "invoice": null,  
      "last_payment_error": null,  
      "latest_charge": null,  
      "livemode": false,  
      "metadata": {  
      },  
      "next_action": null,  
      "on_behalf_of": null,  
      "payment_method": null,  
      "payment_method_options": {  
        "card": {  
          "installments": null,  
          "mandate_options": null,  
          "network": null,  
          "request_three_d_secure": "automatic"  
        }  
      },  
      "payment_method_types": [  
        "card"  
      ],  
      "processing": null,  
      "receipt_email": null,  
      "review": null,  
      "setup_future_usage": null,  
      "shipping": {  
        "address": {  
          "city": "San Francisco",  
          "country": "US",  
          "line1": "510 Townsend St",  
          "line2": null,  
          "postal_code": "94103",  
          "state": "CA"  
        },  
        "carrier": null,  
        "name": "Jenny Rosen",  
        "phone": null,  
        "tracking_number": null  
      },  
      "source": null,  
      "statement_descriptor": null,  
      "statement_descriptor_suffix": null,  
      "status": "requires_payment_method",  
      "transfer_data": null,  
      "transfer_group": null  
    }  
  },  
  "livemode": false,  
  "pending_webhooks": 2,  
  "request": {  
    "id": "req_MfPOwrw4MZsykJ",  
    "idempotency_key": "10108c32-75db-4e1e-abb3-b3b2673df025"  
  },  
  "type": "payment_intent.created"  
}

求助

已查阅大量资料并尝试多种方法,仍无法解决签名验证失败问题,恳请提供排查思路。


内容的提问来源于stack exchange,提问作者Designly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:37:53