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

Stripe集成报错:调用Stripe()传入空publishable key问题排查

Stripe支付集成报错:初始化使用空公钥

问题现象

电商项目集成Stripe支付功能时,输入Stripe官方测试信用卡卡号后页面直接刷新,无后续响应,不会跳转至/success路由,浏览器控制台抛出如下错误:

Uncaught (in promise) IntegrationError: Please call Stripe() with your publishable key. 
You used an empty string.

现有代码

前端app.js核心代码

function App() {
  const {isAuthenticated, user} = useSelector((state)=>state.user)
  const [stripeApiKey, setStripeApiKey] = useState("");

  async function getStripeApiKey() {
    const {data} = await axios.get("/api/v1/stripeapikey");
    setStripeApiKey(data.stripeApiKey)
  }

  useEffect(() => { 
    WebFont.load({
      google:{
        families: [ "Droid Sans", "Chilanka"],
      },
    });
    store.dispatch(loadUser())
    getStripeApiKey()
  }, []);

  return (
    <Router>
      <Header/>
      {isAuthenticated && <UserOptions user={user} />}
      <Routes>
        <Route path="/" element={<Home/>}/>
        <Route path="/product/:id" element={<ProductDetails/>}/>
        <Route path="/products" element={<Products/>}/>
        <Route path="/products/:keyword" element={<Products/>}/>
        <Route path="/search" element={<Search/>}/>
        <Route element={<ProtectedRoute/>}/>
          <Route path="/account" element={<Profile/>}/>
        <Route element={<ProtectedRoute/>}/>
          <Route path="/me/update" element={<UpdateProfile/>}/>
        <Route element={<ProtectedRoute/>}/>
          <Route path="/password/update" element={<UpdatePassword/>}/>
        <Route path="/password/forgot" element={<ForgotPassword/>}/> 
        <Route path="/password/reset/:token" element={<ResetPassword/>}/> 
        <Route path="/login" element={<LoginSignUp/>}/>
        <Route path="/cart" element={<Cart/>}/>
        <Route element={<ProtectedRoute/>}/>
          <Route path="/shipping" element={<Shipping/>}/>
        <Route element={<ProtectedRoute/>}/>
          <Route path="/order/confirm" element={<ConfirmOrder/>}/>
        <Route element={<ProtectedRoute/>}/>
          <Route  path="/process/payment" element={ <Elements stripe={loadStripe(stripeApiKey)}><Payment/></Elements>}/>
      </Routes>
      <Footer/>
    </Router>
  );
}

后端paymentController代码

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

exports.processPayment = catchAsyncErrors(async (req, res, next) => {
  const myPayment = await stripe.paymentIntents.create({
    amount: req.body.amount,
    currency: "inr",
    metadata: {
      company: "Ecommerce",
    },
  });

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

exports.sendStripeApiKey = catchAsyncErrors(async (req, res, next) => {
  res.status(200).json({ stripeApiKey: process.env.STRIPE_API_KEY });
});  

问题根因

  • stripeApiKey初始值为空字符串,getStripeApiKey是异步接口请求,组件首次渲染时接口尚未返回公钥值,此时已经调用loadStripe("")初始化Stripe实例,直接触发空key报错。
  • 支付路由没有加加载完成判断,即使后续接口返回了公钥,首次已经初始化的错误Stripe实例不会自动更新,导致支付流程完全失效。
  • 现有路由配置存在语法问题:所有<ProtectedRoute>都是自闭合标签,后续需要鉴权的路由(包括支付路由)实际没有被鉴权组件包裹,也会加剧逻辑异常。

修复方案

  1. 增加Stripe公钥加载判断,只有拿到有效公钥后才初始化Stripe实例、渲染支付组件,同时用useMemo缓存Stripe实例避免重复初始化:
    // 组件内新增缓存逻辑
    const stripePromise = useMemo(() => {
      return stripeApiKey ? loadStripe(stripeApiKey) : null;
    }, [stripeApiKey]);
    
    // 修正路由写法,把需要鉴权的路由嵌套在ProtectedRoute内部,同时加Stripe实例判断
    <Route element={<ProtectedRoute/>}>
      <Route path="/account" element={<Profile/>}/>
      <Route path="/me/update" element={<UpdateProfile/>}/>
      <Route path="/password/update" element={<UpdatePassword/>}/>
      <Route path="/shipping" element={<Shipping/>}/>
      <Route path="/order/confirm" element={<ConfirmOrder/>}/>
      <Route  
        path="/process/payment" 
        element={
          stripePromise 
            ? <Elements stripe={stripePromise}><Payment/></Elements>
            : <div>加载支付组件中...</div>
        }
      />
    </Route>
    
  2. 校验后端配置:
    • 确认后端环境变量中STRIPE_API_KEY为Stripe平台获取的可发布公钥(pk_开头),STRIPE_SECRET_KEY为密钥(sk_开头),没有拼写错误、没有多余空格。
    • 直接访问/api/v1/stripeapikey接口,确认接口正常返回公钥值,不存在鉴权拦截、跨域拦截导致前端拿不到key的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:06:25