phpjqueryajaxwoocommercesession-variables

Add fees based on custom selected options in WooCommerce Cart page


I've added some checkboxes to my cart page which give the customers the opportunity to add extra items to their order.

This is based on Custom checkbox that adds a fee in WooCommerce cart page answer code.

The last checkbox doubles needs to double the price of the product (which it's doing) but also the Stall Added price needs to double (become £20).

Cart page with relevant boxes checked:

enter image description here

/*------------------------------------*\
    Add to cart page 
\*------------------------------------*/


add_action( 'woocommerce_before_cart_totals', 'add_extras_title', 20 );

function add_extras_title(){
    
    if( current_user_can( 'stallholder') ) {

        echo '<table><tr class="installment-section">
        <h3>'.__("Add Extras").'</h3></tr></table>';
               
    } else {
        // Do Nothing
    }
    
}


/* Add Stall */

// Display the checkout field in cart page totals section
add_action( 'woocommerce_before_cart_totals', 'display_priority_fee_checkbox_field', 20 );

function display_priority_fee_checkbox_field(){
    
    if( current_user_can( 'stallholder') ) {

        echo '<table cellspacing="0" class="shop_table shop_table_responsive"><tr class="installment-section">
        <th>'.__("Add Stall").'</th><td>';

        woocommerce_form_field( 'priority_fee', array(
            'type'          => 'checkbox',
            'class'         => array('form-row-wide'),
            'label'         => __(' £10.00'),
        ), WC()->session->get('priority_fee') ? '1' : '' );

        echo '</td></tr>';
               
    } else {
        // Do Nothing
    }
    
}

// Remove "(optional)" text from the field
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_priority_fee_checkbox', 10, 4 );
function remove_optional_txt_from_priority_fee_checkbox( $field, $key, $args, $value ) {
    // Only on checkout page for Order notes field
    if( 'priority_fee' === $key ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    return $field;
}

// jQuery :: Ajax script
add_action( 'wp_footer', 'priority_fee_js_script' );
function priority_fee_js_script() {
    // On Order received page, remove the wc session variable if it exist
    if ( is_wc_endpoint_url('order-received')
        && WC()->session->__isset('priority_fee') ) :

        WC()->session->__unset('priority_fee');

    // On Cart page: jQuert script
    elseif ( is_cart() ) :

    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof woocommerce_params === 'undefined')
            return false;

        var c = 'input[name=priority_fee]';

        $(document.body).on( 'click change', c, function(){
            console.log('click');
            var fee = $(c).is(':checked') ? '1' : '';

            $.ajax({
                type: 'POST',
                url: woocommerce_params.ajax_url,
                data: {
                    'action': 'priority_fee',
                    'priority_fee': fee,
                },
                success: function (response) {
                    setTimeout(function(){
                        $(document.body).trigger('added_to_cart');
                    }, 500);
                },
            });
        });
    });
    </script>
    <?php
    endif;
}

// Get Ajax request and saving to WC session
add_action( 'wp_ajax_priority_fee', 'priority_fee_ajax_receiver' );
add_action( 'wp_ajax_nopriv_priority_fee', 'priority_fee_ajax_receiver' );
function priority_fee_ajax_receiver() {
    if ( isset($_POST['priority_fee']) ) {
        $priority_fee = $_POST['priority_fee'] ? true : false;
        // Set to a WC Session variable
        WC()->session->set('priority_fee', $priority_fee );

        echo $priority_fee ? '1' : '0';
        die();
    }
}

// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_priority_fee' );
function set_priority_fee( $cart ){
    if ( is_admin() && ! defined('DOING_AJAX') )
        return;
            
        if ( WC()->session->get('priority_fee') && isset($_GET['double_pitch']) && $_GET['double_pitch'] == "1")  {
            $stall  = $cart->get_cart_contents_count();
            $fee_label   = sprintf( __( "Stall Added" ) );
            $fee_amount  = 20 * $item_count;
            $cart->add_fee( $fee_label, $fee_amount, true );
        }
        
        if ( WC()->session->get('priority_fee') ) {
        $item_count  = $cart->get_cart_contents_count();
        $fee_label   = sprintf( __( "Stall Added" ) );
        $fee_amount  = 10 * $item_count;
        $cart->add_fee( $fee_label, $fee_amount, true );
        
    
    }

}


/* Add Power */

