Question

Clear WooCommerce Custom Fees on shipping method change

I'm implementing some additional fields and fees on the Woocommerce Checkout Page depending on the chosen shipping method.

I'm stuck when I try to clear all fees when user changes the chosen shipping method.

My extra fees are associated with some WC Session variables I've created and I thought if I unset them on change of shipping method for radios that this would remove them from the order details but it only SOMETIMES removes my fees, so it's inconstant for some reason. Hoping someone out there can identify my error(s). Maybe I'm not clearing these fees (sessions variables) in the right spot.

Note that the code below is in a WP custom plugin that I've created.

global $dr_pr_fee;
global $dr_ad_fee;
$dr_pr_fee = 60;
$dr_ad_fee = 46.87;

global $fedex_npd_fee;
global $fedex_rd_fee;
global $fedex_lad_fee;
global $fedex_lg_fee;
$fedex_npd_fee = 61;
$fedex_rd_fee = 191;
$fedex_lad_fee = 85;
$fedex_lg_fee = 81.50;

global $shipping_fedex_ground;
global $shipping_fedex_freight_priority;
global $shipping_fedex_freight_economy;
global $shipping_dr_freight_s;
global $shipping_dr_freight_l;

$shipping_fedex_ground = "wf_fedex_woocommerce_shipping:FEDEX_GROUND";
$shipping_fedex_freight_priority = "wf_fedex_woocommerce_shipping:FEDEX_FREIGHT_PRIORITY";
$shipping_fedex_freight_economy = "wf_fedex_woocommerce_shipping:FEDEX_FREIGHT_ECONOMY";
$shipping_dr_freight_s = "dayross:day_rossdayross_S";
$shipping_dr_freight_l = "dayross:day_rossdayross_L";
        
// START ADD CUSTOM FIELDS
add_action('woocommerce_review_order_before_payment', 'bs_shipping_extras_add_custom_fields', 20);
function bs_shipping_extras_add_custom_fields() {

    echo '<div id="my_custom_checkout_field" class="bs_dr_shipping_extras_field_container"><h2>' . __('Additional Day & Ross Freight Services: ') . '</h2>';

    woocommerce_form_field('bs_dr_pr_fee', array(
        'type'  => 'checkbox',
        'label' => __('<strong>D&R Private Residence / Limited Access Delivery ($' . $GLOBALS['dr_pr_fee'] . '</strong><br><span class="extra_details">(Select this option if the driver cannot pull up to a loading dock to unload for this delivery. This option would include delivery to private residences or locations with limited access such as farms, ranches, dormitories, churches or schools. Locations determined to be in a residential area can be considered as a private residence.)</span>'),
        'class' => array('form-row-wide'),
        'placeholder'   => __(''),
    ), WC()->session->get('bs_dr_pr_fee') ? '1' : '');

    woocommerce_form_field('bs_dr_ad_fee', array(
        'type'  => 'checkbox',
        'label' => __('<strong>D&R Appointment Delivery ($' . $GLOBALS['dr_ad_fee'] . ')</strong><br><span class="extra_details">(Select this option if you require an appointment with the receiver for accepting your delivery from the driver. Appointment Freight occurs when the customer requests, via the Bill of Lading (BOL) or other means, to establish a time and date specific Appointment, or Call and Notify the consignee as a condition before attempting delivery. Enter Appointment Details in Special Instructions, if available.)</span>'),
        'class' => array('form-row-wide'),
        'placeholder'   => __(''),
    ), WC()->session->get('bs_dr_ad_fee') ? '1' : '');

    echo '</div>';

    echo '<div id="my_custom_checkout_field" class="bs_fedex_shipping_extras_field_container"><h2>' . __('Additional Fedex Freight Services: ') . '</h2>';

    woocommerce_form_field('bs_fedex_npd_fee', array(
        'type'  => 'checkbox',
        'label' => __('<strong>FedEx Notification Prior To Delivery ($' . $GLOBALS['fedex_npd_fee'] . ')</strong><br><span class="extra_details">(when notification prior to delivery is requested or required by any means whatsoever)</span>'),
        'class' => array('form-row-wide'),
        'placeholder'   => __(''),
    ), WC()->session->get('bs_fedex_npd_fee') ? '1' : '');


    woocommerce_form_field('bs_fedex_rd_fee', array(
        'type'  => 'checkbox',
        'label' => __('<strong>FedEx Residential Delivery ($' . $GLOBALS['fedex_rd_fee'] . ')</strong><br><span class="extra_details">(this includes private residences, apartment complexes, dormitories, businesses located at a private residence, farm or ranch that are not open to the walk-in public during normal business hours)</span>'),
        'class' => array('form-row-wide'),
        'placeholder'   => __(''),
    ), WC()->session->get('bs_fedex_rd_fee') ? '1' : '');

    woocommerce_form_field('bs_fedex_lad_fee', array(
        'type'  => 'checkbox',
        'label' => __('<strong>FedEx Limited Access Delivery ($' . $GLOBALS['fedex_lad_fee'] . ')</strong><br><span class="extra_details">(Limited access locations include: individual (mini) storage units, churches, schools, commercial establishments not open to walk-in public during normal business hours, construction sites, fairs or carnivals, prisons, military bases, mining sites, sites requiring security inspections prior to delivery, wind farm sites) Such charge will include an initial notification to make delivery arrangements.)</span>'),
        'class' => array('form-row-wide'),
        'placeholder'   => __(''),
    ), WC()->session->get('bs_fedex_lad_fee') ? '1' : '');

    woocommerce_form_field('bs_fedex_lg_fee', array(
        'type'  => 'checkbox',
        'label' => __('<strong>FedEx Liftgate Service ($' . $GLOBALS['fedex_lg_fee'] . ')</strong><br><span class="extra_details">(delivery by a truck equipped with a liftgate / tailgate that raises and lowers to facilitate unloading)</span>'),
        'class' => array('form-row-wide'),
        'placeholder'   => __(''),
    ), WC()->session->get('bs_fedex_lg_fee') ? '1' : '');

    echo '</div>';
}
// END ADD CUSTOM FIELDS

