skip to Main Content

Is there any way to remove a fee from an Woocommerce order before saving it to the database?

I have tried the following hooks, to no success

  1. woocommerce_before_save_order_items
  2. woocommerce_calculate_totals
  3. wp_insert_post_data

I also tried to edit the fee total as below, but the fee still gets saved to the database

add_action( 'woocommerce_review_order_before_payment', 'cst_my_hook_1', 10, 3);
function cst_my_hook_1() {
    WC()->cart->set_fee_total(0);
}

I am sharing a screenshot to make my requirements more clear. Woocommerce cart class (class-wc-cart.php) contains a public function to add fees, so I think there should be ways to remove it too.

I used the hook "woocommerce_cart_calculate_fees" to add the fee shown in the screenshot. Now I want to remove it before saving to DB.

I am using WordPress 5.7.1, Woocommerce 5.2.1

enter image description here

2

Answers


  1. To disable fees from order once checking out, use this simple following hooked function, that will clean all fees from orders and email notifications:

    add_action( 'woocommerce_checkout_order_created', 'order_created_disable_fees' );
    function order_created_disable_fees( $order ) {
        $targeted_item_name = __( "Total Tax Payment", "woocommerce" );
    
        foreach( $order->get_items( 'fee' ) as $item_id => $item ) {
            if( $targeted_item_name === $item['name'] ) {
                $order->remove_item($item_id);
            }       
        }
        $order->calculate_totals();
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.


    Now if you want to remove the fees, but keep original total order amount, use the following:

    add_action( 'woocommerce_checkout_order_created', 'order_created_disable_fees' );
    function order_created_disable_fees( $order ) {
        $targeted_item_name = __( "Total Tax Payment", "woocommerce" );
    
        foreach( $order->get_items( 'fee' ) as $item_id => $item ) {
            if( $targeted_item_name === $item['name'] ) {
                $order->remove_item($item_id);
            }
        }
        $order->save();
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.

    Login or Signup to reply.
  2. If you want to remove a fee from an order before saving it in the database you can use the woocommerce_create_order hook that fires before the order is created within the create_order method of the WC_Checkout class.

    Based on this answer:

    you will be able to remove the fee from the cart.

    However, you will also have to recalculate the totals and taxes (it works whether the fee is taxable or not, and even with multiple tax classes).

    REMOVE A FEE FROM CART AND RECALCULATE TOTALS

    // removes a specific fee by name before creating the order and recalculates the totals
    add_filter( 'woocommerce_create_order', 'remove_specific_fee_from_cart_before_creating_order', 10, 2 );
    function remove_specific_fee_from_cart_before_creating_order( $order_id = null, $order ) {
    
        // get the fees added to the cart
        $fees = WC()->cart->get_fees();
    
        // initialize taxes (if the fee is not taxable)
        $fee_tax = 0;
        $fee_tax_data = array();
    
        foreach ( $fees as $key => $fee ) {
            // replace "Total Tax Payment" with the name of the fee you added to the cart
            if ( $fee->name == 'Total Tax Payment' ) {
                // gets the data to recalculate the cart total
                $fee_amount = $fee->amount;
                if ( $fee->taxable ) {
                    $fee_tax      = $fee->tax;
                    $fee_tax_data = $fee->tax_data;
                }
                // removes the fee
                unset( $fees[$key] );
                break;
            }
        }
    
        // updates the cart fees
        WC()->cart->fees_api()->set_fees( $fees );
    
        // gets the current values of the cart to be recalculated
        $cart_total     = WC()->cart->get_total(''); // returns the float value instead of HTML code
        $cart_total_tax = WC()->cart->get_total_tax();
        $cart_fee_taxes = WC()->cart->get_fee_taxes();
    
        // if the fee is taxable
        // recalculates the taxes by removing the taxes of the removed fee
        if ( ! empty( $fee_tax_data ) ) {
            foreach ( $cart_fee_taxes as $fee_tax_key => $fee_tax ) {
                if ( array_key_exists( $fee_tax_key, $fee_tax_data ) ) {
                    $cart_fee_taxes[$fee_tax_key] = $fee_tax - $fee_tax_data[$fee_tax_key];
                }
            }
        }
    
        // updates the cart totals
        WC()->cart->set_total( $cart_total - $fee_amount - $fee_tax );
        WC()->cart->set_total_tax( $cart_total_tax - $fee_tax );
        WC()->cart->set_fee_taxes( $cart_fee_taxes );
    
        return $order_id;
    }
    

    REMOVES A FEE FROM CART WITHOUT RECALCULATING THE TOTALS

    // removes a specific fee by name before creating the order
    add_filter( 'woocommerce_create_order', 'remove_specific_fee_from_cart_before_creating_order', 10, 2 );
    function remove_specific_fee_from_cart_before_creating_order( $order_id = null, $order ) {
    
        // get the fees added to the cart
        $fees = WC()->cart->get_fees();
    
        foreach ( $fees as $key => $fee ) {
            // replace "Total Tax Payment" with the name of the fee you added to the cart
            if ( $fee->name == 'Total Tax Payment' ) {
                // removes the fee
                unset( $fees[$key] );
                break;
            }
        }
    
        // updates the cart fees
        WC()->cart->fees_api()->set_fees( $fees );
    
        return $order_id;
    }
    

    The code has been tested and works. Add it to your active theme’s functions.php.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search