Recently I was tasked with adding a field to the cash on delivery gateway in WooCommerce. They wanted a field they could put in a dollar amount that would be tacked on as a fee to orders using that gateway. Seemed simple enough with some googling but took a bit longer to tweak and get functioning correctly.
Add Field to Cash On Delivery Gateway
Adding fields in WooCommerce to its forms is pretty straight forward. You hook into the WC Settings API and adjust them using this hook:
add_filter( 'woocommerce_settings_api_form_fields_<id>', function( $form_fields ) { return $form_fields; } );
Replace <id> with the id of the form. In this case it’s “cod” for the Cash on Delivery form. In your hooked function you can manipulate the form fields array as needed. For my case I just needed to add a field at the end for a fee so I do this:
https://gist.github.com/ChrisFlannagan/bcfe4ea1cbfdcd629db7f292c22cc40c
Add Fee To The Order
Now that we have a fee set we need to hook into the checkout process. For this I use the action “woocommerce_checkout_create_order” to manipulate the order right before it’s saved. In WooCommerce 3.0 and over you no longer use the add_fee() function but instead create a line item fee object and add that to the order. Here’s how I did what I needed:
https://gist.github.com/ChrisFlannagan/ae68a43ec4b60ac741c95715e58dd001
SUPER IMPORTANT
Notice the add_item( $item ) call to place it in the order. If that’s all you do then you will see the fee on the order but the order total won’t include it. You need to make sure you run the order’s calculate_totals() function after adding the item.