WooCommerce:限制payment gateway跳转,结账页popup modal处理支付
WooCommerce 实现结账页弹窗处理第三方支付方案
核心思路
绕开默认支付网关的跳转逻辑,通过AJAX拦截结账提交,后端完成订单生成、第三方API调用后,把数据返回前端渲染弹窗,全程留在结账页操作。
1. 前端拦截结账提交(JS代码)
针对你的特定支付方式(比如支付方式ID为custom_payment_gateway),阻止默认表单提交,改用AJAX发送请求:
jQuery(document).ready(function($) { // 监听结账表单提交事件 $('form.checkout').on('submit', function(e) { const selectedGateway = $('input[name="payment_method"]:checked').val(); // 仅拦截目标支付方式,其他支付方式走默认流程 if (selectedGateway !== 'custom_payment_gateway') return; e.preventDefault(); // 阻止页面跳转 const $placeOrderBtn = $(this).find('.place-order'); $placeOrderBtn.prop('disabled', true).text('处理中...'); // 收集表单数据 const formData = $(this).serialize(); // 发送AJAX请求到后端 $.ajax({ url: wc_checkout_params.ajax_url, type: 'POST', data: { action: 'process_custom_payment', form_data: formData, security: wc_checkout_params.checkout_nonce }, success: function(response) { $placeOrderBtn.prop('disabled', false).text('下单'); if (response.success) { // 渲染弹窗并传入订单、API数据 renderPaymentModal(response.data.order_data, response.data.api_response); } else { // 显示错误提示 $('form.checkout').find('.woocommerce-error').remove(); $('form.checkout').prepend(`<div class="woocommerce-error">${response.data.message}</div>`); } }, error: function() { $placeOrderBtn.prop('disabled', false).text('下单'); $('form.checkout').find('.woocommerce-error').remove(); $('form.checkout').prepend('<div class="woocommerce-error">服务器错误,请重试</div>'); } }); }); // 渲染支付弹窗函数 function renderPaymentModal(orderData, apiResponse) { // 移除已存在的弹窗 $('#custom-payment-modal').remove(); // 构建弹窗HTML结构 const modalHtml = ` <div id="custom-payment-modal" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);display:flex;justify-content:center;align-items:center;z-index:9999;"> <div style="background:white;padding:2rem;border-radius:8px;width:90%;max-width:500px;"> <h3>订单 #${orderData.id} 支付确认</h3> <p>应付金额: ${orderData.total}</p> <p>支付流水号: ${apiResponse.payment_id}</p> <div style="margin-top:1.5rem;display:flex;gap:1rem;"> <button id="proceed-payment" style="flex:1;padding:0.8rem;background:#007cba;color:white;border:none;border-radius:4px;">前往支付</button> <button id="cancel-payment" style="flex:1;padding:0.8rem;background:#dc3232;color:white;border:none;border-radius:4px;">取消支付</button> </div> </div> </div> `; // 添加弹窗到页面 $('body').append(modalHtml); // 绑定支付跳转事件 $('#proceed-payment').on('click', function() { window.location.href = apiResponse.payment_url; }); // 绑定取消支付事件 $('#cancel-payment').on('click', function() { $.ajax({ url: wc_checkout_params.ajax_url, type: 'POST', data: { action: 'cancel_custom_payment_order', order_id: orderData.id, security: wc_checkout_params.checkout_nonce }, success: function() { $('#custom-payment-modal').remove(); $('form.checkout').find('.woocommerce-message').remove(); $('form.checkout').prepend('<div class="woocommerce-message">订单已取消,请重新操作</div>'); } }); }); // 点击遮罩关闭弹窗 $('#custom-payment-modal').on('click', function(e) { if (e.target === this) $(this).remove(); }); } });
将这段脚本通过wp_enqueue_script挂载到结账页,确保依赖jQuery和WooCommerce内置的wc-checkout脚本。
2. 后端AJAX处理(PHP代码)
在主题functions.php或自定义插件中添加以下代码,处理订单生成、API调用和状态更新:
// 注册AJAX处理动作(支持登录/未登录用户) add_action('wp_ajax_process_custom_payment', 'process_custom_payment'); add_action('wp_ajax_nopriv_process_custom_payment', 'process_custom_payment'); function process_custom_payment() { // CSRF安全验证 check_ajax_referer('woocommerce-checkout', 'security'); // 解析表单数据 parse_str($_POST['form_data'], $formData); $checkout = WC()->checkout(); try { // 生成WooCommerce订单 $order_id = $checkout->create_order(); $order = wc_get_order($order_id); // 设置订单为待支付状态 $order->update_status('on-hold', '等待第三方支付确认'); // 准备第三方API请求参数 $api_data = [ 'order_id' => $order_id, 'amount' => $order->get_total(), 'currency' => $order->get_currency(), 'customer_email' => $order->get_billing_email() ]; // 调用第三方API $api_response = wp_remote_post('第三方API端点地址', [ 'headers' => ['Content-Type' => 'application/json'], 'body' => json_encode($api_data), 'timeout' => 30 ]); if (is_wp_error($api_response)) throw new Exception('第三方API调用失败'); $api_body = json_decode(wp_remote_retrieve_body($api_response), true); if (!isset($api_body['success']) || !$api_body['success']) { throw new Exception('支付初始化失败: ' . $api_body['message']); } // 保存API响应到订单元数据 $order->update_meta_data('_custom_payment_api_response', $api_body); $order->save(); // 返回数据给前端 wp_send_json_success([ 'order_data' => [ 'id' => $order_id, 'total' => $order->get_formatted_order_total(), 'status' => $order->get_status() ], 'api_response' => $api_body ]); } catch (Exception $e) { // 订单生成失败时清理状态 if (isset($order_id)) { $order = wc_get_order($order_id); $order->update_status('failed', '支付处理失败: ' . $e->getMessage()); } wp_send_json_error(['message' => $e->getMessage()]); } } // 取消订单的AJAX处理 add_action('wp_ajax_cancel_custom_payment_order', 'cancel_custom_payment_order'); add_action('wp_ajax_nopriv_cancel_custom_payment_order', 'cancel_custom_payment_order'); function cancel_custom_payment_order() { check_ajax_referer('woocommerce-checkout', 'security'); $order_id = intval($_POST['order_id']); $order = wc_get_order($order_id); if ($order && $order->get_status() === 'on-hold') { $order->update_status('cancelled', '用户主动取消支付'); wp_send_json_success(); } else { wp_send_json_error(['message' => '无法取消该订单']); } }
3. 关键注意事项
- 替换代码中的
custom_payment_gateway为你实际的支付方式ID(可在WooCommerce支付设置中查看) - 订单状态可根据需求调整,也可创建自定义状态(如
pending_payment) - 第三方API调用部分需根据接口文档调整请求头、参数格式
- 弹窗样式可替换为主题CSS类,保持视觉统一
- 必须保留
check_ajax_referer验证,防止跨站请求伪造
内容的提问来源于stack exchange,提问作者VIKEE R
相关产品推荐
相关产品推荐