// START REMOVE 'optional' FROM BESIDE FIELD
add_filter('woocommerce_form_field', 'remove_order_comments_optional_fields_label', 10, 4);
function remove_order_comments_optional_fields_label($field, $key, $args, $value) {

    // Only on checkout page for Order notes field
    if ('bs_dr_pr_fee' === $key && is_checkout()) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
        $field = str_replace($optional, '', $field);
    }

    if ('bs_dr_ad_fee' === $key && is_checkout()) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
        $field = str_replace($optional, '', $field);
    }

    if ('bs_fedex_npd_fee' === $key && is_checkout()) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
        $field = str_replace($optional, '', $field);
    }

    if ('bs_fedex_rd_fee' === $key && is_checkout()) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
        $field = str_replace($optional, '', $field);
    }

    if ('bs_fedex_lad_fee' === $key && is_checkout()) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
        $field = str_replace($optional, '', $field);
    }

    if ('bs_fedex_lg_fee' === $key && is_checkout()) {
        $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
        $field = str_replace($optional, '', $field);
    }

    return $field;
}
// END REMOVE 'optional' FROM BESIDE FIELD


// START AJAX/JQUERY FOR ADDING/REMOVING CUSTOM FEES

// Ajax / jQuery script
add_action('wp_footer', 'bs_shipping_extras_fee_script');
function bs_shipping_extras_fee_script() {

    // On checkoutpage
    if ((is_checkout() && !is_wc_endpoint_url())) :
?>

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

                console.log('defined');


                // START ON PAGE LOAD CHECK WHAT SHIPPING METHOD IS SELECTED IF APPLICABLE  
                if ($(".shipping_method").attr('type') == 'hidden') { // IF ONLY ONE IS AVAILBLE ITS A HIDDEN INPUT FIELD SO GET ITS VALUE
                    var myShippingMethod = $('.shipping_method').val();
                    //alert(myShippingMethod);
                } else { // ELSE THERE WILL BE RADIO BUTTONS FOR THE AVAILABLE OPTIONS SO GET THE CHECKED VALUE
                    var myShippingMethod = $("input[type='radio'][name='shipping_method[0]']:checked").val();
                    //alert(myShippingMethod);   
                }
                // END ON PAGE LOAD CHECK WHAT SHIPPING METHOD IS SELECTED IF APPLICABLE    

                // START TO DO ON ajaxComplete
                $(document).ajaxComplete(function() {

                    //alert( "Triggered ajaxComplete handler." );

                    if ($(".shipping_method").attr('type') == 'hidden') { // IF ONLY ONE IS AVAILBLE ITS A HIDDEN INPUT FIELD SO GET ITS VALUE
                        var myShippingMethod = $('.shipping_method').val();
                        //alert(myShippingMethod);
                    } else { // ELSE THERE WILL BE RADIO BUTTONS FOR THE AVAILABLE OPTIONS SO GET THE CHECKED VALUE
                        var myShippingMethod = $("input[type='radio'][name='shipping_method[0]']:checked").val();
                        //alert(myShippingMethod);  
                    }


                    // IF FEDEX GROUND
                    if (myShippingMethod == "<?php print $GLOBALS['shipping_fedex_ground']; ?>") {
                        //alert('REMOVE ALL OPTIONS');

                        $(".bs_fedex_shipping_extras_field_container").css("display", "none");
                        $(".bs_dr_shipping_extras_field_container").css("display", "none");

                    }

                    // IF FEDEX PRIORITY OR ECONOMY
                    if (myShippingMethod == "<?php print $GLOBALS['shipping_fedex_freight_priority']; ?>" || myShippingMethod == "<?php print $GLOBALS['shipping_fedex_freight_economy']; ?>") {
                        //alert('SHOW FEDEX AND HIDE DAY AND ROSS');

                        $(".bs_fedex_shipping_extras_field_container").css("display", "block");
                        $(".bs_dr_shipping_extras_field_container").css("display", "none");

                    }

                    // IF DAY AND ROSS LIFTGATE AND STANDARD
                    if (myShippingMethod == "<?php print $GLOBALS['shipping_dr_freight_s']; ?>" || myShippingMethod == "<?php print $GLOBALS['shipping_dr_freight_l']; ?>") {
                        //alert('HIDE FEDEX AND SHOW DAY AND ROSS');

                        $(".bs_fedex_shipping_extras_field_container").css("display", "none");
                        $(".bs_dr_shipping_extras_field_container").css("display", "block");

                    }

                });
                // END TO DO ON ajaxComplete

                // START IF DAY AND ROSS PRIVATE RESIDENCE CHECKED
                // find wp/wc action(s) on lines 424 - 435
                $('input[name=bs_dr_pr_fee]').click(function() {
                    var dr_pr_fee = $(this).prop('checked') === true ? '1' : '';
                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'bs_dr_pr_fee',
                            'bs_dr_pr_fee': dr_pr_fee,
                        },
                        success: function(result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                            //alert(' DR Private'); 
                            var aTag = $("a[name='bsbacktodetails']");
                            $('html,body').animate({
                                scrollTop: aTag.offset().top
                            }, 'slow');
                        },

                    });
                });
                // END IF DAY AND ROSS PRIVATE RESIDENCE CHECKED

                // START IF DAY AND ROSS APPOINTMENT DELIVER CHECKED
                // find wp/wc action(s) on lines 437 - 448
                $('input[name=bs_dr_ad_fee]').click(function() {
                    var dr_ad_fee = $(this).prop('checked') === true ? '1' : '';
                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'bs_dr_ad_fee',
                            'bs_dr_ad_fee': dr_ad_fee,
                        },
                        success: function(result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                            //alert(' DR Appointment'); 
                            var aTag = $("a[name='bsbacktodetails']");
                            $('html,body').animate({
                                scrollTop: aTag.offset().top
                            }, 'slow');
                        },

                    });
                });
                // END IF DAY AND ROSS APPOINTMENT DELIVER CHECKED

                // START IF FEDEX NOTIFICATION PRIOR TO DELIVERY CHECKED
                // find wp/wc action(s) on lines 450 - 461
                $('input[name=bs_fedex_npd_fee]').click(function() {
                    //alert('Fedex NPD Checked');
                    var fedex_npd_fee = $(this).prop('checked') === true ? '1' : '';
                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'bs_fedex_npd_fee',
                            'bs_fedex_npd_fee': fedex_npd_fee,
                        },
                        success: function(result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                            //alert(' FedEx Notification Prior');
                            var aTag = $("a[name='bsbacktodetails']");
                            $('html,body').animate({
                                scrollTop: aTag.offset().top
                            }, 'slow');
                        },

                    });
                });
                // END IF FEDEX NOTIFICATION PRIOR TO DELIVERY CHECKED

                // START IF FEDEX RESIDENTIAL DELIVERY CHECKED
                // find wp/wc action(s) on lines 464 - 475
                $('input[name=bs_fedex_rd_fee]').click(function() {
                    var fedex_rd_fee = $(this).prop('checked') === true ? '1' : '';
                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'bs_fedex_rd_fee',
                            'bs_fedex_rd_fee': fedex_rd_fee,
                        },
                        success: function(result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                            //alert(' Form Residential Deliver');
                            var aTag = $("a[name='bsbacktodetails']");
                            $('html,body').animate({
                                scrollTop: aTag.offset().top
                            }, 'slow');
                        },

                    });
                });
                // END IF FEDEX RESIDENTIAL DELIVERY CHECKED

                // START IF FEDEX Limited Access Delivery CHECKED
                // find wp/wc action(s) on lines 478 - 487
                $('input[name=bs_fedex_lad_fee]').click(function() {
                    var fedex_lad_fee = $(this).prop('checked') === true ? '1' : '';
                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'bs_fedex_lad_fee',
                            'bs_fedex_lad_fee': fedex_lad_fee,
                        },
                        success: function(result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                            //alert(' FedEx LAD');
                            var aTag = $("a[name='bsbacktodetails']");
                            $('html,body').animate({
                                scrollTop: aTag.offset().top
                            }, 'slow');
                        },

                    });
                });
                // END IF FEDEX Limited Access Delivery CHECKED

                // START IF FEDEX LIFTGATE SERVICE CHECKED
                // find wp/wc action(s) on lines 492 - 502
                $('input[name=bs_fedex_lg_fee]').click(function() {
                    var fedex_lg_fee = $(this).prop('checked') === true ? '1' : '';
                    $.ajax({
                        type: 'POST',
                        url: woocommerce_params.ajax_url,
                        data: {
                            'action': 'bs_fedex_lg_fee',
                            'bs_fedex_lg_fee': fedex_lg_fee,
                        },
                        success: function(result) {
                            $('body').trigger('update_checkout');
                            console.log(result);
                            //alert(' FedEx LG');
                            var aTag = $("a[name='bsbacktodetails']");
                            $('html,body').animate({
                                scrollTop: aTag.offset().top
                            }, 'slow');

                        },

                    });
                });
                // END IF FEDEX LIFTGATE SERVICE CHECKED


                // When shipping method is changed
                // try and clear wc sessions related to the custom extra fees.
                jQuery('form.checkout').on('change', 'input[name^="shipping_method"]', function() {
                    var val = jQuery(this).val();

                    //alert('Form Changed');

                    // Uncheck All Extra custom fee checkboxes
                    $("#bs_fedex_npd_fee").prop("checked", false);
                    $("#bs_fedex_rd_fee").prop("checked", false);
                    $("#bs_fedex_lad_fee").prop("checked", false);
                    $("#bs_fedex_lg_fee").prop("checked", false);
                    $("#bs_dr_pr_fee").prop("checked", false);
                    $("#bs_dr_ad_fee").prop("checked", false);


                    // ajax call to wp/wc action(s) that should unset the custom fee sessions
                    // however its in consistant and only removes the fees sometimes?????
                    // find wp/wc action(s) on lines 550 - 570
                    $.ajax({
                        type: "POST",
                        url: woocommerce_params.ajax_url,
                        data: {
                            action: 'bs_clear_extra_fees'
                        },
                        success: function(data) {
                            alert(data);
                            $('body').trigger('update_checkout');
                        },
                        error: function(errorThrown) {

                        }
                    });

                });

            });
        </script>

