Laravel中如何通过新Ajax将支付结果传递至控制器
没问题,完全可以通过新增一个独立的Ajax请求来实现这个需求!既然原控制器的try块动不了,那我们就把支付结果的处理逻辑完全剥离到新的控制器方法里,再在Midtrans的回调中发起请求传递数据。下面是具体的实现步骤:
1. 创建新的控制器方法接收支付结果
首先在你的控制器(比如沿用原有的订单控制器,或者新建专门的支付处理控制器)里新增一个方法,用来接收Midtrans返回的支付结果并更新数据库:
use Illuminate\Http\Request; public function updatePaymentStatus(Request $request) { // 验证必要参数,确保订单ID和支付结果存在 $request->validate([ 'order_id' => 'required|integer', 'payment_result' => 'required|array' ]); try { // 根据订单ID找到对应的订单记录 $order = \App\Models\Order::findOrFail($request->order_id); // 根据Midtrans返回的状态码更新订单状态(状态码请参考Midtrans官方文档调整) $statusCode = $request->payment_result['status_code']; switch ($statusCode) { case '200': $order->status = 'paid'; // 支付成功 break; case '201': $order->status = 'pending'; // 支付待处理 break; default: $order->status = 'failed'; // 支付失败 } // 可以额外存储支付结果的完整信息,方便后续排查 $order->payment_response = json_encode($request->payment_result); $order->save(); return response()->json(['message' => '支付状态更新成功'], 200); } catch (\Exception $e) { return response()->json(['message' => '更新失败:' . $e->getMessage()], 500); } }
2. 添加对应的路由
在routes/web.php中新增一条POST路由,指向刚才创建的控制器方法:
Route::post('/update-payment-status', [YourController::class, 'updatePaymentStatus'])->name('payment.update');
(记得把YourController::class替换成你实际的控制器类名)
3. 修改前端JavaScript的回调逻辑
接下来修改原有的JS代码,在Midtrans的onSuccess、onPending、onError回调中,新增一个Ajax请求把支付结果和订单ID发送到新控制器。注意要让订单ID变量能被回调函数访问到:
<script type="text/javascript"> $('.pay-button').click(function (event) { $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); event.preventDefault(); var prdfoId = $(this).data('id'); // 把订单ID变量放在外层,让回调能访问 $.ajax({ url: '{{url("orderspayonline")}}/'+encodeURI(prdfoId), type: "POST", cache: false, success: function(data) { var resultType = document.getElementById('result-type'); var resultData = document.getElementById('result-data'); function changeResult(type,data){ $("#result-type").val(type); $("#result-data").val(JSON.stringify(data)); } // 封装发送支付结果的函数,避免重复写Ajax代码 function sendPaymentResult(result) { $.ajax({ url: '{{url("update-payment-status")}}', type: "POST", cache: false, data: { order_id: prdfoId, payment_result: result }, success: function(response) { console.log('支付状态已更新:', response); }, error: function(xhr) { console.error('更新支付状态失败:', xhr.responseText); } }); } snap.pay(data, { onSuccess: function(result){ changeResult('success', result); console.log(result.status_message); console.log(result); sendPaymentResult(result); // 发送成功结果到控制器 $("#payment-form").submit(); }, onPending: function(result){ changeResult('pending', result); console.log(result.status_message); sendPaymentResult(result); // 发送待处理结果到控制器 $("#payment-form").submit(); }, onError: function(result){ changeResult('error', result); console.log(result.status_message); sendPaymentResult(result); // 发送失败结果到控制器 $("#payment-form").submit(); } }); } }); }); </script>
关键注意事项
- Midtrans状态码匹配:上面控制器里的状态码(200、201)是示例,你需要根据Midtrans官方文档里的实际返回状态码来调整判断逻辑。
- CSRF保护:已经通过
$.ajaxSetup全局设置了CSRF头,确保POST请求不会出现419错误。 - 订单ID传递:把点击事件中获取的
prdfoId传递给新Ajax,让控制器能精准定位到要更新的订单。 - 错误调试:新Ajax里添加了error回调,方便你排查更新失败的具体原因。
这样就能在不修改原控制器try块的前提下,完美实现支付结果的数据库更新啦!
内容的提问来源于stack exchange,提问作者mafortis
相关产品推荐
相关产品推荐

