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

MERN项目集成Stripe支付网关遇API密钥认证错误求助

Stripe支付网关集成MERN项目时的认证错误排查

错误信息

StripeAuthenticationError: 未提供API密钥。需要在Authorization头部使用Bearer认证方式提供API密钥(例如:'Authorization: Bearer YOUR_SECRET_KEY')。

错误堆栈片段:

D:\Visual Studio Code\Projects\MERN Projects\Online Movie Ticket Booking System\server\node_modules\stripe\cjs\RequestSender.js:96
err = new Error_js_1.StripeAuthenticationError(jsonResponse.error);
^

问题场景

将Stripe支付网关集成到MERN项目中,调用Stripe API时触发上述认证错误。已检查代码和环境变量,确认密钥设置逻辑,且在App.jsx中能成功获取并打印stripeApikey,但错误依然存在。以下是相关代码片段:


后端PaymentController代码

const express = require("express");
const router = express.Router();

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

router.post("/process", async (req, res, next) => {
  const myPayment = await stripe.paymentIntents.create({
    amount: req.body.amount,
    currency: "inr",
    metadata: {
      company: "Mahadi",
    },
  });

  console.log("Stripe Secret Key:", process.env.STRIPE_SECRET_KEY);

  res.status(200).json({
    success: true,
    client_secret: myPayment.client_secret,
  });
});

router.get("/stripeapikey", async (req, res, next) => {
  console.log("Stripe API Key:", process.env.STRIPE_API_KEY);

  res.status(200).json({ stripeApikey: process.env.STRIPE_API_KEY });
});

module.exports = router;

前端App.jsx代码

const [stripeApikey, setStripeApiKey] = useState("");

async function getStripeApikey() {
  try {
    const { data } = await axios.get(`${server}/payment/stripeapikey`);
    setStripeApiKey(data.stripeApikey);
    console.log("Stripe API Key:", data.stripeApikey);
  } catch (error) {
    console.error("Error fetching Stripe API key:", error);
  }
}
console.log(stripeApikey);

useEffect(() => {
  getStripeApikey();
}, []);

return (
  <>
    <BrowserRouter>
      {stripeApikey && (
        <Elements stripe={loadStripe(stripeApikey)}>
          <Routes>
            <Route
              path="/booking"
              element={
                <ProtectedRoute>
                  <BookingPage />
                </ProtectedRoute>
              }
            />
          </Routes>
        </Elements>
      )}

前端BookingPage.jsx核心支付逻辑

const handleSubmit = async (e) => {
  e.preventDefault();

  try {
    const config = {
      headers: {
        "Content-Type": "application/json",
      },
    };

    const paymentData = {
      amount: ticketPrice * 100, // Stripe要求金额以分为单位
    };

    const { data } = await axios.post(
      `${server}/payment/process`,
      paymentData,
      config
    );

    const client_secret = data.client_secret;

    if (!stripe || !elements) {
      toast.error("Stripe或Elements未初始化。");
      return;
    }

    const result = await stripe.confirmCardPayment(client_secret, {
      payment_method: {
        card: elements.getElement(CardNumberElement),
      },
    });

    if (result.error) {
      toast.error(result.error.message);
    } else {
      if (result.paymentIntent.status === "succeeded") {
        const reservationData = {
          movieName,
          theaterName,
          showDate,
          selectedShowtime,
          selectedHall,
          selectedSeats,
          ticketPrice,
          paymentInfo: {
            id: result.paymentIntent.id,
            status: result.paymentIntent.status,
            type: "Credit Card",
          },
        };

        dispatch(createReservation(reservationData));
        toast.success("预订成功!");

        navigate("/ticket", {
          state: {
            movieName,
            theaterName,
            showDate,
            selectedShowtime,
            selectedHall,
            selectedSeats,
            ticketPrice,
          },
        });
      } else {
        toast.error("支付处理失败,请重试。");
      }
    }
  } catch (error) {
    toast.error(error.message);
  }
};

Stripe卡片组件代码

<div className="w-[50%] mb-5">
  <label className="block pb-3 text-[black]">
    有效期 <span className="text-red-500">*</span>{" "}
  </label>
  <CardExpiryElement
    className="w-full border p-1 rounded-[5px]"
    options={{
      style: {
        base: {
          fontSize: "15px",
          lineHeight: 1.5,
          color: "#444",
        },
        empty: {
          color: "#3a120a",
          backgroundColor: "transparent",
          "::placeholder": {
            color: "#444",
          },
        },
      },
    }}
  />
</div>
</div>

<div className="w-full pb-3 ">
  <div className="w-[50%] mb-5">
    <label className="block pb-3 text-[black]">
      卡号 <span className="text-red-500">*</span>{" "}
    </label>
    <CardNumberElement
      className={`w-full border p-1 rounded-[5px] !h-[35px]`}
      options={{
        style: {
          base: {
            fontSize: "15px",
            lineHeight: 1.5,
            color: "#444",
          },
          empty: {
            color: "#3a120a",
            backgroundColor: "transparent",
            "::placeholder": {
              color: "#444",
            },
          },
        },
      }}
    />
  </div>
  <div className="w-[50%] ">
    <label className="block pb-3 text-[black]">
      CVV <span className="text-red-500">*</span>{" "}
    </label>
    <CardCvcElement
      className="w-full border p-1 rounded-[5px] !h-[35px]"
      options={{
        style: {
          base: {
            fontSize: "15px",
            lineHeight: 1.5,
            color: "#444",
          },
          empty: {
            color: "#3a120a",
            backgroundColor: "transparent",
            "::placeholder": {
              color: "#444",
            },
          },
        },
      }}
    />
  </div>
</div>

排查及解决方案

  1. 确认后端环境变量加载状态

    • 检查后端.env文件,确保STRIPE_SECRET_KEY拼写正确,值为Stripe后台获取的Secret Key(格式为sk_test_xxxxxx或sk_live_xxxxxx),而非Publishable Key。
    • 修改.env后必须重启后端服务,process.env仅在服务启动时加载新值。
    • 在初始化Stripe实例前打印process.env.STRIPE_SECRET_KEY,确认输出为完整有效密钥,而非undefined或空字符串。
  2. 规范Stripe实例初始化顺序

    • 确保dotenv配置在引入Stripe之前执行:
      require('dotenv').config(); // 置于代码最顶部
      const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
      
  3. 验证密钥类型正确性

    • 前端使用Publishable Key(pk_test_xxxxxx),后端使用Secret Key,二者不可混用。检查/stripeapikey接口返回的是否为正确的Publishable Key。
  4. 排查网络请求拦截问题

    • 确认后端服务器可正常访问Stripe服务,无防火墙或代理拦截请求导致Authorization头部丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:22:03