Woo Dev Patch – Add Custom Fees to WooCommerce Checkout

Need to add a fixed fee to each cart at Checkout? Do you want to restrict the fees based on country of delivery or maybe based on the category of products in the Cart? I’m sharing some snippets below that will help you achieve the same without a lot of fuss.

The hook that we need to use is woocommerce_cart_calculate_fees. Please note this is a server side hook.

Add fixed fees to the Cart

function wc_add_custom_fees() {

	if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
		return;
	}
		
	// Add 1% of the subtotal + shipping as fee.
	$cart_content_total = WC()->cart->get_cart_contents_total();
	$shipping_total     = WC()->cart->get_shipping_total();
	$percentage         = 0.1;
	$custom_fee         = ( $cart_content_total + $shipping_total ) * $percentage;
	WC()->cart->add_fee( 'Custom Fee', $custom_fee, true, '' );
}
add_action( 'woocommerce_cart_calculate_fees', 'wc_add_custom_fees' );

In case if you wish to add a fixed fee amount, you can enter the amount directly.

Add fees based on Shipping Country

In this example, we will charge a delivery fee if the shipping country is any place other than US.

function wc_add_delivery_fee() {

	if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
		return;
	}

	$country = array( 'US' );

	if ( ! in_array( WC()->checkout->get_value( 'shipping_country' ), $country ) ) {
		$delivery_fee = 50;
		WC()->cart->add_fee( 'Delivery Fee', $surcharge, true, '' );
	} else {
		$fees = WC()->cart->get_fees();
		foreach ( $fees as $key => $fee ) {
			if ( 'Delivery Fee' === $fees[ $key ]->name ) {
				unset( $fees[ $key ] );
			}
		}
		WC()->cart->fees_api()->set_fees( $fees );
	}
}
add_action( 'woocommerce_cart_calculate_fees', 'wc_add_delivery_fee' );

Add fees based on product category

In the snippet below we will add fees to the cart if any item in the cart belongs to the ‘accessories’ category. Note that I’m comparing the category slug to ensure the category is matched correctly.

function wc_add_category_fee() {

	if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
		return;
	}

	$cart_items = WC()->cart->get_cart();
	$category_match = false;
	foreach ( $cart_items as $item_key => $item ) {
		$product_id = $item['product_id'];

		$terms = get_the_terms( $product_id, 'product_cat' );

		if ( is_array( $terms ) && count( $terms ) > 0 ) {
			foreach ( $terms as $cat_details ) {
				if ( 'accessories' === $cat_details->slug ) {
					$category_match = true;
					break;
				}
			}
		}
	}

	if ( $category_match ) {
		WC()->cart->add_fee( 'Custom Fee', 10, true, '' );
	} else {
		$fees = WC()->cart->get_fees();
		foreach ( $fees as $key => $fee ) {
			if ( 'Custom Fee' === $fees[ $key ]->name ) {
				unset( $fees[ $key ] );
			}
		}
		WC()->cart->fees_api()->set_fees( $fees );
	}
}
add_action( 'woocommerce_cart_calculate_fees', 'wc_add_category_fee' );

These snippets work fine with legacy Cart and Checkout pages as well as blocks based Cart and Checkout pages. Since this a server side hook, the changes will be reflected only on page load.

If you have any question, please feel free to ask in the comments section below.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top