Search code examples
phpwordpresswoocommercecarthook-woocommerce

Set a custom calculated item price in Woocommerce mini-cart / Cart


Currently i have some custom calculation of product price based on different situation. When customer added a product in to cart then the custom price is set in session data , cart_item_data['my-price'] and i implemented using add_filter( 'woocommerce_add_cart_item') function and everything seems to working now .

Now the price in view cart page, checkout page is correct with my cart_item_data['my-price'].

But the only problem i am facing is the price is not updated in woocommerce mini cart that is appeared in the menu ,How can i change this ?

enter image description here

When i google i see a filter

add_filter('woocommerce_cart_item_price');

but i can't understand how to use this i do the following

    add_filter('woocommerce_cart_item_price','modify_cart_product_price',10,3);

function modify_cart_product_price( $price, $cart_item, $cart_item_key){
  if($cart_item['my-price']!==0){
      $price =$cart_item['my-price'];
    }
    return $price;
    //exit;
}

Here individual price is getting correct , but total price is wrong


Solution

  • Updated (october 2021)

    For testing this successfully (and as I don't know how you make calculations), I have added a custom hidden field in product add to cart form with the following:

    // The hidden product custom field
    add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );
    function add_gift_wrap_field() {
        global $product;
        // The fake calculated price
        ?>
            <input type="hidden" id="my-price" name="my-price" value="115">
        <?php
    }
    

    When product is added to cart, this my-price custom field is also submitted (posted). To set this value in cart object I use the following function:

    add_filter( 'woocommerce_add_cart_item', 'custom_cart_item_prices', 20, 2 );
    function custom_cart_item_prices( $cart_item_data, $cart_item_key ) {
        // Get and set your price calculation
        if( isset( $_POST['my-price'] ) ){
            $cart_item_data['my-price'] = $_POST['my-price'];
    
            // Every add to cart action is set as a unique line item
            $cart_item_data['unique_key'] = md5( microtime().rand() );
        }
    
        return $cart_item_data;
    }
    

    Now to apply (set) the new calculated price my-price to the cart item, I use this last function:

    // For mini cart *(cart item displayed price)*
    add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
    function filter_cart_item_price( $price, $cart_item ) {
        if ( ! is_checkout() && isset($cart_item['my-price']) ) {
            $args = array( 'price' => floatval( $cart_item['my-price'] ) );
    
            if ( WC()->cart->display_prices_including_tax() ) {
                $product_price = wc_get_price_including_tax( $cart_item['data'], $args );
            } else {
                $product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
            }
            return wc_price( $product_price );
        }
        return $price;
    }
    
    add_action( 'woocommerce_before_calculate_totals', 'set_calculated_cart_item_price', 20, 1 );
    function set_calculated_cart_item_price( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item ){
            if( isset( $cart_item['my-price'] ) && ! empty( $cart_item['my-price'] ) || $cart_item['my-price'] != 0 ){
                // Set the calculated item price (if there is one)
                $cart_item['data']->set_price( $cart_item['my-price'] );
            }
        }
    }
    

    All code goes in function.php file of your active child theme (or active theme).

    Tested and works