/**
* Adds cart fees based on the product's category.
*
* @see https://wpcodebook.com/cart-fees-product-category-woocommerce-php/
* @see https://github.com/woocommerce/woocommerce/blob/8.0.1/plugins/woocommerce/includes/class-wc-cart.php#L1893
* @see https://github.com/woocommerce/woocommerce/blob/8.0.1/plugins/woocommerce/includes/class-wc-cart.php#L1919
* @see https://github.com/woocommerce/woocommerce/blob/8.0.1/plugins/woocommerce/includes/class-wc-cart.php#L597
* @see https://github.com/woocommerce/woocommerce/blob/8.0.1/plugins/woocommerce/includes/abstracts/abstract-wc-product.php
* @see https://developer.wordpress.org/reference/functions/get_term_by/
*/
add_action( 'woocommerce_cart_calculate_fees', function ( $cart ) {
// Set your fees here, in `category slug` => `fee amount` format
$fee_amounts = array(
'shirts' => 10.50,
'jackets' => 12.50,
'accessories' => 15.00,
);
// Prepare fees
$fees = array();
foreach ( $cart->get_cart() as $cart_item_key => $values ) {
if ( is_a( $values['data'], 'WC_Product' ) ) {
$product = $values['data'];
// Get product categories
$category_ids = $product->get_category_ids();
if (
empty( $category_ids ) &&
0 != ( $parent_id = $product->get_parent_id() ) &&
( $parent_product = wc_get_product( $parent_id ) )
) {
$category_ids = $parent_product->get_category_ids();
}
// Product categories loop
foreach ( $category_ids as $category_id ) {
if (
( $term = get_term_by( 'term_id', $category_id, 'product_cat' ) ) &&
! empty( $fee_amounts[ $term->slug ] )
) {
$name = sprintf( esc_html__( '%s fee (%s)' ), $product->get_name(), $term->name );
if ( ! isset( $fees[ $name ] ) ) {
$fees[ $name ] = 0;
}
$fees[ $name ] += ( $fee_amounts[ $term->slug ] * $values['quantity'] );
}
}
}
}
// Add fees
if ( ! empty( $fees ) ) {
foreach ( $fees as $name => $amount ) {
/**
* - WooCommerce sorts fees by amount (see the `woocommerce_sort_fees_callback` filter).
* - Last two params are `taxable` and `tax_class`.
*/
$cart->add_fee( $name, $amount, true, '' );
}
}
} );