<?php
    endif;
}
// END AJAX/JQUERY FOR ADDING/REMOVING FEES

// START GET AJAX REQUEST FOR DAY AND ROSS PRIVATE RES AND SET WC SESSION
add_action('wp_ajax_bs_dr_pr_fee', 'get_ajax_bs_dr_pr_fee');
add_action('wp_ajax_nopriv_bs_dr_pr_fee', 'get_ajax_bs_dr_pr_fee');
function get_ajax_bs_dr_pr_fee() {
    if (isset($_POST['bs_dr_pr_fee'])) {
        WC()->session->set('bs_dr_pr_fee', ($_POST['bs_dr_pr_fee'] ? '1' : ''));
    }
    die();
}
// END GET AJAX REQUEST FOR DAY AND ROSS PRIVATE RES AND SET WC SESSION

// START GET AJAX REQUEST FOR DAY AND ROSS APPOINTMENT DELIVERY AND SET WC SESSION
add_action('wp_ajax_bs_dr_ad_fee', 'get_ajax_bs_dr_ad_fee');
add_action('wp_ajax_nopriv_bs_dr_ad_fee', 'get_ajax_bs_dr_ad_fee');
function get_ajax_bs_dr_ad_fee() {
    if (isset($_POST['bs_dr_ad_fee'])) {
        WC()->session->set('bs_dr_ad_fee', ($_POST['bs_dr_ad_fee'] ? '1' : ''));
    }
    die();
}
// END GET AJAX REQUEST FOR DAY AND ROSS APPOINTMENT DELIVERY AND SET WC SESSION

