I’m trying to apply a discount to one shipping class for products currently in a cart. This is applied on the checkout view.
In Woocommerce backend, the option is set to charge each shipping class individually. Also, I use only one shipping method named “flat rate”.
Based on Override all shipping costs for a specific shipping class in Woocommerce, the following code that should apply the discount:
add_filter('woocommerce_package_rates', 'shipping_class_null_shipping_costs', 10, 2); function shipping_class_null_shipping_costs( $rates, $package ){ if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return $rates; $shipping_class_slug = 'large'; // Your shipping class slug $found = false; // Loop through cart items and checking for the specific defined shipping class foreach( $package['contents'] as $cart_item ) { if( $cart_item['data']->get_shipping_class() == $shipping_class_slug ) $found = true; } $percentage = 50; // 50% $subtotal = WC()->cart->get_cart_shipping_total(); // Set shipping costs to 50% discount if shipping class is found if( $found ){ foreach ( $rates as $rate_key => $rate ){ $has_taxes = false; // Targetting "flat rate" if( 'flat_rate' === $rate->method_id ){ $rates[$rate_key]->cost = $subtotal; } } } return $rates; }
But whatever I try, the calculated shipping result is $0.
What am I doing wrong here and what would be the correct way to apply a discount to shipping class?
Thank you.
Advertisement
Answer
Update (Just about settings)
To add a discount only for “large” shipping class on “Flat rate” shipping method, You will have to:
- Set the discounted price directly on your shipping method cost.
- Enable option “Per class: Charge shipping for each shipping class individually”
Like:
Original answer:
The following code will set the shipping cost of 50% for “Flat rate” shipping method, when a specific defined shipping method is found in cart items.
Testing: Temporary “Enable debug mode” in Shipping settings under Shipping options tab…
Shipping “Flat rate” settings: Your shipping classes costs should be defined.
In the code below define in each function your shipping class slug and your custom notice:
add_filter('woocommerce_package_rates', 'shipping_costs_discounted_based_on_shipping_class', 10, 2); function shipping_costs_discounted_based_on_shipping_class( $rates, $package ){ if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return $rates; // Your settings below $shipping_class = 'large'; // <=== Shipping class slug $percentage = 50; // <=== Discount percentage $discount_rate = $percentage / 100; $is_found = false; // Loop through cart items and checking for the specific defined shipping class foreach( $package['contents'] as $cart_item ) { if( $cart_item['data']->get_shipping_class() == $shipping_class ) $is_found = true; } // Set shipping costs to 50% if shipping class is found if( $is_found ){ foreach ( $rates as $rate_key => $rate ){ $has_taxes = false; // Targeting "flat rate" if( 'flat_rate' === $rate->method_id ){ $rates[$rate_key]->cost = $rate->cost * $discount_rate; // Taxes rate cost (if enabled) foreach ($rates[$rate_key]->taxes as $key => $tax){ if( $tax > 0 ){ $has_taxes = true; $taxes[$key] = $tax * $discount_rate; } } if( $has_taxes ) $rates[$rate_key]->taxes = $taxes; } } } return $rates; }
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Don’t forget to disable “debug mode” in shipping settings once this has been tested once.