// Display the checkout field in cart page totals section
add_action( 'woocommerce_before_cart_totals', 'display_power_checkbox_field', 20 );
function display_power_checkbox_field(){
    
    if( current_user_can( 'stallholder') && current_user_can('hot_food')  ) {

        echo '<tr class="installment-section">
            <th>'.__("Add Power").'</th><td>';

            woocommerce_form_field( 'power_16', array(
                'type'          => 'checkbox',
                'class'         => array('form-row-wide'),
                'label'         => __(' £10.00 (16v Supply)'),
            ), WC()->session->get('power_16') ? '1' : '' );
                
            woocommerce_form_field( 'power_32', array(
                'type'          => 'checkbox',
                'class'         => array('form-row-wide'),
                'label'         => __(' £20.00 (32v Supply)'),
            ), WC()->session->get('power_32') ? '1' : '' );
            
        echo '</td></tr>';
               
    }
   
    
    else {
        // Do Nothing
    }
    
}


// Remove "(optional)" text from the field
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_power_checkbox', 10, 4 );
function remove_optional_txt_from_power_checkbox( $field, $key, $args, $value ) {
    // Only on checkout page for Order notes field
    if( 'power_16' === $key ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    if( 'power_32' === $key ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    return $field;
}




// jQuery :: Ajax script
add_action( 'wp_footer', 'power_js_script' );
function power_js_script() {
    // On Order received page, remove the wc session variable if it exist
    if ( is_wc_endpoint_url('order-received')
        && WC()->session->__isset('power_16') ) :

        WC()->session->__unset('power_16');
    
    elseif ( is_wc_endpoint_url('order-received')
        && WC()->session->__isset('power_32') ) :

        WC()->session->__unset('power_32');

    // On Cart page: jQuert script
    elseif ( is_cart() ) :

    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof woocommerce_params === 'undefined')
            return false;

        var c = 'input[name=power_16]';

        $(document.body).on( 'click change', c, function(){
            console.log('click');
            var fee = $(c).is(':checked') ? '1' : '';

            $.ajax({
                type: 'POST',
                url: woocommerce_params.ajax_url,
                data: {
                    'action': 'power_16',
                    'power_16': fee,
                },
                success: function (response) {
                    setTimeout(function(){
                        $(document.body).trigger('added_to_cart');
                    }, 500);
                },
            });
        });
    });
    </script>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof woocommerce_params === 'undefined')
            return false;

        var c = 'input[name=power_32]';

        $(document.body).on( 'click change', c, function(){
            console.log('click');
            var fee = $(c).is(':checked') ? '1' : '';

            $.ajax({
                type: 'POST',
                url: woocommerce_params.ajax_url,
                data: {
                    'action': 'power_32',
                    'power_32': fee,
                },
                success: function (response) {
                    setTimeout(function(){
                        $(document.body).trigger('added_to_cart');
                    }, 500);
                },
            });
        });
    });
    </script>
    <?php
    endif;
}

// Get Ajax request and saving to WC session
add_action( 'wp_ajax_power_16', 'power_16_ajax_receiver' );
add_action( 'wp_ajax_nopriv_power_16', 'power_16_ajax_receiver' );
function power_16_ajax_receiver() {
    if ( isset($_POST['power_16']) ) {
        $power_16 = $_POST['power_16'] ? true : false;
        // Set to a WC Session variable
        WC()->session->set('power_16', $power_16 );

        echo $power_16 ? '1' : '0';
        die();
    }
}

add_action( 'wp_ajax_power_32', 'power_32_ajax_receiver' );
add_action( 'wp_ajax_nopriv_power_32', 'power_32_ajax_receiver' );
function power_32_ajax_receiver() {
    if ( isset($_POST['power_32']) ) {
        $power_32 = $_POST['power_32'] ? true : false;
        // Set to a WC Session variable
        WC()->session->set('power_32', $power_32 );

        echo $power_32 ? '1' : '0';
        die();
    }
}

// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_power' );
function set_power( $cart ){
    if ( is_admin() && ! defined('DOING_AJAX') )
        return;

    if ( WC()->session->get('power_16') ) {
        $item_count  = $cart->get_cart_contents_count();
        $fee_label   = sprintf( __( "16v Supply Added" ) );
        $fee_amount  = 10 * $item_count;
        $cart->add_fee( $fee_label, $fee_amount, true );
    }
    if ( WC()->session->get('power_32') ) {
        $item_count  = $cart->get_cart_contents_count();
        $fee_label   = sprintf( __( "32v Supply Added" ) );
        $fee_amount  = 20 * $item_count;
        $cart->add_fee( $fee_label, $fee_amount, true );
    }
}


/* Double Pitch*/

// Display the checkout field in cart page totals section

add_action( 'woocommerce_before_cart_totals', 'display_double_pitch_checkbox_field', 20 );
function display_double_pitch_checkbox_field(){
    
    if( current_user_can( 'stallholder') ) {

echo '<tr class="installment-section">
    <th>'.__("Double Pitch").'</th><td>';

    woocommerce_form_field( 'double_pitch', array(
        'type'          => 'checkbox',
        'class'         => array('form-row-wide'),
        'label'         => __(' x2'),
    ), WC()->session->get('double_pitch') ? '1' : '' );

    echo '</td></tr></table>';
               
    } else {
        // Do Nothing
    }
    
}



