如何通过Ajax实现Stripe支付无页面跳转并展示结果
解决无跳转Ajax Stripe支付问题
让我帮你排查下问题,你当前的代码里有几个关键原因导致了页面跳转和Ajax错误,咱们一步步来修复:
核心问题分析
- 同时触发了表单提交和Ajax请求:你在Stripe的
token回调里先执行了表单提交,这会直接触发页面跳转,导致后续的Ajax请求被中断,自然会抛出错误。 - 前后端参数不匹配:Ajax请求传的参数是
tokenid,但后端代码里拿的是$request->stripeToken,根本获取不到正确的支付令牌。 - Ajax请求缺少CSRF验证:Laravel默认会拦截不带CSRF令牌的POST请求,这也是触发错误的潜在原因。
步骤1:修改前端Stripe代码(核心修复)
移除表单提交逻辑,修正参数名并带上CSRF令牌,同时处理支付结果的提示:
// 可选:全局设置CSRF令牌,避免每个Ajax都手动加 $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); let stripe = StripeCheckout.configure({ key: "{{config('services.stripe.key')}}", image: "", locale: "auto", token: (token) => { // 移除表单提交代码,只保留Ajax请求 $.ajax({ type: "POST", url: '{{route('registration.charge')}}', // 注意路由名要和后端配置一致,你之前写的conferences.charge是笔误 data: { stripeToken: token.id, // 参数名和后端的$request->stripeToken对应 email: token.email }, success: function(data) { if (data.success) { // 这里替换成你想要的成功提示,比如插入页面元素或弹窗 alert('支付成功!'); // 示例:隐藏支付按钮,显示成功信息 $('#payment').hide(); $('#payment-status').html('<div class="alert alert-success">支付已完成</div>'); } else { alert('支付失败:' + data.message); } // 恢复支付按钮可用状态 $('#payment').prop('disabled', false); }, error: function(xhr) { let errorMsg = xhr.responseJSON?.message || '支付过程中出现未知错误'; alert('支付出错:' + errorMsg); console.log(xhr); // 恢复支付按钮可用状态 $('#payment').prop('disabled', false); } }); } }); document.getElementById('payment').addEventListener('click', function(e){ // 点击后禁用按钮,防止重复提交 this.disabled = true; stripe.open({ name: 'test', description: 'test', amount: '{{session('total')}}' }); e.preventDefault(); });
步骤2:优化后端Charge方法(统一返回格式)
你的后端代码已经处理了异常,但可以优化返回格式,让前端更易判断状态:
public function charge(Request $request) { Stripe::setApiKey(config('services.stripe.secret')); $source = $request->stripeToken; $selectedRtypes = Session::get('selectedRtypes'); $amount = (collect($selectedRtypes)->first()['total']) * 100; try{ Charge::create([ 'currency' => 'eur', 'description' => 'Example charge', 'amount' => $amount, 'source' => $source, ]); return response()->json([ 'success' => true, 'message' => '支付成功' ], 200); } catch(\Exception $e){ return response()->json([ 'success' => false, 'message' => $e->getMessage() ], 422); } }
步骤3:确保页面存在CSRF元标签
在页面的<head>里添加CSRF元标签,配合前面的全局Ajax设置使用:
<meta name="csrf-token" content="{{ csrf_token() }}">
这样修改后,用户点击支付完成Stripe验证后,会通过Ajax提交请求,页面不会跳转,同时能根据后端返回的结果显示对应的成功/失败提示。
内容的提问来源于stack exchange,提问作者johnW
相关产品推荐
相关产品推荐

