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

Next.js集成Stripe自定义Payment Element加载失败及key未定义问题

Next.js集成Stripe Payment Element UI不显示及API key undefined问题解决

问题现象

  • 页面加载时短暂显示UI骨架,随后无任何支付UI渲染
  • 网络请求中调用Stripe Payment Intent接口时出现key=undefined错误,请求地址带?key=undefined参数

核心原因

  1. 未正确初始化Stripe客户端实例并传入合法的发布可密钥
  2. 手动创建挂载Payment Element的方式不符合React组件规范,导致上下文异常
  3. Next.js环境变量未按规则配置,客户端无法读取到Stripe密钥

解决方案

1. 正确配置Stripe实例与Elements上下文(父组件)

在包含CheckoutForm的父页面中,使用loadStripe初始化客户端实例,并通过<Elements>组件传递上下文和Payment Intent的clientSecret:

import { loadStripe } from "@stripe/stripe-js";
import { Elements } from "@stripe/react-stripe-js";
import CheckoutForm from "./CheckoutForm";

// Next.js客户端环境变量必须以NEXT_PUBLIC_开头,确保能被浏览器访问
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!);

export default function CheckoutPage() {
  // 此处clientSecret建议通过服务端API获取,而非硬编码
  const clientSecret = "pi_xxx_secret_xxx";

  return (
    <Elements 
      stripe={stripePromise} 
      options={{ 
        clientSecret,
        // 全局外观配置可在此处定义
        appearance: {}
      }}
    >
      <CheckoutForm />
    </Elements>
  );
}

2. 修正CheckoutForm组件,使用官方推荐的PaymentElement组件

移除手动创建挂载的逻辑,直接使用<PaymentElement>组件,并配置自定义布局:

import { useState } from "react";
import { useStripe, useElements, PaymentElement } from "@stripe/react-stripe-js";

interface CheckoutFormProps {
  customerId?: string;
  priceId?: string;
}

export default function CheckoutForm(props: CheckoutFormProps) {
  const [error, setError] = useState<string | undefined>(undefined);
  const [disabled, setDisabled] = useState(false);
  const stripe = useStripe();
  const elements = useElements();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!stripe || !elements) return;

    setDisabled(true);
    const { error } = await stripe.confirmPayment({
      elements,
      confirmParams: {
        return_url: `${window.location.origin}/payment-success`,
      },
    });

    if (error) {
      setError(error.message);
      setDisabled(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement
        options={{
          layout: {
            type: "accordion",
            defaultCollapsed: false,
            radios: true,
            spacedAccordionItems: false,
          },
        }}
      />
      {error && <div style={{ color: "#dc2626" }}>{error}</div>}
      <button disabled={!stripe || disabled} type="submit">
        Pay Now
      </button>
    </form>
  );
}

3. 配置Next.js环境变量

在项目根目录的.env.local文件中添加:

# 客户端使用,必须带NEXT_PUBLIC_前缀
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_xxx
# 服务端使用,无需前缀
STRIPE_SECRET_KEY=sk_xxx

关键错误点说明

  • 原代码中注释的var stripe = new Stripe(...)是服务端SDK用法,客户端必须使用loadStripe初始化
  • 手动调用elements.create并挂载的方式会脱离React上下文,导致Stripe无法正确传递密钥和配置
  • API请求key=undefined是因为Stripe实例未正确初始化,请求时无法带上合法的发布可密钥参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:43:26