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

Next.js本地环境下Stripe Webhooks无法触发的问题求助

解决Next.js 13.4.4中Stripe Webhook的两个问题

问题1:Webhook签名验证失败

可能原因及修复方案:

  • 硬编码签名密钥错误:代码中直接写死的whsec_5e..可能不完整,或误用了API密钥而非Webhook签名密钥。
    • 本地开发时,stripe listen启动后会生成临时签名密钥(控制台输出webhook signing secret: whsec_xxx),必须使用这个临时密钥。
    • 生产环境需使用Stripe仪表盘对应Webhook端点的签名密钥。
  • Next.js自动解析body导致签名不匹配:App Router默认会自动解析请求body,导致获取的rawBody并非原始请求内容,签名验证失败。在路由文件顶部添加配置禁用自动解析:
    export const config = {
      api: {
        bodyParser: false,
      },
    };
    

问题2:stripe trigger无日志输出且无事件记录

可能原因及修复方案:

  • stripe listen未正确运行:确保命令执行后控制台显示Ready!状态,且生成了正确的临时签名密钥。
  • Stripe CLI未授权:执行stripe login完成授权,否则无法生成测试事件。
  • 路径/端口不匹配:确认本地服务运行在3000端口,且--forward-to后的路径与路由路径app/api/webhooks/route.ts完全一致。

修改后的完整路由代码

import { NextRequest, NextResponse } from 'next/server';
import { stripe } from '@utils/stripe';
import Stripe from 'stripe';

// 禁用Next.js自动body解析,确保拿到原始请求体
export const config = {
  api: {
    bodyParser: false,
  },
};

export async function POST(request: NextRequest) {
  try {
    console.log('Endpoint hit');
    const rawBody = await request.text();
    console.log('RAW BODY:', rawBody);
    const sig = request.headers.get('stripe-signature') || '';
    console.log('SIGNATURE', sig);

    let event: Stripe.Event;
    try {
      // 建议用环境变量存储密钥,不要硬编码
      const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET || '';
      event = stripe.webhooks.constructEvent(
        rawBody,
        sig,
        webhookSecret
      );
    } catch (err) {
      console.error(`Webhook signature verification failed: ${err}`);
      return NextResponse.json({ received: false }, { status: 400 });
    }

    switch (event.type) {
      case 'customer.subscription.created':
        console.log('case sub created');
        break;
      case 'payment_intent.succeeded':
        console.log('PAYMENT INTENT EVENT');
        break;
      default:
        console.warn(`Unhandled event type: ${event.type}`);
        break;
    }

    return NextResponse.json({ received: true }, { status: 200 });
  } catch (e) {
    console.error('Error in POST function:', e);
    return NextResponse.json({ received: false }, { status: 500 });
  }
}

额外注意事项:

  • 本地开发时,将stripe listen输出的临时签名密钥设置到环境变量STRIPE_WEBHOOK_SECRET中,避免硬编码。
  • 确保@utils/stripe中初始化的Stripe实例使用了正确的API密钥,且API版本与Stripe CLI使用的版本一致。

内容的提问来源于stack exchange,提问作者Patrik Rikama-Hinnenberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:20:33