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

WooCommerce中排除指定品类商品计算免运费最低金额问题

解决WooCommerce中特定品类商品排除免运费门槛计算的问题

需求说明

已在WooCommerce配置多个配送区域,每个区域包含平邮(Flat rate)、免费自提(Local pickup)、满额免运费(Free shipping)三种配送方式。需要将leeggoed品类的商品排除在免运费资格的小计计算之外——即该品类商品的金额不计入满额免邮的达标门槛。

当前已实现免运费可用时隐藏平邮的功能,代码如下:

function hide_shipping_when_free_is_available( $rates, $package ) {
    $new_rates = array();
    foreach ( $rates as $rate_id => $rate ) {
        // 仅当免运费方式存在时调整配送选项
        if ( 'free_shipping' === $rate->method_id ) {
            $new_rates[ $rate_id ] = $rate;
            break;
        }
    }

    if ( ! empty( $new_rates ) ) {
        // 保留自提选项(如果存在)
        foreach ( $rates as $rate_id => $rate ) {
            if ('local_pickup' === $rate->method_id ) {
                $new_rates[ $rate_id ] = $rate;
                break;
            }
        }
        return $new_rates;
    }
    return $rates;
}

add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );

但用于调整免运费门槛计算的代码未生效,即使调整后的小计达标,仍无法触发免运费:

add_filter('woocommerce_shipping_free_shipping_is_available', function ($is_available, $package, $shipping_method) {
    $excluded_category = 'leeggoed'; // 要排除的品类别名
    $adjusted_total = 0; // 初始化调整后的小计

    // 步骤1:计算排除"leeggoed"品类后的购物车总额
    foreach (WC()->cart->get_cart() as $cart_item) {
        $product = $cart_item['data'];
        $product_id = $product->get_id();

        // 仅统计不在"leeggoed"品类的商品
        if (!has_term($excluded_category, 'product_cat', $product_id)) {
            $adjusted_total += $cart_item['line_subtotal'];
        }
    }

    // 步骤2:获取当前配送方式的免运费门槛
    if (isset($shipping_method->min_amount)) {
        $free_shipping_min_amount = (float) $shipping_method->min_amount;
    } else {
        $free_shipping_min_amount = 0; // 无门槛时默认设为0
    }

    // 步骤3:仅当调整后小计达标时,免运费可用
    return ($adjusted_total >= $free_shipping_min_amount);
}, 10, 3);

问题分析与修正代码

现有代码存在三个核心问题:

  1. 遍历整个购物车而非当前配送区域的商品包($package),多配送区域场景下计算逻辑错误;
  2. 变体商品使用变体ID检查分类,而品类通常设置在父产品上,导致判断失效;
  3. 直接覆盖原始判断结果,忽略了WooCommerce内置的免运费生效条件(如配送区域匹配、用户权限等)。

修正后的代码如下:

add_filter('woocommerce_shipping_free_shipping_is_available', function ($is_available, $package, $shipping_method) {
    // 先保留原始免运费生效条件(如配送区域匹配)
    if (!$is_available) {
        return false;
    }

    $excluded_category = 'leeggoed';
    $adjusted_total = 0;

    // 遍历当前配送区域的商品包,而非整个购物车
    foreach ($package['contents'] as $cart_item) {
        // 变体商品取父产品ID,普通商品取自身ID
        $product_id = $cart_item['variation_id'] ? $cart_item['product_id'] : $cart_item['data']->get_id();
        
        // 仅统计非排除品类的商品金额
        if (!has_term($excluded_category, 'product_cat', $product_id)) {
            $adjusted_total += $cart_item['line_subtotal'];
        }
    }

    $free_shipping_min_amount = isset($shipping_method->min_amount) ? (float)$shipping_method->min_amount : 0;

    // 结合原始条件与自定义金额判断返回结果
    return $adjusted_total >= $free_shipping_min_amount;
}, 10, 3);

关键修改点说明

  • 基于配送区域计算:用$package['contents']遍历当前配送区域的商品,确保多配送场景下计算准确;
  • 兼容变体商品:通过variation_id判断是否为变体,取父产品ID检查分类,避免因变体未设置品类导致的判断错误;
  • 保留原始规则:先校验$is_available,不破坏WooCommerce内置的免运费基础规则;
  • 金额逻辑统一:沿用购物车项的line_subtotal,与系统默认小计计算逻辑保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:53:20