I’ve been trying to implement a discount in my store with the following code:
add_action('woocommerce_before_calculate_totals', 'set_discount', 10 ); function set_discount( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // Loop Through cart items foreach ( $cart->get_cart() as $cart_item ) { // 50% items discount $cart_item['data']->set_price( $cart_item['data']->get_price() / 2 ); } }
- The code works on the cart page, the discount is applied as it should
- The code works on the checkout page for a second or two, BUT when then the loading spinner has finalized the discount disappears and the original price is shown
It seems the set price is overwritten in the checkout by some standard AJAX request which reuses the original price, or something. I have tried using add_fee() with the same result, I have also tried deactivating all plugins (except woocommerce, of course) and I have tried switching to another theme – nothing works!
Using WordPress 5.0.3, Woocommerce 3.5.4, Child theme of Storefront 2.4.2
UPDATE: Added screenshots.
1) This is what should be shown on checkout, and is being shown for around 1-2 seconds:
2) This is what is shown once the loading spinner is finalized – the original prices:
Advertisement
Answer
The correct code to be used since Woocommerce 3.2+ avoiding problems and errors is:
add_action('woocommerce_before_calculate_totals', 'cart_item_discount', 10, 1 ); function cart_item_discount( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return; // Avoiding hook repetition (when using price calculations for example) if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return; // Loop Through cart items foreach ( $cart->get_cart() as $cart_item ) { $original_price = $cart_item['data']->get_price(); // Get original product price $discounted_price = $original_price / 2; // 50 % of discount $cart_item['data']->set_price( $discounted_price ); } }
Code goes in function.php file of your active child theme (or active theme). Tested and works (Tested on last versions: WordPress 5.0.x | Woocommerce 3.5.x | Storefront 2.4.x)
If it doesn’t work, it’s because some other things or customizations are interacting with it. You need first to check Woocommerce > Status for red items (where all overridden templates, at the end, need to be up to date).