// START GET AJAX REQUEST FOR FEDEX NOTIFICATION PRIOR TO DELIVERY AND SET WC SESSION
add_action('wp_ajax_bs_fedex_npd_fee', 'get_ajax_bs_fedex_npd_fee');
add_action('wp_ajax_nopriv_bs_fedex_npd_fee', 'get_ajax_bs_fedex_npd_fee');
function get_ajax_bs_fedex_npd_fee(){
    if (isset($_POST['bs_fedex_npd_fee'])) {
        WC()->session->set('bs_fedex_npd_fee', ($_POST['bs_fedex_npd_fee'] ? '1' : ''));
    }
    die();
}
// END GET AJAX REQUEST FOR FEDEX NOTIFICATION PRIOR TO DELIVERY AND SET WC SESSION


// START GET AJAX REQUEST FOR FEDEX RESIDENTIAL DELIVERY AND SET WC SESSION
add_action('wp_ajax_bs_fedex_rd_fee', 'get_ajax_bs_fedex_rd_fee');
add_action('wp_ajax_nopriv_bs_fedex_rd_fee', 'get_ajax_bs_fedex_rd_fee');
function get_ajax_bs_fedex_rd_fee() {
    if (isset($_POST['bs_fedex_rd_fee'])) {
        WC()->session->set('bs_fedex_rd_fee', ($_POST['bs_fedex_rd_fee'] ? '1' : ''));
    }
    die();
}
// END GET AJAX REQUEST FOR FEDEX RESIDENTIAL DELIVERY AND SET WC SESSION


// START GET AJAX REQUEST FOR FEDEX Limited Access Delivery AND SET WC SESSION
add_action('wp_ajax_bs_fedex_lad_fee', 'get_ajax_bs_fedex_lad_fee');
add_action('wp_ajax_nopriv_bs_fedex_lad_fee', 'get_ajax_bs_fedex_lad_fee');
function get_ajax_bs_fedex_lad_fee() {
    if (isset($_POST['bs_fedex_lad_fee'])) {
        WC()->session->set('bs_fedex_lad_fee', ($_POST['bs_fedex_lad_fee'] ? '1' : ''));
    }
    die();
}
// END GET AJAX REQUEST FOR FEDEX Limited Access Delivery AND SET WC SESSION


