Mohammad Ghali
Mohammad Ghali

Reputation: 29

Woocommerce new cart item price not updating

In WooCommerce I want to have a checkbox that, when pressed, it adds a product to my cart, and the price of that product is 3% of the total cart price.

Based on "Checkbox field that add to cart a product in Woocommerce checkout page" answer thread and edited a bit to suit my needs, here is my code:


 // Display a custom checkout field
add_action( 'woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field' );
function custom_checkbox_checkout_field() {
    $value = WC()->session->get('add_a_product');

    woocommerce_form_field( 'cb_add_product', array(
        'type'          => 'checkbox',
        'label'         => '  ' . __('Add Assembly Service (3% extra)'),
        'class'         => array('form-row-wide'),
    ), $value == 'yes' ? true : false );
}


// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_custom_jquery_script' );
function checkout_custom_jquery_script() {
    // Only checkout page
    if( is_checkout() && ! is_wc_endpoint_url() ):

    // Remove "ship_different" custom WC session on load
    if( WC()->session->get('add_a_product') ){
        WC()->session->__unset('add_a_product');
    }
    if( WC()->session->get('product_added_key') ){
        WC()->session->__unset('product_added_key');
    }
    // jQuery Ajax code
    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof wc_checkout_params === 'undefined')
            return false;

        $('form.checkout').on( 'change', '#cb_add_product', function(){
            var value = $(this).prop('checked') === true ? 'yes' : 'no';

            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': 'add_a_product',
                    'add_a_product': value,
                },
                success: function (result) {
                    $('body').trigger('update_checkout');
                    console.log(result);
                }
            });
        });
    });
    </script>
    <?php
    endif;
}

// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
function checkout_ajax_add_a_product() {
    if ( isset($_POST['add_a_product']) ){
        WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
        echo $_POST['add_a_product'];
    }
    die();
}

// Add remove free product
add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product');
function adding_removing_specific_product( $cart ) {
    if (is_admin() && !defined('DOING_AJAX'))
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // HERE the specific Product ID
    $product_id = 1514;

    $result = WC()->session->get('add_a_product');
    if( strpos($result, 'yes') !== false && ! WC()->session->get('product_added_key') )
    {
        $cart_item_key = $cart->add_to_cart( $product_id );
        WC()->session->set('product_added_key', $cart_item_key);

    }
    elseif( strpos($result, 'no') !== false && WC()->session->get('product_added_key') )
    {
        $cart_item_key = WC()->session->get('product_added_key');
        $cart->remove_cart_item( $cart_item_key );
        WC()->session->__unset('product_added_key');
    }
}

function woocommerce_custom_price_to_cart_item( $cart ) {  
    if (is_admin() && !defined('DOING_AJAX'))
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    if( !WC()->session->__isset( "reload_checkout" )) {
         global $woocommerce; 
        $totalPriceBeforeService = $cart->cart_contents_total;
        $servicePrice = (float) ceil($totalPriceBeforeService) * 0.03;
        foreach ( $cart->cart_contents as $key => $value ) {
            $product_idnew = $value['data']->get_id();
             if($product_idnew == 1514){
                 //set new prices
                $value['data']->set_price($servicePrice);
                $new_price = $value['data']->get_price();
                echo" $new_price ";
             }
        } 
    }  
}
add_action( 'woocommerce_before_calculate_totals', 'woocommerce_custom_price_to_cart_item' );

It adds the product fine, and all is good. However, when I set the price, its not updating.

Okay, So here is the checkbox unselected.

enter image description here

And here is the checkbox after checking it. As you can see, the value of the item is 46.5, but its not updating in the cart. Any idea how to fix this?

enter image description here

Upvotes: 1

Views: 1823

Answers (1)

7uc1f3r
7uc1f3r

Reputation: 29624

  • You use 2x woocommerce_before_calculate_totals, I reduced it to 1.

  • $cart->get_cart_contents_total(); also include the original product price (of the new added product), so this will be deducted before the final calculation.

// Display a custom checkout field
add_action( 'woocommerce_checkout_before_terms_and_conditions', 'custom_checkbox_checkout_field' );
function custom_checkbox_checkout_field() {
    $value = WC()->session->get('add_a_product');

    woocommerce_form_field( 'cb_add_product', array(
        'type'          => 'checkbox',
        'label'         => '&nbsp;&nbsp;' . __('Add a demo product to your order'),
        'class'         => array('form-row-wide'),
    ), $value == 'yes' ? true : false );
}


// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_custom_jquery_script' );
function checkout_custom_jquery_script() {
    // Only checkout page
    if( is_checkout() && ! is_wc_endpoint_url() ):

    // Remove "ship_different" custom WC session on load
    if( WC()->session->get('add_a_product') ){
        WC()->session->__unset('add_a_product');
    }
    if( WC()->session->get('product_added_key') ){
        WC()->session->__unset('product_added_key');
    }
    // jQuery Ajax code
    ?>
    <script type="text/javascript">
    jQuery( function($){
        if (typeof wc_checkout_params === 'undefined')
            return false;

        $('form.checkout').on( 'change', '#cb_add_product', function(){
            var value = $(this).prop('checked') === true ? 'yes' : 'no';

            $.ajax({
                type: 'POST',
                url: wc_checkout_params.ajax_url,
                data: {
                    'action': 'add_a_product',
                    'add_a_product': value,
                },
                success: function (result) {
                    $('body').trigger('update_checkout');
                    console.log(result);
                }
            });
        });
    });
    </script>
    <?php
    endif;
}

// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
function checkout_ajax_add_a_product() {
    if ( isset($_POST['add_a_product']) ){
        WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
        echo $_POST['add_a_product'];
    }
    die();
}

// Add remove free product
function adding_removing_specific_product( $cart ) {
    if (is_admin() && !defined('DOING_AJAX'))
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // HERE the specific Product ID
    $product_id = 1514;

    if( WC()->session->get('add_a_product') == 'yes' && ! WC()->session->get('product_added_key') ) {
        $cart_item_key = $cart->add_to_cart( $product_id );
        WC()->session->set('product_added_key', $cart_item_key);
    }
    elseif( WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key') ) {
        $cart_item_key = WC()->session->get('product_added_key');
        $cart->remove_cart_item( $cart_item_key );
        WC()->session->__unset('product_added_key');
    }
    
    if( !WC()->session->__isset( "reload_checkout" )) {
        // Get cart total
        $cart_total = $cart->get_cart_contents_total();
        
        if ( isset( $cart_total ) && $cart_total != 0 ) {                       
            foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
                // Get product id
                $product_id_new = $cart_item['product_id'];
                
                // Get original product price
                $exclude_original_product_price = $cart_item['data']->get_price();

                if( $product_id_new == $product_id ) {
                    // Calculate new cart total
                    $new_cart_total = $cart_total - $exclude_original_product_price;
                    
                    // Caclulate new price ( 3% )
                    $new_price = $new_cart_total * 3 / 100;
                    
                    $cart_item['data']->set_price( $new_price );
                    break;
                }
            }
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product', 10, 1 );

Upvotes: 1

Related Questions