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

WooCommerce按重量计算运费及免运费类失效问题求助

Fix WooCommerce Weight-Based Shipping with Free Shipping Class Priority

Let's fix your free shipping class issue while honoring your core rule: if there's at least one paid shipping item in the cart, weight-based rates apply; only when all items are free shipping do we show the free option.

The Problem with Your Original Code

Your current code only checks the total cart weight, but it doesn't account for the free_shipping class on individual products. It always hides the free shipping option whenever the weight falls into either tier, which is why the free shipping class never triggers.

Fixed Code

Replace your existing custom_tiered_shipping_rates function with this updated version:

add_filter( 'woocommerce_package_rates', 'custom_tiered_shipping_rates_with_free_class', 9999, 2 );
function custom_tiered_shipping_rates_with_free_class( $rates, $package ) {
    // Check if any item in the cart requires paid shipping (not free_shipping class)
    $has_paid_shipping_items = false;
    foreach ( $package['contents'] as $item ) {
        $product = $item['data'];
        $shipping_class_slug = $product->get_shipping_class();
        
        // Flip the flag if we find a non-free-shipping item
        if ( $shipping_class_slug !== 'free_shipping' ) {
            $has_paid_shipping_items = true;
            break;
        }
    }

    // Scenario 1: Cart has paid shipping items – use weight-based rates
    if ( $has_paid_shipping_items ) {
        $total_weight = WC()->cart->get_cart_contents_weight();
        
        // Show only <19kg rate if weight is under 19kg
        if ( $total_weight < 19 ) {
            if ( isset( $rates['flat_rate:21'] ) ) {
                unset( $rates['flat_rate:22'], $rates['flat_rate:24'] );
            }
        }
        // Show only >19kg rate if weight exceeds 19kg (matches your original $300 rule)
        elseif ( $total_weight > 19 ) {
            if ( isset( $rates['flat_rate:22'] ) ) {
                unset( $rates['flat_rate:21'], $rates['flat_rate:24'] );
            }
        }
        // Optional: Handle exact 19kg (adjust if you want a specific rate here)
        else {
            unset( $rates['flat_rate:21'], $rates['flat_rate:22'] );
        }
    } 
    // Scenario 2: All items are free shipping – only show free option
    else {
        if ( isset( $rates['flat_rate:24'] ) ) {
            unset( $rates['flat_rate:21'], $rates['flat_rate:22'] );
        }
    }

    return $rates;
}

Key Changes Explained

  1. Paid Shipping Check: We loop through every item in the cart to check if any product doesn't have the free_shipping class. If so, we stick strictly to weight-based pricing.
  2. Free Shipping Only for All-Free Carts: Only when every single item is marked with free_shipping do we hide the paid rates and show the free shipping option.
  3. Weight Rule Alignment: I adjusted the weight check to >19 to match your original rule (over 19kg = $300). If you meant to use 20kg as the threshold, just change that value to >20.

Important Checks to Ensure It Works

  • Verify Shipping Class Slug: Go to WooCommerce > Products > Shipping Classes and confirm your free shipping class has the slug free_shipping. If it's different, update the value in the code.
  • Confirm Rate IDs: Double-check that flat_rate:21, flat_rate:22, and flat_rate:24 match the actual IDs of your shipping methods. You can find these by editing a shipping method and looking at the URL (look for the rate_id parameter).
  • Clear WooCommerce Cache: After adding the code, go to WooCommerce > Settings > Shipping, make a tiny change (like toggling a setting off/on), and save. This clears the shipping rate cache so your new rules take effect.

内容的提问来源于stack exchange,提问作者Victor S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:06:00