// START GET AJAX REQUEST FOR FEDEX LIFTGATE SERIVCE AND SET WC SESSION
add_action('wp_ajax_bs_fedex_lg_fee', 'get_ajax_bs_fedex_lg_fee');
add_action('wp_ajax_nopriv_bs_fedex_lg_fee', 'get_ajax_bs_fedex_lg_fee');
function get_ajax_bs_fedex_lg_fee() {
    if (isset($_POST['bs_fedex_lg_fee'])) {
        WC()->session->set('bs_fedex_lg_fee', ($_POST['bs_fedex_lg_fee'] ? '1' : ''));
    }
    die();
}
// END GET AJAX REQUEST FOR FEDEX LIFTGATE SERIVCE AND SET WC SESSION


// START ADD AND REMOVE CUSTOM FEES
add_action('woocommerce_cart_calculate_fees', 'add_remove_bs_shipping_extras_fees', 20, 1);
function add_remove_bs_shipping_extras_fees($cart) {
    // Only on checkout
    if ((is_admin() && !defined('DOING_AJAX')) || is_cart())
        return;

    $dr_pr_fee_amount = $GLOBALS['dr_pr_fee'];
    $dr_ad_fee_amount = $GLOBALS['dr_ad_fee'];
    $fedex_npd_fee_amount = $GLOBALS['fedex_npd_fee'];
    $fedex_rd_fee_amount = $GLOBALS['fedex_rd_fee'];
    $fedex_lad_fee_amount = $GLOBALS['fedex_lad_fee'];
    $fedex_lg_fee_amount = $GLOBALS['fedex_lg_fee'];

    if (WC()->session->get('bs_dr_pr_fee'))
        WC()->cart->add_fee('D&R Private Residence / Limited Access Delivery', $dr_pr_fee_amount, true);

    if (WC()->session->get('bs_dr_ad_fee'))
        WC()->cart->add_fee('D&R Appointment Delivery', $dr_ad_fee_amount, true);

    if (WC()->session->get('bs_fedex_npd_fee'))
        WC()->cart->add_fee('FedEx Notification Prior To Delivery', $fedex_npd_fee_amount, true);

    if (WC()->session->get('bs_fedex_rd_fee'))
        WC()->cart->add_fee('FedEx Residential Delivery', $fedex_rd_fee_amount, true);

    if (WC()->session->get('bs_fedex_lad_fee'))
        WC()->cart->add_fee('FedEx Limited Access Delivery', $fedex_lad_fee_amount, true);

    if (WC()->session->get('bs_fedex_lg_fee'))
        WC()->cart->add_fee('FedEx Liftgate Service', $fedex_lg_fee_amount, true);
}
// END ADD AND REMOVE CUSTOM FEES


// START CLEAR CART FEES HERE FROM THE AJAX CALL IN THE ON CHANGE OF FORM
function bs_shipping_extras_anchor_checkout($order) {
    echo '<a name="bsbacktodetails">';
}
add_action('woocommerce_checkout_before_order_review', 'bs_shipping_extras_anchor_checkout', 10, 1);


// START CLEAR CART FEES HERE FROM THE AJAX CALL IN THE ON CHANGE OF FORM
function bs_clear_extra_fees() {

    // THESE SESSIONS DONT SEEM TO BE UNSETTING
    // OR FEES NOT CLEARING NOT CLEARNING CONSISTANTLY???
    // Sometimes the fees stay and are not removed.
    WC()->session->__unset('bs_fedex_npd_fee');
    WC()->session->__unset('bs_fedex_rd_fee');
    WC()->session->__unset('bs_fedex_lad_fee');
    WC()->session->__unset('bs_fedex_lg_fee');
    WC()->session->__unset('bs_dr_pr_fee');
    WC()->session->__unset('bs_dr_ad_fee');


    print "Shipping method has changed. Please review your order details.";
    wp_die();
}
add_action('wp_ajax_bs_clear_extra_fees', 'bs_clear_extra_fees');
add_action('wp_ajax_nopriv_bs_clear_extra_fees', 'bs_clear_extra_fees');
// END CLEAR CART FEES HERE FROM THE AJAX CALL IN THE ON CHANGE OF FORM
 2  54  2
1 Jan 1970

Solution

 0

There are some mistakes in your code and it can be simplified, compacted and optimized.

Note:
The code allow to set multiple fees, depending on the related displayed checkboxes. If you want to allow only one fee (so only one checked checkbox at the time) see the addition at the end.

Try the following:

