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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:35:50