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

NextJS部署后Stripe结账报500及ERR_HTTP_HEADERS_SENT错误

解决Stripe结账部署后500错误及重复响应头问题

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

这个错误的直接原因是同一个请求处理流程中发送了两次响应,导致HTTP头被重复设置。结合你的代码和Stripe已生成未支付订单的情况,具体问题及修复方案如下:

1. 修复API路由的重复响应问题

在pages/api/stripe.js中,你先调用res.status(200).json(session)返回JSON数据,紧接着又执行res.redirect(303, session.url)进行重定向。这两个操作都会向客户端发送响应头,触发重复设置的错误。

根据你的前端逻辑(前端拿到sessionId后自行调用stripe.redirectToCheckout),只需要返回session数据即可,不需要在API层做重定向。修改后的代码:

import Stripe from 'stripe';

// 注意:私钥不能用NEXT_PUBLIC前缀,避免暴露到前端
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  if (req.method === 'POST') {
    
    try {
      const params = {
        submit_type :'pay',
        mode:'payment',
        payment_method_types:['card'],
        shipping_address_collection: {
            allowed_countries: ['IN'],
        },
        shipping_options: [
            {shipping_rate: '替换为你的Stripe运费费率ID'}
        ],
        line_items: req.body.map((item)=>{
            const img = item.image[0].asset._ref;
            const newImage = img.replace('image-','https://cdn.sanity.io/..../').replace('-webp','.webp');
            return {
                price_data:{
                    currency:'inr',
                    product_data:{
                        name:item.name,
                        images:[newImage],
                    },
                    unit_amount:item.price*100,
                },
                adjustable_quantity:{
                    enabled:true,
                    minimum:1
                },
                quantity:item.quantity
            }
        }),
        success_url: `${req.headers.origin}/success`,
        cancel_url: `${req.headers.origin}`,
      }
      const session = await stripe.checkout.sessions.create(params);

      // 仅返回session数据,由前端处理重定向
      res.status(200).json(session);
    } catch (err) {
      res.status(err.statusCode || 500).json(err.message);
    }
  } else {
    res.setHeader('Allow', 'POST');
    res.status(405).end('Method Not Allowed');
  }
}

2. 修正环境变量名称错误

Stripe的密钥(Secret Key)不能使用NEXT_PUBLIC_前缀,这个前缀会让变量暴露到前端代码中,存在安全风险,同时可能导致部署后密钥无法正确读取。将环境变量名从NEXT_PUBLIC_STRIPE_SECRET_KEY改为STRIPE_SECRET_KEY,并确保部署环境中已正确配置该变量。

3. 修复前端错误状态判断

在cart.js中,你使用response.statusCode判断响应状态,但Fetch API的响应对象属性是status,不是statusCode,这会导致500错误无法被正确捕获。修改代码:

const handleCheckout = async () => {
    const stripe = await getStripe();

    const response = await fetch('/api/stripe', {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(cartItems)
    });

    // 修正为response.status
    if (response.status === 500) {
        toast.error('结账请求失败,请重试');
        return;
    }
    const data = await response.json();

    toast.loading("Redirecting...");
    stripe.redirectToCheckout({ sessionId: data.id });
};

额外检查点

  • 确认部署环境中已正确配置NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY(公钥)和STRIPE_SECRET_KEY(私钥)
  • 确保shipping_options中的shipping_rate是有效的Stripe运费费率ID,不要留占位符
  • 检查Sanity图片链接替换逻辑是否正确,避免因图片URL无效导致Stripe会话创建失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 08:50:38