// Utility function: Settings for checkboxes fields and fees
function get_bs_fields_fees_settings() {
    return array(
        'dr_pr_fee'     => array(
            'cost'  => 60,
            'label' => __('D&R Private Residence / Limited Access Delivery'),
            'extra' => __('select this option if the driver cannot pull up to a loading dock to unload for this delivery. This option would include delivery to private residences or locations with limited access such as farms, ranches, dormitories, churches or schools. Locations determined to be in a residential area can be considered as a private residence.'),
        ),
        'dr_ad_fee'     => array(
            'cost'  => 46.87,
            'label' => __('D&R Appointment Delivery'),
            'extra' => __('select this option if you require an appointment with the receiver for accepting your delivery from the driver. Appointment Freight occurs when the customer requests, via the Bill of Lading (BOL) or other means, to establish a time and date specific Appointment, or Call and Notify the consignee as a condition before attempting delivery. Enter Appointment Details in Special Instructions, if available.'),
        ),
        'fedex_npd_fee' => array(
            'cost'  => 61,
            'label' => __('FedEx Notification Prior To Delivery'),
            'extra' => __('when notification prior to delivery is requested or required by any means whatsoever'),
        ),
        'fedex_rd_fee'  => array(
            'cost'  => 191,
            'label' => __('D&FedEx Residential Delivery'),
            'extra' => __('this includes private residences, apartment complexes, dormitories, businesses located at a private residence, farm or ranch that are not open to the walk-in public during normal business hours.'),
        ),
        'fedex_lad_fee' => array(
            'cost'  => 85,
            'label' => __('D&FedEx Limited Access Delivery'),
            'extra' => __('limited access locations include: individual (mini) storage units, churches, schools, commercial establishments not open to walk-in public during normal business hours, construction sites, fairs or carnivals, prisons, military bases, mining sites, sites requiring security inspections prior to delivery, wind farm sites) Such charge will include an initial notification to make delivery arrangements.'),
        ),
        'fedex_lg_fee'  => array(
            'cost'  => 81.50,
            'label' => __('D&FedEx Liftgate Service'),
            'extra' => __('delivery by a truck equipped with a liftgate / tailgate that raises and lowers to facilitate unloading.'),
        ),
    );
}

// Utility function: Array of hipping method rate Ids
function get_bs_shipping_method_ids() {
    return array(
        'fedex_ground'    => 'wf_fedex_woocommerce_shipping:FEDEX_GROUND',
        'fedex_priority'  => 'wf_fedex_woocommerce_shipping:FEDEX_FREIGHT_PRIORITY',
        'fedex_economy'   => 'wf_fedex_woocommerce_shipping:FEDEX_FREIGHT_ECONOMY',
        'dayross_s'       => 'dayross:day_rossdayross_S',
        'dayross_l'       => 'dayross:day_rossdayross_L',
    );
}

// Add custom checkout fields after order review table
add_action('woocommerce_review_order_before_payment', 'add_bs_shipping_extras_custom_fields', 20);
function add_bs_shipping_extras_custom_fields() {
    echo '<div id="bs-checkout-fields">';

    $chosen_fees    = (array) WC()->session->get('chosen_fees'); // Get session variable data
    $section_titles = array( 
        'dr_pr_fee'         => '<div class="dayross-fields-group" style="display:none;">
            <h2>' . __('Additional Day & Ross Freight Services: ') . '</h2>',

        'fedex_npd_fee'     => '</div>
        <div class="fedex-fields-group" style="display:none;">
            <h2>' . __('Additional Fedex Freight Services: ') . '</h2>',
    );

    // Loop through Fields settings array
    foreach ( get_bs_fields_fees_settings() as $field_key => $field_data ) {
        // Add Sections and titles
        if ( isset($section_titles[$field_key]) ) {
            echo $section_titles[$field_key];
        }

        $label_string   = '<strong>%s%s</strong> <br><span class="extra_details">(%s)</span>'; // with placeholders
        $formatted_cost = ' (' . strip_tags( wc_price($field_data['cost']) ) . ')';

        woocommerce_form_field('bs_'.$field_key, array(
            'type'          => 'checkbox',
            'label'         => sprintf($label_string , $field_data['label'], $formatted_cost, $field_data['extra']),
            'class'         => array('form-row-wide'),
            'placeholder'   => '',
        ), isset($chosen_fees[$field_key]) && $chosen_fees[$field_key] ? '1' : '' );
    }
    echo '</div></div>';
}

// Remove 'optional' from specific fields
add_filter('woocommerce_form_field', 'remove_bs_optional_fields_label', 10, 4);
function remove_bs_optional_fields_label($field, $key, $args, $value) {
    if ( is_checkout() && !is_wc_endpoint_url() ) {
        foreach( array_keys(get_bs_fields_fees_settings()) as $field_key ) {
            if ( $key === 'bs_' . $field_key ) {
                $optional = '&nbsp;<span class="optional">(' . esc_html__('optional', 'woocommerce') . ')</span>';
                $field = str_replace($optional, '', $field);
            }
        }
    }
    return $field;
}

// Add an empty div as an anchor to scroll back.
add_action('woocommerce_checkout_before_order_review', 'bs_shipping_extras_anchor_checkout');
function bs_shipping_extras_anchor_checkout() {
    echo '<div id="bs-back-to-details"></div>';
}

