Since WooCommerce 3+, the WC_Product get_price_including_tax()
is deprecated and has been replaced by the function wc_get_price_excluding_tax()
(not anymore a method).
You should not need any coupon code to make this kind of code working. As you are using them to fired this discount "Buy one Get one Free", I keep it on the function below.
What you have forgotten in your code is:
- to take care of quantities, when you are adding the product prices in your prices array.
- to get all necessary cheapest prices array, when there is multiple items, with different quantities.
The min()
php function will work only on one item, so it's not really appropriated.
So the correct code should be something like:
add_action('woocommerce_cart_calculate_fees', 'buy_one_get_one_free', 10, 1 );
function buy_one_get_one_free( $wc_cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$cart_item_count = $wc_cart->get_cart_contents_count();
if ( $cart_item_count < 2 ) return;
// Set HERE your coupon codes
$coupons_codes = array('2for1wow', 'anothercouponcode');
$discount = 0; // initializing
$matches = array_intersect( $coupons_codes, $wc_cart->get_applied_coupons() );
if( count($matches) == 0 ) return;
// Iterating through cart items
foreach ( $wc_cart->get_cart() as $key => $cart_item ) {
$qty = intval( $cart_item['quantity'] );
// Iterating through item quantities
for( $i = 0; $i < $qty; $i++ )
$items_prices[] = floatval( wc_get_price_excluding_tax( $cart_item['data'] ) );
}
asort($items_prices); // Sorting cheapest prices first
// Get the number of free items (detecting odd or even number of prices)
if( $cart_item_count % 2 == 0 ) $free_item_count = $cart_item_count / 2;
else $free_item_count = ($cart_item_count - 1) / 2;
// keeping only the cheapest free items prices in the array
$free_item_prices = array_slice($items_prices, 0, $free_item_count);
// summing prices for this free items
foreach( $free_item_prices as $key => $item_price )
$discount -= $item_price;
if( $discount != 0 ){
// The discount
$label = '"'.reset($matches).'" '.__("discount");
$wc_cart->add_fee( $label, number_format( $discount, 2 ), true, 'standard' );
# Note: Last argument in add_fee() method is related to applying the tax or not to the discount (true or false)
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works. You will get something like:

A coupon code (here 2for1wow
) need to be created with a zero price discount. When the coupon is applied to cart, a negative fee (a discount) is enabled and will free one item on two.
Similar answer: WooCommerce discount: buy one get one 50% off