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

WooCommerce 新客首单优惠券自动校验代码失效问题排查

WooCommerce新客首单优惠券校验代码不生效问题修复

问题背景

需要实现WooCommerce新客首单优惠券自动校验逻辑:自动判断用户是否为首次下单的新客,符合条件则允许使用指定优惠券,非新客则自动移除优惠券并弹出错误提示。将自定义PHP代码加入子主题functions.php后,在WordPress 6.0、WooCommerce 6.5.1环境下始终无法正常生效。

原实现代码如下:

add_action('woocommerce_after_checkout_validation','check_new_customer_coupon', 0);
function check_new_customer_coupon(){
    global $woocommerce;
    // 可自行修改优惠券编码
    $new_cust_coupon_code = 'new2022';

    $has_apply_coupon = false;

    foreach ( WC()->cart->get_coupons() as $code => $coupon ) {
        if($code == $new_cust_coupon_code) {
            $has_apply_coupon = true;
        }
    }

    if($has_apply_coupon) {

        if(is_user_logged_in()) {
            $user_id = get_current_user_id();

            // 查询所有订单
            $customer_orders = get_posts( array(
                    'meta_key'    => '_customer_user',
                    'meta_value'  => $user_id,
                    'post_type'   => 'shop_order',
                    'numberposts'=> -1
            ) );

            if(count($customer_orders) > 0) {
                $has_ordered = false;

                $statuses = array('wc-failed', 'wc-cancelled', 'wc-refunded');

                // 遍历订单,排除失败、取消、退款状态的订单
                foreach($customer_orders as $tmp_order) {

                    $order = wc_get_order($tmp_order->ID);
                    if(!in_array($order->get_status(), $statuses)) {
                        $has_ordered = true;
                    }
                }

                // 老用户移除优惠券
                if($has_ordered == true) {
                    WC()->cart->remove_coupon( $new_cust_coupon_code );
                    wc_add_notice( sprintf( "Coupon code: %s is only applicable for new customer." , $new_cust_coupon_code), 'error' );
                    return false;
                }
            } else {
                // 无历史订单判定为新客
                return true;
            }

        } else {
            // 未登录用户直接判定为新客
            return true;
        }
    }
}

代码失效核心原因

  • 钩子选择错误:woocommerce_after_checkout_validation触发时,购物车优惠券的计算逻辑已经执行完成,此时移除优惠券不会重新计算购物车金额,也无法阻断不符合条件的订单提交。同时WooCommerce 3.0+版本开始,直接用get_posts查询shop_order文章类型会漏掉HPOS高性能存储模式下的订单数据,且全量查询订单的写法性能很差。
  • 未覆盖游客校验场景:原代码默认所有未登录用户都是新客,实际上游客下单是通过账单邮箱关联历史订单的,同一游客使用相同邮箱重复下单时,原代码会错误判定为新客,存在逻辑漏洞。
  • 触发时机过晚:仅在提交结账的最后节点做校验,用户在购物车页、结账页加载阶段就能看到优惠券抵扣金额,直到提交订单才提示无法使用,体验很差。

修正后可直接使用的代码

将以下代码替换原代码加入子主题functions.php即可,注意修改第一行的优惠券编码为你自己的新客券编码:

// 配置项:修改为你的新客首单优惠券编码
define('NEW_CUSTOMER_COUPON_CODE', 'new2022');

// 购物车/结账页加载时校验优惠券有效性
add_action('woocommerce_before_cart', 'validate_new_customer_coupon');
add_action('woocommerce_before_checkout_form', 'validate_new_customer_coupon');
// 提交订单时二次校验,防止绕过前端校验
add_action('woocommerce_checkout_process', 'validate_new_customer_coupon');
// 手动应用优惠券时即时校验
add_filter('woocommerce_coupon_is_valid', 'check_coupon_valid_for_new_customer', 10, 2);

function check_coupon_valid_for_new_customer($is_valid, $coupon) {
    if($coupon->get_code() !== NEW_CUSTOMER_COUPON_CODE) return $is_valid;
    
    $has_valid_order = false;
    if(is_user_logged_in()) {
        $customer_id = get_current_user_id();
        // 用WooCommerce内置函数查询用户有效订单,兼容HPOS模式
        $customer_orders = wc_get_orders([
            'customer_id' => $customer_id,
            'status' => array_diff(array_keys(wc_get_order_statuses()), ['wc-failed', 'wc-cancelled', 'wc-refunded']),
            'limit' => 1,
            'return' => 'ids'
        ]);
        $has_valid_order = !empty($customer_orders);
    } else {
        // 游客场景通过账单邮箱校验历史订单
        $billing_email = isset($_POST['billing_email']) ? sanitize_email($_POST['billing_email']) : WC()->session->get('billing_email');
        if($billing_email) {
            $guest_orders = wc_get_orders([
                'billing_email' => $billing_email,
                'status' => array_diff(array_keys(wc_get_order_statuses()), ['wc-failed', 'wc-cancelled', 'wc-refunded']),
                'limit' => 1,
                'return' => 'ids'
            ]);
            $has_valid_order = !empty($guest_orders);
        }
    }

    if($has_valid_order) {
        $is_valid = false;
        add_filter('woocommerce_coupon_error', 'show_new_customer_coupon_error', 10, 3);
    }
    return $is_valid;
}

function show_new_customer_coupon_error($err, $err_code, $coupon) {
    if($coupon->get_code() === NEW_CUSTOMER_COUPON_CODE) {
        $err = sprintf('优惠券码 %s 仅限首次下单的新客户使用。', NEW_CUSTOMER_COUPON_CODE);
    }
    return $err;
}

function validate_new_customer_coupon() {
    if(!WC()->cart->has_discount(NEW_CUSTOMER_COUPON_CODE)) return;
    
    $has_valid_order = false;
    if(is_user_logged_in()) {
        $customer_id = get_current_user_id();
        $customer_orders = wc_get_orders([
            'customer_id' => $customer_id,
            'status' => array_diff(array_keys(wc_get_order_statuses()), ['wc-failed', 'wc-cancelled', 'wc-refunded']),
            'limit' => 1,
            'return' => 'ids'
        ]);
        $has_valid_order = !empty($customer_orders);
    } else {
        $billing_email = WC()->customer->get_billing_email();
        if($billing_email) {
            $guest_orders = wc_get_orders([
                'billing_email' => $billing_email,
                'status' => array_diff(array_keys(wc_get_order_statuses()), ['wc-failed', 'wc-cancelled', 'wc-refunded']),
                'limit' => 1,
                'return' => 'ids'
            ]);
            $has_valid_order = !empty($guest_orders);
        }
    }

    if($has_valid_order) {
        WC()->cart->remove_coupon(NEW_CUSTOMER_COUPON_CODE);
        wc_add_notice(sprintf('优惠券码 %s 仅限首次下单的新客户使用,已自动移除。', NEW_CUSTOMER_COUPON_CODE), 'error');
    }
}

代码说明

  • 兼容WooCommerce 3.0+到最新版本,支持HPOS高性能订单存储模式,不会出现订单查询遗漏问题
  • 覆盖购物车页、结账页、提交订单、手动应用优惠券四个校验节点,不会出现校验绕过问题
  • 同时支持登录用户和游客的新客身份判定,游客通过账单邮箱匹配历史有效订单
  • 无效优惠券会被自动移除,同时展示对应错误提示,用户体验更流畅

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:27:04