// jQuery code (Show hide field \ Send Ajax requests)
add_action('wp_footer', 'bs_shipping_extra_fees_js');
function bs_shipping_extra_fees_js() {
    if ( is_checkout() && !is_wc_endpoint_url() ) : 
    
    $shipping = get_bs_shipping_method_ids();
    ?>
    <script type="text/javascript">
    jQuery(function($) {
        if (typeof wc_checkout_params === 'undefined') {
            return false;
        }

        const ShippingM = 'input[name^=shipping_method]',
            backTag   = $('#bs-back-to-details'),
            feeFields = <?php echo json_encode( array_keys(get_bs_fields_fees_settings()) ); ?>;

        var chosenShipping = $(ShippingM).attr('type') === 'hidden' ? $(ShippingM).val() : $(ShippingM+':checked').val();

        // Function that show or hide field groups based on the chosen shipping method
        function ShowHideCheckboxesFieldsGroups( chosenShipping ) {
            // Shipping FEDEX "GROUND": Hide All
            if ( chosenShipping === '<?php echo $shipping['fedex_ground']; ?>') {
                $('.dayross-fields-group').hide();
                $('.fedex-fields-group').hide();
            }
            // Shipping FEDEX FREIGHT "PRIORITY" or "ECONOMY": Show "Fedex" fields group only
            else if ( chosenShipping === '<?php echo $shipping['fedex_priority']; ?>' || chosenShipping === '<?php echo $shipping['fedex_economy']; ?>' ) {
                $('.dayross-fields-group').hide();
                $('.fedex-fields-group').show();
            }
            // Shipping DAY AND ROSS "LIFTGATE" or "STANDARD": Show "dayross" fields group only
            else if ( chosenShipping === '<?php echo $shipping['dayross_s']; ?>' || chosenShipping === '<?php echo $shipping['dayross_l']; ?>' ) {
                $('.dayross-fields-group').show();
                $('.fedex-fields-group').hide();
            }
        }

        // Function that scrolls back to Order details
        function scrollBackToBottom(){
            $('html,body').animate({
                scrollTop: backTag.offset().top
            }, 'slow');
        }

        // Function that Uncheck All Extra custom fee checkboxes
        function uncheckAllCheckboxes(){
            $.each(feeFields, function(index, key){
                if ( $('input[name=bs_'+key+']').prop('checked') === true ) {
                    $('input[name=bs_'+key+']').prop('checked', false);
                }
            });
        }

        // On Start: Show / hide custom field groups
        ShowHideCheckboxesFieldsGroups( chosenShipping );

        // On shipping methods "Change" event (Show / hide fields)
        $('form.checkout').on('change', ShippingM, function() {
            // Uncheck All Extra custom fee checkboxes
            uncheckAllCheckboxes();

            // Show / hide custom field groups
            ShowHideCheckboxesFieldsGroups( $(this).val() );
            
            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action':   'chosen_fee',
                    'field_id': 'clear_all',
                    'enabled':  '0'
                },
                success: function(response) {
                    setTimeout(function(){
                        $(document.body).trigger('update_checkout');
                    }, 250);
                }
            });
        });

        // On Custom Checkboxes fields "Click" events
        $.each(feeFields, function(index, key){
            $('input[name=bs_'+key+']').on('click', function() {
                $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action':   'chosen_fee',
                        'field_id': key,
                        'enabled':  $(this).prop('checked') === true ? '1' : '0'
                    },
                    success: function(result) {
                        scrollBackToBottom();
                        $(document.body).trigger('update_checkout');
                    }
                });
            });
        });
    });      
    </script>
    <?php
    endif;
}

// Ajax PHP Receiver: Set WC Session variable for fees
add_action('wp_ajax_chosen_fee', 'set_session_chosen_fees');
add_action('wp_ajax_nopriv_chosen_fee', 'set_session_chosen_fees');
function set_session_chosen_fees() {
    if ( isset($_POST['field_id']) && isset($_POST['enabled']) ) {
        $chosen_fees = (array) WC()->session->get('chosen_fees');

        if ( esc_attr($_POST['field_id']) === 'clear_all' ) {
            WC()->session->set('chosen_fees', []); // Empty fees array
        } else {
            $chosen_fees[esc_attr($_POST['field_id'])] = intval($_POST['enabled']);
            WC()->session->set('chosen_fees', $chosen_fees); // Update fees array
        }
    }
    wp_die();
}


// Add Fees based on checkboxes choices
add_action('woocommerce_cart_calculate_fees', 'add_bs_shipping_extras_fees', 20, 1);
function add_bs_shipping_extras_fees( $cart ) {
    // Only on checkout
    if ((is_admin() && !defined('DOING_AJAX')) || is_cart())
        return;

    $chosen_fees = (array) WC()->session->get('chosen_fees'); // Load Wc Session variable array

    foreach ( get_bs_fields_fees_settings() as $key => $fee_data ) {
        if ( isset($chosen_fees[$key]) && $chosen_fees[$key] ) {
            $cart->add_fee($fee_data['label'], $fee_data['cost'], true);
        }
    }
}

