The following guide is written for developers who want to add fees to the WooCommerce cart and would like to learn about how these fees interact with WooCommerce Subscriptions.
The guide explains how fees added to the cart act by default, and how they can be customized to be applied only to the initial order or recurring orders.
Understanding Cart Fees
Unlike cart items, cart fees are non-persistent, this means third-party plugins which add fees need to be constantly hooked into the cart calculations, adding their fees each time the cart totals are calculated.
To do that WooCommerce provides the woocommerce_cart_calculate_fees
hook, which third parties can use to add their fees.
For example, to add a $10 engraving fee to the cart, you could use the following code snippet:
add_filter( 'woocommerce_cart_calculate_fees', 'add_engraving_fees', 10, 1 ); function add_engraving_fees( $cart ) { $cart->add_fee( 'Engraving', '10' ); }
This fee will appear like this in the cart totals section of the cart page:
WooCommerce Subscriptions’ recurring carts use the same cart calculations and so the code snippet above also applies the fees to any recurring cart. That is to say, by default, any cart fees added using the woocommerce_cart_calculate_fees
hook will be applied both to both the initial order, and any subscriptions created for that transaction. Those fees are then also applied to subsequent transactions.
So for example, using the same code snippet above, customers purchasing subscriptions would see the following cart totals:
Recurring Only Fees
As mentioned above, by default, fees applied to the cart are applied to be the initial and recurring carts.
In some cases, you may require the fee to only apply to the on-going recurring payment for any subscriptions. To achieve this, you need to tweak the code snippet from above and add a condition to check whether the cart being passed into your callback is a recurring cart, or the standard WooCommerce cart.
Recurring carts have a $recurring_cart_key
property we can use to determine if the cart is a recurring cart.
For example:
add_filter( 'woocommerce_cart_calculate_fees', 'add_recurring_postage_fees', 10, 1 ); function add_recurring_postage_fees( $cart ) { if ( ! empty( $cart->recurring_cart_key ) ) { $cart->add_fee( 'Postage', 5 ); } }
Initial Order Only Fees
For situations where fees should only be charged on the initial order when the customer signs up, there are two options to add a fee only to the initial order:
Option 1: Invert check for recurring cart
add_filter( 'woocommerce_cart_calculate_fees', 'add_administration_fees', 10, 1 ); function add_administration_fees( $cart ) { if ( empty( $cart->recurring_cart_key ) ) { $cart->add_fee( 'Processing Fee', 2.5 ); } }
In this example, we’ve reversed the logic from the previous code example. This code now only applies fees to the initial purchase cart.
Option 2: Apply fee to global cart
add_filter( 'woocommerce_cart_calculate_fees', 'add_administration_fees', 10 ); function add_administration_fees() { WC()->cart->add_fee( 'Processing Fee', 2.5 ); }
In this example, we’re applying the fee to the global WooCommerce cart object. This is the default cart object and so only applies fees to the initial purchase.
The Recurring Fee Filter
WooCommerce Subscriptions 2.2.16 introduced the woocommerce_subscriptions_is_recurring_fee
filter. This filter allows developers who have applied fees to the initial cart to also apply the fees to the recurring cart.
For example, if the cart fees have been applied using WC()->cart->add_fee( 'Fee', '10' );
, you could use this filter to also apply it to all recurring carts.
By default, the return value of this filter is set to false
, so that all fees applied using WC()->cart
are non-recurring fees by default.
// All fees are recurring add_filter( 'woocommerce_subscriptions_is_recurring_fee', '__return_true' ); add_filter( 'woocommerce_cart_calculate_fees', 'add_fees', 10 ); function add_fees() { WC()->cart->add_fee( 'Fee', '10' ); }
If only certain fees are recurring or you would like to apply more complex conditions, you can use the $fee
and $cart
filter arguments.
For example:
add_filter( 'woocommerce_cart_calculate_fees', 'add_fees', 10 ); function add_fees() { WC()->cart->add_fee( 'Personal Engraving', 10 ); WC()->cart->add_fee( 'Postage', 5 ); } add_filter( 'woocommerce_subscriptions_is_recurring_fee', 'apply_recurring_fees', 10, 3 ); function apply_recurring_fees( $is_recurring, $fee, $cart ) { // Personal engraving fees should be charged on a recurring basis if ( 'personal-engraving' === $fee->id ) { $is_recurring = true; // Subscriptions with a recurring total less than $30 are required to pay on-going postage charges } elseif ( 'postage' === $fee->id && 30 > $cart->get_subtotal() ) { $is_recurring = true; } return $is_recurring; }