I've set up my shop so that I am able to create an entire order programmatically. Line items register fine. However, I can't get fees to stick through the ordering process. I'm using the following code:

$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$fee = 'machine_name_of_fee';
commerce_fees_apply($order_wrapper, $fee, 500, 'USD');

I then push the order through to checkout so that I can manage it on the backend:

commerce_order_status_update($order, 'checkout_checkout');

I get no errors, but when I check the order in the admin backend, there are no fees that show up. I've double checked that the machine name is correct, and have even confirmed that the commerce fees module returns as 'empty' if the machine name doesn't exist. This leads me to believe that the fees are indeed being added, but that they are being removed at some point after a checkout stage. Is there a specific stage where fees have to be added in order to stick to and affect the order total? Am I implementing commerce_fees_apply() incorrectly?

2 Answers 2


You need to apply commerce fees after "checkout_checkout" status and also move order to next status i assume "checkout_review".

commerce_fees_apply() is a rule callback and you are calling it directly from your code.This function first removes all fee type line item and then adds add the same and expects values from rules config.

I tried this and it worked.

$order = commerce_order_load(3);
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$fee = 'test';
commerce_fees_apply($order_wrapper, $fee, 500, 'USD');
commerce_order_status_update($order, 'checkout_review');

But curious to know why you are writing code for this.You can easily achieve this using rules.

  • thanks so much. after implementing your code, it appears that it is adding a line item, but then somewhere it's being deleted. Can't figure out why or where. To follow the path, I dsm'ed every stage of the process in the commerce_fees module. This told me that a new line item was being created (line item 30462, according to the dsm output). But when I look at my database, the line items stop at 30461. See this link for screenshots of what I'm talking about: link . Can't figure out why it's not sticking?? Any ideas?
    – sakeferret
    Apr 26, 2016 at 3:03
  • ...and I forgot to answer your question. My client has a super complex set of products who's pricing varies based on around 10 to 15 different variables, all set by the customer. So i've created a custom order form that allows incoming orders to, not only have accurate prices, but to have consistent descriptions that allow for the production team to easily parse and move the products through the pipeline. So when an admin needs to adjust an order, i load the order back into the order form (reading all line items and fees) and then allow an admin to resave that order with any needed adjustments
    – sakeferret
    Apr 26, 2016 at 13:18
function commerce_fees_commerce_cart_order_refresh($order_wrapper) {
$line_item_ids = array();

foreach ($order_wrapper->commerce_line_items as $delta =>   $line_item_wrapper) {
// If the line item is a fee remove it.
if ($line_item_wrapper->getBundle() == 'fee') {
  // Delete the line item, and remove it from the order.
  $line_item_ids[] = $line_item_wrapper->line_item_id->value();


// If we found any fee type line items...
if (!empty($line_item_ids)) {
// Then delete the line items.

rules_invoke_event('commerce_fees_order', $order_wrapper);

This code is responsible for removing fee type line item on page refresh.So hook_commerce_cart_order_refresh is called on every page load and commerce fees module is using this hook to remove all existing fees attached to an order and applying the same using rules_invoke_event function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.