It should work.

Note: You may need to adjust the displayed cost in the checkboxes, adding the taxes if any.


Addition

Allow only one fee at the time (one checked checkbox only):

Use the following replacement functions:

// jQuery code (Show hide field \ Send Ajax requests)
add_action('wp_footer', 'bs_shipping_extra_fees_js');
function bs_shipping_extra_fees_js() {
    if ( is_checkout() && !is_wc_endpoint_url() ) : 
    
    $shipping = get_bs_shipping_method_ids();
    ?>
    <script type="text/javascript">
    jQuery(function($) {
        if (typeof wc_checkout_params === 'undefined') {
            return false;
        }

        const ShippingM = 'input[name^=shipping_method]',
            backTag   = $('#bs-back-to-details'),
            feeFields = <?php echo json_encode( array_keys(get_bs_fields_fees_settings()) ); ?>;

        var chosenShipping = $(ShippingM).attr('type') === 'hidden' ? $(ShippingM).val() : $(ShippingM+':checked').val();

        // Function that show or hide field groups based on the chosen shipping method
        function ShowHideCheckboxesFieldsGroups( chosenShipping ) {
            // Shipping FEDEX "GROUND": Hide All
            if ( chosenShipping === '<?php echo $shipping['fedex_ground']; ?>') {
                $('.dayross-fields-group').hide();
                $('.fedex-fields-group').hide();
            }
            // Shipping FEDEX FREIGHT "PRIORITY" or "ECONOMY": Show "Fedex" fields group only
            else if ( chosenShipping === '<?php echo $shipping['fedex_priority']; ?>' || chosenShipping === '<?php echo $shipping['fedex_economy']; ?>' ) {
                $('.dayross-fields-group').hide();
                $('.fedex-fields-group').show();
            }
            // Shipping DAY AND ROSS "LIFTGATE" or "STANDARD": Show "dayross" fields group only
            else if ( chosenShipping === '<?php echo $shipping['dayross_s']; ?>' || chosenShipping === '<?php echo $shipping['dayross_l']; ?>' ) {
                $('.dayross-fields-group').show();
                $('.fedex-fields-group').hide();
            }
        }

        // Function that scrolls back to Order details
        function scrollBackToBottom(){
            $('html,body').animate({
                scrollTop: backTag.offset().top
            }, 'slow');
        }

        // Function that Uncheck All Extra custom fee checkboxes
        function uncheckAllCheckboxes( currentKey = null ){
            console.log(currentKey);
            $.each(feeFields, function(index, key){
                if ( currentKey !== key && $('input[name=bs_'+key+']').prop('checked') === true ) {
                    $('input[name=bs_'+key+']').prop('checked', false);
                }
            });
        }

        // On Start: Show / hide custom field groups
        ShowHideCheckboxesFieldsGroups( chosenShipping );

        // On shipping methods "Change" event (Show / hide fields)
        $('form.checkout').on('change', ShippingM, function() {
            // Uncheck All Extra custom fee checkboxes
            $.each(feeFields, function(index, key){
                if ( $('input[name=bs_'+key+']').prop('checked') === true ) {
                    $('input[name=bs_'+key+']').prop('checked', false);
                }
            });

            // Show / hide custom field groups
            ShowHideCheckboxesFieldsGroups( $(this).val() );
            
            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action':   'chosen_fee',
                    'field_id': 'clear_all',
                    'enabled':  '0'
                },
                success: function(response) {
                    setTimeout(function(){
                        $(document.body).trigger('update_checkout');
                    }, 250);
                }
            });
        });

        // On Custom Checkboxes fields "Click" events
        $.each(feeFields, function(index, key){
            $('input[name=bs_'+key+']').on('click', function() {
                uncheckAllCheckboxes( key ); // Uncheck All Extra custom fee checkboxes (except current)
            
                $.ajax({
                    type: 'POST',
                    url: wc_checkout_params.ajax_url,
                    data: {
                        'action':   'chosen_fee',
                        'field_id': key,
                        'enabled':  $(this).prop('checked') === true ? '1' : '0'
                    },
                    success: function(result) {
                        scrollBackToBottom();
                        $(document.body).trigger('update_checkout');
                    }
                });
            });
        });
    });      
    </script>
    <?php
    endif;
}

// Ajax PHP Receiver: Set WC Session variable for fees
add_action('wp_ajax_chosen_fee', 'set_session_chosen_fees');
add_action('wp_ajax_nopriv_chosen_fee', 'set_session_chosen_fees');
function set_session_chosen_fees() {
    if ( isset($_POST['field_id']) && isset($_POST['enabled']) ) {
        $chosen_fees = array(); // Initialize

        if ( esc_attr($_POST['field_id']) !== 'clear_all' && intval($_POST['enabled']) === 1 ) {
            $chosen_fees[esc_attr($_POST['field_id'])] = 1;
        }
        WC()->session->set('chosen_fees', $chosen_fees); // Update fees array
    }
    wp_die();
}
2024-07-20
LoicTheAztec