phpwordpresswoocommercehook-woocommerceshipping-method

Set custom shipping rates programmatically in WooCommerce 3


I have searched and found a number of examples of how to change the shipping rates. Basically I am looking to do the same, but I want to use a 3rd party API.

I have set up a custom plugin with a functions.php and activated it. I think used something simple like this:

add_filter('woocommerce_package_rates','test_overwrite',10,2);
function test_overwrite($rates,$package) {

    echo "<h2>Can you see me</h2>";
    foreach ($rates as $rate) {
        //Set the price
        $rate->cost = 1000;
        //Set the TAX
        $rate->taxes[1] = 1000 * 0.2;
    }
    return $rates;
}

However when I run either the checkout, or basket, the filter does not seem to run because I cannot see the echo. I also tried print_r().

Am I missing something as to why I cannot run this filter ?


Solution

  • As this is a filter and as the data is cached, you can't get any output with print_r().

    The correct way to make it work is the following:

    add_filter( 'woocommerce_package_rates', 'custom_shipping_costs', 20, 2 );
    function custom_shipping_costs( $rates, $package ) {
        // New shipping cost (can be calculated)
        $new_cost = 1000;
        
        foreach( $rates as $rate_key => $rate ){
            // Excluding free shipping methods
            if( $rate->method_id !== 'free_shipping'){
                // Original rate cost
                $base_cost = $rate->cost; 
    
                // Set rate cost
                $rates[$rate_key]->cost = $new_cost;
    
                // Set taxes rate cost (if enabled)
                $taxes = array();
                $has_taxes = false;
    
                // Loop through taxes
                foreach ($rate->taxes as $key => $tax){
                    if( $tax > 0 ) {
                        $conv_rate   = $tax / $base_cost; 
                        $taxes[$key] = $new_cost * $conv_rate; // Set tax rate cost
                        $has_taxes = true;
                    }
                }
                if ( $has_taxes ) {
                    $rates[$rate_key]->taxes = $taxes;
                }
            }
        }
        return $rates;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.

    You may need to refresh shipping methods cache by emptying the cart.


    Targetting shipping method(s) rate ID(s)

    To Target a shipping rate ID like for example flat_rate:12 simply use the $rate_key argument, replacing:

    // Excluding free shipping methods
    if( $rate->method_id !== 'free_shipping'){
    

    with

    // Targetting specifically a shipping method rate ID
    if( $rate_key === 'flat_rate:12'){
    

    or the rate id property (when using some 3rd party plugins):

    // Targetting specifically a shipping method rate ID
    if( $rate->id === 'flat_rate:12'){
    

    or for multiple shipping rate IDs replace with (for example):

    // Targetting specifically multiple shipping method rate IDs
    if( in_array( $rate->id, array('flat_rate:12', 'flat_rate:15') ){
    

    How to get the correct shipping rate(s) ID(s)

    The following function will display, near the footer, the available shipping rates IDs, that you can use:

    add_action('wp_footer', 'display_shipping_methods_rate_ids');
    function display_shipping_methods_rate_ids() {
        echo '<pre><h4>Available Shipping Methods Rates</h4>
        <table><thead><tr><th>Shipping method</th><th>Rate ID</th></tr></thead><tbody>';
    
        foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
            $data = WC()->session->get( "shipping_for_package_{$package_key}" );
            foreach ( $data['rates'] as $rate ) {
                echo '<tr><td>'.$rate->label.'</td><td>'.$rate->id.'</td></tr>';
            }
        }
        echo '</tbody></table></pre>';
    }
    

    Once you get the correct shipping rate ID to be used in the previous code, you can remove this code snippet.