21

I am trying to change product price in cart using the following function:

    add_action( 'woocommerce_before_shipping_calculator', 'add_custom_price' 
     );
      function add_custom_price( $cart_object ) {
         foreach ( $cart_object->cart_contents as $key => $value ) {
         $value['data']->price = 400;
        } 
     }

It was working correctly in WooCommerce version 2.6.x but not working anymore in version 3.0+

How can I make it work in WooCommerce Version 3.0+?

Thanks.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Archana
  • 337
  • 2
  • 4
  • 12
  • Possible duplicate of [woocommerce\_before\_calculate\_totals hook stopped working after update to WC 3.0.1](http://stackoverflow.com/questions/43285252/woocommerce-before-calculate-totals-hook-stopped-working-after-update-to-wc-3-0) – Never Stop Learning Apr 17 '17 at 09:04

2 Answers2

62

Update 2021 (Handling mini cart custom item price)

With WooCommerce version 3.0+ you need:

Here is the code:

// Set custom cart item price
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);
function add_custom_price( $cart ) {
    // This is necessary for WC 3.0+
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Avoiding hook repetition (when using price calculations for example | optional)
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item ) {
        $cart_item['data']->set_price( 40 );
    }
}

And for mini cart (update):

// Mini cart: Display custom price 
add_filter( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 3 );
function filter_cart_item_price( $price_html, $cart_item, $cart_item_key ) {

    if( isset( $cart_item['custom_price'] ) ) {
        $args = array( 'price' => 40 );

        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_html;
}

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

This code is tested and works (still works on WooCommerce 5.1.x).

Note: you can increase the hook priority from 20 to 1000 (or even 2000) when using some few specific plugins or others customizations.

Related:

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Hi, #LoicTheAztec this solution is working correctly for hard coded values but not working for dynamic values. – Archana Apr 11 '17 at 07:51
  • How can we make these values dynamic? – Asif Rao Nov 17 '17 at 12:04
  • @AsifRao What do you need exactly, could you be more spécific please? – LoicTheAztec Nov 17 '17 at 12:25
  • I want to add custom price for the product added in cart using add_to_cart(); so need the product_id and custom price that I have calculated. in this whook. how can I get these values in this hook. – Asif Rao Nov 17 '17 at 13:29
  • @AsifRao So sorry but this answer is not related to add_to_cart() functionality… you should need to ask a new question on StackOverFlow… – LoicTheAztec Nov 17 '17 at 13:35
1

With WooCommerce version 3.2.6, @LoicTheAztec's answer works for me if I increase the priority to 1000.

add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 1000, 1);

I tried priority values of 10,99 and 999 but the price and total in my cart did not change (even though I was able to confirm with get_price() that set_price() had actually set the price of the item.

I have a custom hook that adds a fee to my cart and I'm using a 3rd party plugin that adds product attributes. I suspect that these WooCommerce "add-ons" introduce delays that require me to delay my custom action.

Tony
  • 363
  • 2
  • 8
  • I'm using WC-Fields-Factory plugin version 2.0.6 to add custom product attributes. I grepped the plugin directory for 999 and found multiple instances in the plugin where the action priority is 999. I'm guessing that, in my case, this is why I needed a priority of 1000. – Tony Feb 16 '18 at 13:56