Search code examples
phpwordpresswoocommercehook-woocommerceshipping-method

Change WooCommerce specific shipping method cost based on cart subtotal


I'm managing a site that is WP with Woocommerce. During checkout, there is a 3-Day-Air shipping method option, which, right now is only shown for customers residing in 2 specific US states. The shipping method is a live rate from UPS and pulled in via the UPS API. (The API is handled via Hive UPS Shipping & Label plugin).

Currently, I have one filter working that unsets all other shipping methods if the user's $shipping_state is in the 2-state array in the filter. Another filter shows all shipping options, except the 3-Day_Air option, IF the state address is not in the array of the 2 states.

Then this filter in the snippet below is to change the incoming live-rate price for 3-Day-Air to $69.95 for shipping cost.

My question: is there a way to subtract $50 from the rate set in the snippet if the cart subtotal is over $200? (or reset the rate $19.95 if the >200 condition is met?)

This post answer is close

This is another workaround but it would have to only work for the condition of shipping_address is one of the 2 states.

Any help would be greatly appreciated. I'm picking up bits and pieces of PHP, but it gets murky pretty quickly. Thanks in advance.

add_filter( 'woocommerce_package_rates', function( $shipping_costs) {
    
    $shipping_method_min_cost = array(
        'wf_shipping_ups:12'    =>  69.95,      // Shipping id  => min_cost
        
    );

    foreach( $shipping_costs as $shipping_cost ) {
        $shipping_method_id = $shipping_cost->get_id();
        if( isset($shipping_method_min_cost[$shipping_method_id]) ) {
            $cost = (float) $shipping_cost->get_cost();
            if( $cost < $shipping_method_min_cost[$shipping_method_id] ) {
                $shipping_cost->set_cost($shipping_method_min_cost[$shipping_method_id]);
            }
        }
    }
    return $shipping_costs;
});


Solution

  • To change "the incoming live-rate price for 3-Day-Air to $69.95 for shipping cost", you simply need to use one of the following ways inside your function:

    1. Cart subtotal excluding taxes
        $shipping_method_min_cost = array(
            'wf_shipping_ups:12' => WC()->cart->subtotal >= 200 ? 69.95 : 19.95,
        );
    
    1. Cart subtotal including taxes:
        $shipping_method_min_cost = array(
            'wf_shipping_ups:12' => WC()->cart->get_subtotal() >= 200 ? 69.95 : 19.95,
        );
    

    Both ways should work.


    You could also use the shipping package displayed cart subtotal (handle tax calculations).

    Below is a complete-revised code version, that handle shipping taxes (if enabled), using the shipping package displayed cart subtotal:

    add_filter( 'woocommerce_package_rates', 'filter_woocommerce_package_rates', 10, 2 );
    function  filter_woocommerce_package_rates( $rates, $package ) {  
        $targeted_method = 'wf_shipping_ups:12'; // Targeted shipping method rate ID
        $cart_subtotal   = $package['cart_subtotal']; // get displayed cart subtotal
        $new_cost        = $cart_subtotal >= 200 ? 69.95 : 19.95; // Cost calculation
    
        // Loop through shipping rates for the current shipping package
        foreach( $rates as $rate_key => $rate ) {
            $base_cost = $rate->cost;
            if( $rate_key === $targeted_method && $base_cost < $new_cost ) {
                $rates[$rate_key]->cost = $new_cost; // set the new cost
    
                $has_taxes = false; // Initializing
                $taxes     = array(); // Initializing
    
                // Loop through taxes array (change taxes rate cost if enabled)
                foreach ($rate->taxes as $key => $tax){
                    if( $tax > 0 ){
                        // Get the tax rate conversion
                        $tax_rate    = $tax / $base_cost;
    
                        // Set the new tax cost in the array
                        $taxes[$key] = $new_cost * $tax_rate;
                        $has_taxes   = true; // Enabling tax changes
                    }
                }
                // set array of shipping tax cost
                if( $has_taxes ) {
                    $rates[$rate_key]->taxes = $taxes;
                }
                break;
            }
        }
        return $rates;
    }
    

    It should work too.


    To refresh shipping cached data, simply empty the cart.