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

Laravel+Vue集成Stripe创建Checkout会话报错:$config must be a string or an array

Stripe Checkout会话创建报错:$config must be a string or an array

报错信息

{ "status": "error", "message": "There was an error creating the checkout session: $config must be a string or an array" }

前端请求代码

const fullName = ref(null);
const gender = ref(null);
const nationalCardID = ref(null);
const purchase = async () => {
    const button = document.getElementById('purchase-btn');
    button.innerHTML = '<span class="loading loading-spinner loading-md"></span>';
    await new Promise(resolve => setTimeout(resolve, 2000));
    try {
        await axios.post('/order-checkout', {
            offerId: selectedOffer.value.id,
            quantity: checked.value ? 2 : 1,
            fullName: fullName.value,
            gender: gender.value,
            nationalCardID: nationalCardID.value,
        }).then((res) => {
            goToStripeCheckout(res.data.checkout_url)
        }).catch(async (err) => {
            toast.error(err.response.data.message);
            console.error('Error placing order:', err);
            showModal.value = false
            await new Promise(resolve => setTimeout(resolve, 500));
            showModal.value = true;
        });
    } catch (error) {
        toast.error(error);
        console.error('Unexpected error:', error);
    }
    button.innerHTML = 'Purchase'
};

后端处理函数

public function orderCheckout(Request $request)
{
    $validatedData = $request->validate([
        'offerId' => 'required|integer|exists:offers,id',
        'quantity' => 'required|integer',
        'fullName' => 'required|string|max:255',
        'gender' => 'required|string|max:255',
        'nationalCardID' => 'required|string|max:500'
    ]);

    $offer = Offer::find($validatedData['offerId']);

    if (!$offer) {
        return response()->json([
            'status' => 'error',
            'message' => 'Offer not found.'
        ], 404);
    }

    try {
        $stripe = new StripeClient(env('STRIPE_SECRET_KEY'));

        $checkout_session = $stripe->checkout->sessions->create([
            'line_items' => [[
                'price_data' => [
                    'currency' => 'usd',
                    'product_data' => [
                        'name' => $offer->name,
                    ],
                    'unit_amount' => $offer->total_with_tax * 100,
                ],
                'quantity' => $validatedData['quantity'],
            ]],
            'mode' => 'payment',
            'success_url' => config('app.frontend_url') . '/checkout/success?session_id={CHECKOUT_SESSION_ID}',
            'cancel_url' => config('app.frontend_url') . '/checkout/cancel',
        ]);

        $order_id = uniqid() . mt_rand(100000, 999999);

        $order = new Order();
        $order->order_id = $order_id;
        $order->status = 'unpaid';
        $order->total_price = $offer->total_with_tax;
        $order->session_id = $checkout_session->id;
        $order->user_id = Auth::user()->id;
        $order->offer_id = $validatedData['offerId'];
        $order->full_name = $validatedData['fullName'];
        $order->gender = $validatedData['gender'];
        $order->national_card_id = $validatedData['nationalCardID'];
        $order->save();

        $countOrdersCacheKey = 'count_orders';
        if (Cache::get($countOrdersCacheKey)) {
            Cache::forget($countOrdersCacheKey);
        }
        
        $admins = User::where('is_admin', 1)->pluck('id');
        DB::transaction(function () use ($admins) {
            $notifications = [];
            foreach ($admins as $adminId) {
                $notifications[] = [
                    'user_id' => $adminId,
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
            OrderNotification::insert($notifications);

            event(new OrderNotifications('New Order! Check it out'));

            foreach ($admins as $adminId) {
                Cache::forget("order_notifications_{$adminId}");
            }
        });

        return response()->json([
            'status' => 'success',
            'message' => 'Checkout session created successfully.',
            'checkout_url' => $checkout_session->url,
            'order_id' => $order_id,
            'order' => $order
        ]);
    } catch (\Exception $e) {
        return response()->json([
            'status' => 'error',
            'message' => 'There was an error creating the checkout session: ' . $e->getMessage()
        ], 500);
    }
}

用户说明:已在.env文件中正确配置Stripe密钥,且使用最新版本的Stripe PHP SDK,请求排查报错问题。


问题排查与解决

这个报错核心是StripeClient初始化参数不符合要求,以下是具体排查和修复方案:

1. 确认Stripe密钥是否正确加载

  • 在new StripeClient前添加dd(env('STRIPE_SECRET_KEY'));,运行请求查看输出。如果为空或格式错误(非sk_live_/sk_test_开头),说明.env配置未被正确读取。
  • 修复步骤:
    • 检查.env文件中STRIPE_SECRET_KEY的拼写和格式,确保无多余空格或引号。
    • 运行php artisan config:clear清除配置缓存,避免Laravel使用旧缓存。
    • 生产环境建议通过配置文件读取密钥:在config/services.php中添加
      'stripe' => [
          'secret' => env('STRIPE_SECRET_KEY'),
      ]
      
      然后初始化代码改为new StripeClient(config('services.stripe.secret'));

2. 适配Stripe SDK的初始化格式

  • 最新版Stripe SDK(v10+)支持字符串密钥或数组配置,但空值会触发该报错。如果使用数组格式初始化,可明确指定参数:
    $stripe = new StripeClient([
        'api_key' => env('STRIPE_SECRET_KEY'),
        'stripe_version' => '2024-06-20', // 推荐指定API版本,避免兼容性问题
    ]);
    
  • 用composer show stripe/stripe-php查看当前SDK版本,对照官方文档调整初始化代码。

3. 排查环境变量覆盖问题

  • 生产环境下,确认服务器环境变量未覆盖本地.env配置,确保部署时.env文件已正确上传。

4. 验证其他潜在关联问题

  • 确认$offer->total_with_tax是有效数值,避免unit_amount出现非整数或空值(虽不触发当前报错,但会引发后续Stripe请求失败)。
  • 检查config('app.frontend_url')是否返回有效URL,确保success_url和cancel_url格式合规。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 04:19:52