1

I am using the following code to add custom fee on checkout:

function woocommerce_custom_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
    return;

if ($_REQUEST['s-baby-seats'] || $_REQUEST['s-taxi-return-id']) {
    global $c_seats;
    global $c_return_fare;
    $baby_seats_fee = intval($c_seats[1]);
    if ($_REQUEST['s-taxi-return-id']) {
        $return_fee = intval($c_return_fare);
    } else {
        $return_fee = 0;
    }
    $surcharge = $baby_seats_fee + $return_fee;
    $surcharge_label = esc_html__('Extra + Return', 'berrytaxiplon');
    $woocommerce->cart->add_fee( $surcharge_label, $surcharge );
}
} 
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );

The fee is added as expected but the order_review section of checkout stays disabled with blockUI. I can't see any php ('WP_DEBUG' is true ) or js console errors. I don't know how to debug this behaviour.

If instead of my code just add $woocommerce->cart->add_fee( 'test', 5 ); the order review is not blocked/disabled and the user can place order normally.

Any ideas what in my code may cause this and how to solve the issue? Thanks!

Edit 1:

I changed my function and removed the conditional and the $_requests to this:

function woocommerce_custom_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
    return;

    global $c_seats;
    global $c_return_fare;
    $baby_seats_fee = intval($c_seats[1]);
    $return_fee = intval($c_return_fare);
    $surcharge = $baby_seats_fee + $return_fee;
    $surcharge_label = esc_html__('Extra + Return', 'berrytaxiplon');
    $woocommerce->cart->add_fee( $surcharge_label, $surcharge );
}
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );

Now the blockUI is removed within seconds but the fee, while it renders correct at first, it is then turned to 0 by js.

Edit 2:

Turns out I had to use sessions all along. Solved thanks to this post: Add a cart fee from an url variable in Woocommerce

0

You can not keep posted values directly in your hooked function as it's not stored anywhere, and you loose them when customer leaves cart page. So blockUI has nothing to do with it.

There is 2 ways to keep (store) that posted values:

  1. On Woocommerce sessions if that custom data is posted outside Woocommerce single product pages.
  2. On add to cart event, if that custom values are posted when customer clicks add to cart (in Single product pages).

Also you code is a bit outdated as $global woocommerce is not anymore needed and replaced by WC(). Now on woocommerce_cart_calculate_fees hooked function, there is a missing argument in your code which is the variable $cart (the WC_Cart Object).

Your code is not really testable as we don't know what are:

global $c_seats;
global $c_return_fare;

You can try one of this 2 ways:

1) The data is posted outside Woocommerce single product pages:

// Add custom cart item data on add to cart
add_filter( 'init', 'set_custom_data_requested_to_wc_sessions', 10, 3 );
function set_custom_data_requested_to_wc_sessions() {

    if( isset($_REQUEST['s-baby-seats']) || isset($_REQUEST['s-taxi-return-id']) ) {
        // Enable Woocommerce sessions (if not done yet)
        if ( ! WC()->session->has_session() ) {
            WC()->session->set_customer_session_cookie( true );
        }

        $session_data = []; // initializing

        if( isset($_REQUEST['s-baby-seats']) && ! empty($_REQUEST['s-baby-seats']) ) {
            // Add the dropdown value as custom cart item data
            $session_data['baby_seats'] = wc_clean( esc_attr($_REQUEST['s-baby-seats']) );
        }

        if( isset($_REQUEST['s-taxi-return-id']) && ! empty($_REQUEST['s-taxi-return-id']) ) {
            // Add the dropdown value as custom cart item data
            $session_data['return_id'] = wc_clean( esc_attr($_REQUEST['s-taxi-return-id']) );
        }

        // Set the data to custom wc_sessions
        if( sizeof($session_data) > 0 ) {
            WC()->session->set('fee_data', $session_data);
        }
    }
}

// Add a fee
add_action( 'woocommerce_cart_calculate_fees','add_custom_surcharge', 10, 1 );
function add_custom_surcharge( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    global $c_seats, $c_return_fare;

    $surcharge = 0; // Initializing
    $fee_data  = WC()->session->get('fee_data'); // Get the data from Woocommerce session

    if( isset($fee_data['baby_seats']) || isset($fee_data['return_id']) ) {
        $baby_seats_fee  = isset($fee_data['baby_seats']) ? intval($c_seats[1]) : 0;
        $return_id_fee =  isset($fee_data['return_id']) && $fee_data['return_id'] ? intval($c_return_fare) : 0;

        $surcharge = $baby_seats_fee + $return_id_fee; // Add to the fee cost
    }

    // Add the calculated fee
    if ( $surcharge > 0 ) {
        $cart->add_fee( esc_html__('Extra + Return', 'woocommerce'), $surcharge );
    }
}

Code goes in function.php file of your active child theme (or active theme). It should works.


2) Data posted on add to cart in single product pages (cart item based):

// Add custom cart item data on add to cart
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data_callback', 10, 3 );
function filter_add_cart_item_data_callback( $cart_item_data, $product_id, $variation_id) {
    if( isset($_REQUEST['s-baby-seats']) && ! empty($_REQUEST['s-baby-seats']) ) {
        // Add the dropdown value as custom cart item data
        $cart_item_data['s-baby-seats'] = wc_clean( esc_attr($_REQUEST['s-baby-seats']) );
        $unique_key = true;
    }

    if( isset($_REQUEST['s-taxi-return-id']) && ! empty($_REQUEST['s-taxi-return-id']) ) {
        // Add the dropdown value as custom cart item data
        $cart_item_data['s-taxi-rid'] = wc_clean( esc_attr($_REQUEST['s-taxi-return-id']) );
        $unique_key = true;
    }

    if( isset($unique_key) && $unique_key )
        $cart_item_data['unique-key'] = md5(microtime().rand()); // Make each item unique

    return $cart_item_data;
}

// Add a fee
add_action( 'woocommerce_cart_calculate_fees','add_custom_surcharge', 10, 1 );
function add_custom_surcharge( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    global $c_seats, $c_return_fare;

    $surcharge = 0; // Initializing

    // Loop through cart items
    foreach( $cart->get_cart() as $cart_item ) {
        if( isset($cart_item['s-baby-seats']) || isset($cart_item['s-taxi-rid']) ) {
            $baby_seats_fee  = isset($cart_item['s-baby-seats']) ? intval($c_seats[1]) : 0;
            $taxi_return_fee =  isset($cart_item['s-taxi-rid']) && $cart_item['s-taxi-rid'] ? intval($c_return_fare) : 0;

            $surcharge += $baby_seats_fee + $return_fee; // Add to the fee cost
        }
    }

    // Add the calculated fee
    if ( $surcharge > 0 ) {
        $cart->add_fee( esc_html__('Extra + Return', 'woocommerce'), $surcharge );
    }
}

Code goes in function.php file of your active child theme (or active theme). It could works.


Related answer on SO: Add a cart fee from an url variable in Woocommerce

  • Thanks for the answer. The related answer you linked pointed me to sessions and solved my issue. Yet I should try the second option since I have already added these requests on cart_item_data. – thepi Apr 15 '19 at 13:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.