// Remove "(optional)" text from the field
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_double_pitch_checkbox', 10, 4 );
function remove_optional_txt_from_double_pitch_checkbox( $field, $key, $args, $value ) {
    // Only on checkout page for Order notes field
    if( 'double_pitch' === $key ) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
        $field = str_replace( $optional, '', $field );
    }
    return $field;
}

// jQuery :: Ajax script
add_action( 'wp_footer', 'double_pitch_js_script' );
function double_pitch_js_script() {
    // On Order received page, remove the wc session variable if it exist
    if ( is_wc_endpoint_url('order-received')
        && WC()->session->__isset('double_pitch') ) :

        WC()->session->__unset('double_pitch');

    // On Cart page: jQuert script
    elseif ( is_cart() ) :

    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof woocommerce_params === 'undefined')
            return false;

        var c = 'input[name=double_pitch]';

        $(document.body).on( 'click change', c, function(){
            console.log('click');
            var fee = $(c).is(':checked') ? '1' : '';

            $.ajax({
                type: 'POST',
                url: woocommerce_params.ajax_url,
                data: {
                    'action': 'double_pitch',
                    'double_pitch': fee,
                },
                success: function (response) {
                    setTimeout(function(){
                        $(document.body).trigger('added_to_cart');
                    }, 500);
                },
            });
        });
    });
    </script>
    <?php
    endif;
}

// Get Ajax request and saving to WC session
add_action( 'wp_ajax_double_pitch', 'double_pitch_ajax_receiver' );
add_action( 'wp_ajax_nopriv_double_pitch', 'double_pitch_ajax_receiver' );
function double_pitch_ajax_receiver() {
    if ( isset($_POST['double_pitch']) ) {
        $double_pitch = $_POST['double_pitch'] ? true : false;
        // Set to a WC Session variable
        WC()->session->set('double_pitch', $double_pitch );

        echo $double_pitch ? '1' : '0';
        die();
    }
}

// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_double_pitch' );
function set_double_pitch( $cart ){
    if ( is_admin() && ! defined('DOING_AJAX') )
        return;

  if ( WC()->session->get('double_pitch') ) {
        $item_count  = WC()->cart->cart_contents_total;
        $fee_label   = __( "Double Pitch" ) ;
        $fee_amount  = 1 * $item_count;
        $cart->add_fee( $fee_label, $fee_amount, true );
    }

}

I've tried isset in many different ways but can not figure it out.

What I need to happen is for the Stall added to x2 (£20) when 'Double Pitch' is checked and return to £10 if unchecked.

Thanks

enter image description here


