简体   繁体   中英

Custom checkbox that adds a fee in WooCommerce cart page

Based on Display a checkbox that add a fee in Woocommerce checkout page answer code I am trying to change usage to Cart page, rather than checkout page per clients request.

So far I managed to display custom fee check box on cart page and trigger Ajax.

However Cart totals are not updated. If someone can help on code or point me in right direction?

// Display the custom checkbox field in cart

add_action( 'woocommerce_cart_totals_before_order_total', 'fee_installment_checkbox_field', 20 );
function fee_installment_checkbox_field(){
    echo '<tr class="packing-select"><th>Priority Dispatch</th><td>';

    woocommerce_form_field( 'priority_fee', array(
        'type'          => 'checkbox',
        'class'         => array('installment-fee form-row-wide'),
        'label'         => __(' $20.00'),
        'placeholder'   => __(''),
    ), WC()->session->get('priority_fee') ? '1' : '' );

    echo '<div class="tooltip">?
  <span class="tooltiptext">By selecting this option... </span>
</div></td>';
}

// jQuery - Ajax script
add_action( 'wp_footer', 'woo_add_cart_fee' );
function woo_add_cart_fee() {
    // Only on Checkout
    if(  ! is_wc_endpoint_url() ) :

    if( WC()->session->__isset('priority_fee') )
        WC()->session->__unset('priority_fee')
    ?>
    <script type="text/javascript">
    jQuery( function($){
        //if (typeof wc_add_to_cart_params  === 'undefined')
          //  return false;

        $('tr.packing-select').on('change', 'input[name=priority_fee]', function(){
            console.log('tests');
            var fee = $(this).prop('checked') === true ? '1' : '';
            
            

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


// Get Ajax request and saving to WC session
add_action( 'wp_ajax_priority_fee', 'get_priority_fee' );
add_action( 'wp_ajax_nopriv_priority_fee', 'get_priority_fee' );
function get_priority_fee() {
    if ( isset($_POST['priority_fee']) ) {
        WC()->session->set('priority_fee', ($_POST['priority_fee'] ? true : false) );
    }
    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 ( did_action('woocommerce_cart_calculate_fees') >= 2 )
        return;

    if ( 1 == WC()->session->get('priority_fee') ) {
        $items_count = WC()->cart->get_cart_contents_count();
        $fee_label   = sprintf( __( "PRIORITY DISPATCH %s %s" ), '&times;', $items_count );
        $fee_amount  = 20;
        WC()->cart->add_fee( $fee_label, $fee_amount );
    }
}

add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_installment_checkbox', 10, 4 );
function remove_optional_txt_from_installment_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;
}

Additionally is this the way this should be done, or is there an easier way to do it?

There are some mistakes in your code. Also, on cart page, jQuery events and Ajax behavior are a bit different, so it requires some changes:

// Display the checkout field in cart page totals section
add_action( 'woocommerce_cart_totals_before_order_total', 'display_priority_fee_checkbox_field', 20 );
function display_priority_fee_checkbox_field(){
    echo '<tr class="installment-section">
    <th>'.__("Priority Dispatch").'</th><td>';

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

    echo '<div class="tooltip">?
    <span class="tooltiptext">'.__("By selecting this option... ").'</span>
    </div></td>';
}

// 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') ) {
        $item_count  = $cart->get_cart_contents_count();
        $fee_label   = sprintf( __( "PRIORITY DISPATCH %s" ), '&times; ' . $item_count );
        $fee_amount  = 20 * $item_count;
        $cart->add_fee( $fee_label, $fee_amount );
    }
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM