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

Next.js API参数Undefined问题:请求报错及原因排查问询

问题描述

我有如下React组件:

import React, { useEffect } from "react";
import styles from "../styles/success.module.css";
import { useRouter } from "next/router";
import axios from "axios";
const Success = () => {
  const {
    query: { id },
  } = useRouter();

  useEffect(() => {
    getId();
  }, [id]);

  const getId = () => {
    axios
      .put("api/getOrder", {
        id,
      })
      .then((res) => {
        if (res.status === 200) {
          console.log(res.data.session);
        }
      })
      .catch((err) => {
        console.log(err);
      });
  };

  return (
    <div className={styles.success}>
      <h1>Thank you for your purchase {id}</h1>
    </div>
  );
};

export default Success;

预期是id加载完成后向API发起请求。

后端代码:

const stripe = require('stripe')(process.env.NEXT_PUBLIC_STRIPE_SECRET_KEY);

export default async function handler(req, res) {
    const session = await stripe.checkout.sessions.retrieve(`${req.body.id}`)

    res.status(200).send({
        nessage: '200',
        session
    });
    res.status(500).send({
        message: '500'
    });
}

问题:尝试将id动态传入session变量时,id为undefined,请求最终完成但控制台报错。

控制台报错信息:

error - StripeInvalidRequestError: No such checkout.session: undefined
    at Function.generate (C:\Users\user\Desktop\zigi\my-app\node_modules\stripe\lib\Error.js:40:16)
    at res.toJSON.then.StripeAPIError.message (C:\Users\user\Desktop\zigi\my-app\node_modules\stripe\lib\StripeResource.js:238:35)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  type: 'StripeInvalidRequestError',
  raw: {
    code: 'resource_missing',
    doc_url: 'https://stripe.com/docs/error-codes/resource-missing',
    message: 'No such checkout.session: undefined',
    request_log_url: 'https://dashboard.stripe.com/test/logs/req_ZrNElSd58VVHSA?t=1666409724',
    type: 'invalid_request_error',
    headers: {
      server: 'nginx',
      date: 'Sat, 22 Oct 2022 03:35:24 GMT',
      'content-type': 'application/json',
      'content-length': '311',
      connection: 'keep-alive',
      'access-control-allow-credentials': 'true',
      'access-control-allow-methods': 'GET, POST, HEAD, OPTIONS, DELETE',
      'access-control-allow-origin': '*',
      'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required',
      'access-control-max-age': '300',
      'cache-control': 'no-cache, no-store',
      'request-id': 'req_ZrNElSd58VVHSA',
      'stripe-version': '2022-08-01',
      'strict-transport-security': 'max-age=63072000; includeSubDomains; preload'
    },
    statusCode: 404,
    requestId: 'req_ZrNElSd58VVHSA'
  },
  rawType: 'invalid_request_error',
  code: 'resource_missing',
  doc_url: 'https://stripe.com/docs/error-codes/resource-missing',
  param: undefined,
  detail: undefined,
  headers: {
    server: 'nginx',
    date: 'Sat, 22 Oct 2022 03:35:24 GMT',
    'content-type': 'application/json',
    'content-length': '311',
    connection: 'keep-alive',
    'access-control-allow-credentials': 'true',
    'access-control-allow-methods': 'GET, POST, HEAD, OPTIONS, DELETE',
    'access-control-allow-origin': '*',
    'access-control-expose-headers': 'Request-Id, Stripe-Manage-Version, X-Stripe-External-Auth-Required, X-Stripe-Privileged-Session-Required',
    'access-control-max-age': '300',
    'cache-control': 'no-cache, no-store',
    'request-id': 'req_ZrNElSd58VVHSA',
    'stripe-version': '2022-08-01',
    'strict-transport-security': 'max-age=63072000; includeSubDomains; preload'
  },
  requestId: 'req_ZrNElSd58VVHSA',
  statusCode: 404,
  charge: undefined,
  decline_code: undefined,
  payment_intent: undefined,
  payment_method: undefined,
  payment_method_type: undefined,
  setup_intent: undefined,
  source: undefined,
  page: '/api/getOrder'
}
error - Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at Object.sendEtagResponse (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\send-payload\index.js:29:13)
    at sendData (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\api-utils\node.js:172:27)
    at ServerResponse.apiRes.send (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\api-utils\node.js:349:31)
    at handler (webpack-internal:///(api)/./pages/api/getOrder.js:12:21)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async Object.apiResolver (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\api-utils\node.js:366:9)
    at async DevServer.runApi (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\next-server.js:481:9)
    at async Object.fn (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\next-server.js:735:37) {
  code: 'ERR_HTTP_HEADERS_SENT',
  page: '/api/getOrder'
}
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at NodeNextResponse.setHeader (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\base-http\node.js:61:19)
    at DevServer.renderError (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\base-server.js:1012:17)
    at DevServer.renderError (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\next-server.js:843:22)
    at DevServer.run (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\dev\next-dev-server.js:715:35)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async DevServer.handleRequest (C:\Users\user\Desktop\zigi\my-app\node_modules\next\dist\server\base-server.js:285:20) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
错误分析与修复

1. 前端:路由query.id初始为undefined,提前触发请求

Next.js的useRouter中query.id初始状态是undefined,组件挂载时useEffect会因为id为undefined先执行一次getId,导致后端收到undefined的id。

修复:
在getId函数中新增判断,仅当id存在时才发起请求:

const getId = () => {
  if (!id) return;
  axios
    .put("/api/getOrder", { id })
    .then((res) => {
      if (res.status === 200) {
        console.log(res.data.session);
      }
    })
    .catch((err) => {
      console.log(err);
    });
};

2. 后端:未处理请求方法、错误捕获,且重复发送响应

  • 未校验请求方法,可能接收非PUT请求导致错误
  • 调用Stripe API时无错误捕获,失败会直接抛出异常
  • 同时执行res.status(200).send()和res.status(500).send(),导致重复发送响应,触发ERR_HTTP_HEADERS_SENT错误
  • 存在拼写错误:nessage应为message

修复后的后端代码:

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

export default async function handler(req, res) {
  // 仅处理PUT请求
  if (req.method !== 'PUT') {
    return res.status(405).send({ message: 'Method Not Allowed' });
  }

  const { id } = req.body;
  
  // 校验id是否存在
  if (!id) {
    return res.status(400).send({ message: 'Missing session ID' });
  }

  try {
    const session = await stripe.checkout.sessions.retrieve(id);
    res.status(200).send({
      message: '200',
      session
    });
  } catch (err) {
    res.status(err.statusCode || 500).send({
      message: err.message || 'Internal Server Error'
    });
  }
}

3. 额外注意事项

  • Stripe密钥不应使用NEXT_PUBLIC_前缀,该前缀会将密钥暴露给前端,改用普通环境变量(如STRIPE_SECRET_KEY)仅在后端使用
  • 前端请求URL需添加斜杠:/api/getOrder,避免路径解析错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:10:32