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

Stripe自定义表单集成报错:StripeCheckout未定义及支付参数缺失

解决Stripe自定义表单支付的一系列错误问题

看起来你在混用Stripe的不同版本API,加上合规性和配置问题导致了这一堆错误,我来一步步帮你理清并解决:


核心问题拆解

首先要明确两个关键错误根源:

  1. 你用了Stripe v3的JS SDK,却在调用v2的StripeCheckout旧API,这直接导致StripeCheckout is not defined错误
  2. 直接收集信用卡号、有效期、CVC是违反Stripe PCI合规要求的,你不能自己写输入框处理这些敏感信息,必须用Stripe Elements来托管输入,否则不仅报错,还会触发合规风险

分步解决方案

1. 先修复Stripe密钥配置问题

首先确保你的Laravel配置是正确的:

  • 在.env文件里填入正确的Stripe密钥:
    STRIPE_KEY=pk_test_你的公钥
    STRIPE_SECRET=sk_test_你的密钥
    
  • 清除Laravel配置缓存(如果之前缓存过):
    php artisan config:clear
    
  • 在JS里引用密钥时必须加引号,否则Laravel解析后会被JS当成变量:
    const stripe = Stripe("{{ config('services.stripe.key') }}");
    

2. 替换自定义表单为Stripe Elements(合规且正确)

删掉你自己写的卡号、有效期、CVC输入框,改用Stripe Elements来生成安全的输入组件:

<form action="{{ route('registration.charge') }}" method="post" id="paymentForm">
    {{ csrf_field() }}
    <input type="hidden" name="stripePaymentMethod" id="stripePaymentMethod"/>
    
    <!-- Stripe Elements 卡片输入容器 -->
    <div class="form-group font-size-sm">
        <label class="text-gray">Card Number</label>
        <div id="card-element" class="form-control"></div>
        <!-- 错误提示区域 -->
        <div id="card-errors" role="alert" class="text-danger mt-1"></div>
    </div>

    <input type="submit" id="confirmPayment" class="btn btn-primary" value="Confirm"/>
</form>

3. 修正前端JS代码(使用v3正确API)

替换原来的JS,用Stripe Elements处理卡片输入和支付流程:

<script src="https://js.stripe.com/v3/"></script>
<script>
    // 初始化Stripe
    const stripe = Stripe("{{ config('services.stripe.key') }}");
    const elements = stripe.elements();

    // 自定义Elements输入框样式(可选,匹配你的网站风格)
    const style = {
        base: {
            color: '#32325d',
            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
            fontSize: '16px',
            '::placeholder': {
                color: '#aab7c4'
            }
        },
        invalid: {
            color: '#fa755a',
            iconColor: '#fa755a'
        }
    };

    // 创建卡片输入组件并挂载到页面
    const cardElement = elements.create('card', {style: style});
    cardElement.mount('#card-element');

    // 监听卡片输入错误
    cardElement.addEventListener('change', function(event) {
        const errorElement = document.getElementById('card-errors');
        if (event.error) {
            errorElement.textContent = event.error.message;
        } else {
            errorElement.textContent = '';
        }
    });

    // 处理表单提交
    const form = document.getElementById('paymentForm');
    form.addEventListener('submit', async function(event) {
        event.preventDefault();

        // 创建PaymentMethod(替代旧的stripeToken)
        const { paymentMethod, error } = await stripe.createPaymentMethod({
            type: 'card',
            card: cardElement,
        });

        if (error) {
            // 显示卡片错误信息
            document.getElementById('card-errors').textContent = error.message;
        } else {
            // 将PaymentMethod ID存入隐藏字段,提交表单到后端
            document.getElementById('stripePaymentMethod').value = paymentMethod.id;
            form.submit();
        }
    });
</script>

4. 修正后端Charge代码(使用PaymentMethod)

Stripe v3推荐用PaymentMethod替代旧的token,修改你的charge方法:

use Stripe\Customer;
use Stripe\Charge;
use Stripe\Exception\CardException;

public function charge(Request $request)
{
    Stripe::setApiKey(config('services.stripe.secret'));

    try {
        // 获取前端传递的PaymentMethod ID
        $paymentMethodId = $request->stripePaymentMethod;

        // 创建Customer(推荐,方便后续重复扣款)
        $customer = Customer::create([
            'payment_method' => $paymentMethodId,
            'email' => auth()->user()->email, // 替换为实际用户邮箱
            'invoice_settings' => [
                'default_payment_method' => $paymentMethodId,
            ],
        ]);

        // 创建扣款订单
        $charge = Charge::create([
            'currency' => 'eur',
            'amount' => 1000, // 单位是分,1000=10欧元
            'customer' => $customer->id, // 使用Customer ID而非直接传入source
        ]);

        // 支付成功后的逻辑,比如跳转成功页面
        return redirect()->route('payment.success')->with('success', 'Payment completed!');

    } catch (CardException $e) {
        // 卡片相关错误(余额不足、过期等)
        return back()->withErrors($e->getError()->message);
    } catch (\Exception $e) {
        // 其他通用错误
        return back()->withErrors('Payment failed, please try again later.');
    }
}

错误逐个解决说明

  • Must provide source or customer:现在后端用Customer ID替代了空的stripeToken,满足Stripe API要求
  • Uncaught ReferenceError: StripeCheckout is not defined:改用了v3的Elements API,不再依赖旧的StripeCheckout对象
  • Uncaught ReferenceError: pk_test_.... is not defined:密钥被包裹在引号里,Laravel解析后是合法的字符串,不会被JS当成变量
  • Invalid value for Stripe(): apiKey should be a string:确保.env配置正确并清除缓存后,config('services.stripe.key')会返回正确的字符串密钥

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:07:59