Solution

  • Update: Allow swapping "Power" checkboxes, avoiding getting both checkboxes selected…

    I have completely revised, optimized and compacted your code, allowing "Double Pitch" option to double "Stall" fee amount when selected.

    // Add custom input checkbox fields in cart page
    add_action( 'woocommerce_before_cart_totals', 'display_custom_fields_before_cart_totals', 20 );
    function display_custom_fields_before_cart_totals(){
        if( current_user_can( 'stallholder') ) {
            echo '<h3>'.__("Add Extras").'</h3>
            <table cellspacing="0" class="shop_table shop_table_responsive add-extras">';
            
            // 1) Add Stall
            echo '<tr class="stall-section">
            <th>'.__("Add Stall").'</th>
            <td>';
    
            woocommerce_form_field( 'stall', array(
                'type'          => 'checkbox',
                'class'         => array('form-row-wide'),
                'label'         => __(' £10.00'),
            ), WC()->session->get('stall') );
    
            echo '</td></tr>';
    
            // 2) Add Power
            if( current_user_can('hot_food') ) {
                echo '<tr class="power-section">
                <th>'.__("Add Power").'</th>
                <td>';
    
                woocommerce_form_field( 'power_16', array(
                    'type'          => 'checkbox',
                    'class'         => array('form-row-wide'),
                    'label'         => __(' £10.00 (16v Supply)'),
                ), WC()->session->get('power_16') );
                    
                woocommerce_form_field( 'power_32', array(
                    'type'          => 'checkbox',
                    'class'         => array('form-row-wide'),
                    'label'         => __(' £20.00 (32v Supply)'),
                ), WC()->session->get('power_32') );
                
                echo '</td></tr>';
            }
    
            // 3) Add Double Pitch
            echo '<tr class="2x-pitch-section">
            <th>'.__("Double Pitch").'</th><td>';
        
            woocommerce_form_field( '2x_pitch', array(
                'type'          => 'checkbox',
                'class'         => array('form-row-wide'),
                'label'         => __(' x2'),
            ), WC()->session->get('2x_pitch') );
        
            echo '</td></tr></table>';
        } 
    }
    
    // Remove "(optional)" text from custom fields
    add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_custom_fields', 10, 4 );
    function remove_optional_txt_from_custom_fields( $field, $key, $args, $value ) {
        if( ! is_cart() ) return $field;
    
        // Here below, define your custom field keys
        $fields   = array('stall', 'power_16', 'power_32', '2x_pitch');
    
        if( in_array($key, $fields) ) {
            $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
            $field    = str_replace( $optional, '', $field );
        } 
        return $field;
    }
    
    // jQuery :: Ajax script
    add_action( 'wp_footer', 'add_cart_extras_js' );
    function add_cart_extras_js() {
        // On Order received page, remove custom wc session variables if they exist
        if ( is_wc_endpoint_url('order-received') ) {
            foreach ( array('stall', 'power_16', 'power_32', '2x_pitch') as $key ) {
                if ( WC()->session->__isset($key) ) {
                    WC()->session->__unset($key);
                }
            }
        // On Cart page: jQuery script
        } elseif ( is_cart() ) {
        ?>
        <script type="text/javascript">
        jQuery( function($){
            if (typeof woocommerce_params === 'undefined')
                return false;
    
            const fields = 'input[name=stall],input[name=power_16],input[name=power_32],input[name=2x_pitch]';
    
            $(document.body).on( 'change', fields, function(){
                const fieldKey = $(this).prop('id'),
                      checked  = $(this).prop('checked') ? '1' : '0';
    
                if ( fieldKey === 'power_16' && $(this).prop('checked') && $('input[name=power_32]').prop('checked') ) {
                    $('input[name=power_32]').prop('checked', false);
                } else if ( fieldKey === 'power_32' && $(this).prop('checked') && $('input[name=power_16]').prop('checked') ) {
                    $('input[name=power_16]').prop('checked', false);
                }
    
                $.ajax({
                    type: 'POST',
                    url: woocommerce_params.ajax_url,
                    data: {
                        'action':      'setting_up_extras',
                        'field_key':   fieldKey,
                        'field_value': checked,
                    },
                    success: function (response) {
                        $(document.body).trigger('added_to_cart');
                        console.log(response); // For testing (to be removed)
                    },
                });
            });
        });
        </script>
        <?php
        }
    }
    
    // Get Ajax request and saving selected options to WC session variables
    add_action( 'wp_ajax_setting_up_extras', 'setting_up_selected_extras_ajax_receiver' );
    add_action( 'wp_ajax_nopriv_setting_up_extras', 'setting_up_selected_extras_ajax_receiver' );
    function setting_up_selected_extras_ajax_receiver() {
        if ( isset($_POST['field_key']) && isset($_POST['field_value']) ) {
            $key   = esc_attr($_POST['field_key']);
            $value = boolval($_POST['field_value']);
    
            WC()->session->set($key, $value);
    
            if ( $key === 'power_16' && $value && WC()->session->get('power_32') ) {
                WC()->session->set('power_32', false);
            } elseif ( $key === 'power_32' && $value && WC()->session->get('power_16') ) {
                WC()->session->set('power_16', false);
            }
            wp_die(json_encode([$key => $value]));
        } else {
            wp_die('Something went wrong');
        }
    }
    
    // Add a custom calculated fee conditionally
    add_action( 'woocommerce_cart_calculate_fees', 'add_selected_extras_fees' );
    function add_selected_extras_fees( $cart ){
        if ( is_admin() && ! defined('DOING_AJAX') )
            return;
    
        $item_count  = $cart->get_cart_contents_count();
                
        if ( WC()->session->get('stall') )  {
            $fee_label   = __( "Stall Added", "woocommerce" );
            $fee_amount  = 10 * $item_count;
            $fee_amount  = WC()->session->get('2x_pitch') ? $fee_amount * 2 : $fee_amount;
            $cart->add_fee( $fee_label, $fee_amount, true );
        }
    
        if ( WC()->session->get('power_16') ) {
            $fee_label   = __( "16v Supply Added", "woocommerce" );
            $fee_amount  = 10 * $item_count;
            $cart->add_fee( $fee_label, $fee_amount, true );
        }
    
        if ( WC()->session->get('power_32') ) {
            $fee_label   = __( "32v Supply Added", "woocommerce" );
            $fee_amount  = 20 * $item_count;
            $cart->add_fee( $fee_label, $fee_amount, true );
        }
    
        if ( WC()->session->get('2x_pitch') ) {
            $fee_label   = __( "Double Pitch", "woocommerce" ) ;
            $fee_amount  = WC()->cart->get_cart_contents_total();
            $cart->add_fee( $fee_label, $fee_amount, true );
        }
    }
    

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