WooCommerce offers a refund option right from the order edit screen. But what if you need to process WooCommerce refunds automatically through code? In this tutorial, we will create the code that will be able to process refunds for a single order.

WooCommerce Refunds

WooCommerce refunds can be created using their own API function wc_create_refund. Let’s first understand what we can pass to that function.

There are 7 arguments that we can pass in an array to that function:

  • amount – The amount to be refunded
  • reason – Reason of the refund
  • order_id – ID of the order we want to refund
  • refund_id – ID of the refund we want to use again and retry
  • line_items – Array of line items which we want to refund from the order
  • refund_payment – Boolean. If true, the refund process will also try to refund the payment through the payment gateway
  • restock_items – If true, it will restock the items back by the quantity of each line item that we have refunded

Line Items

The array of line items will contain various information. Each array item will have the item’s ID as the array key.

Each item that has been assigned to the array by the key, will have:

  • qty – Quantity
  • refund_total – Total amount to be refunded for that item
  • refund_tax – Tax to be refunded

Function to Process WooCommerce Refunds

We will now start creating our own function. This function will receive the Order ID and the refund reason.

In this function we are getting the order by using the function wc_get_order. Then we are checking if the order is of type WC_Order. If it’s not, then we have received a different type of WooCommerce Order which can be something like WC_Order_Refund. We don’t want that.

We also don’t want to refund an order that has already been refunded, so we check for its status. If everything is correct, then we are getting the order items for which we will process the refund. We also define the variable to hold our refund amount and one for the line items.

Getting the Line Items

We will check if we have any order items, and if we do, we will save those line items.

For each line item, we are getting the tax data to calculate the tax refund. We also calculate the refund amount for that line item and sum it up with the current refund amount.

After that, we add all that information to the array of line items.

Creating the Refund

We have everything we need now and we just need to create the refund.

We are passing all our information into an array, with the arguments mentioned at the beginning of this tutorial.

Conclusion

By using the WooCommerce API we can do a lot of stuff automatically. In this tutorial, we got introduced with the WooCommerce refunds and how to create them using the WooCommerce API.

Have you ever had to process refunds? Would you like to process them automatically on some events such as failed products?

If you are a developer who wants to learn more about WooCommerce, check out my eBook:

Book WooCommerce for Developer to buy

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

11 Comments

  1. Hi

    Does Woo commerce provide any hook or filter when refund is done through admin panel ?

    Reply

    1. You can only hook into 'wp_ajax_woocommerce_refund_line_items' since that one is done when processing refund through admin panel. But that is not something that would provide you with refund information. You could maybe try and create a hook (inside the previous one) such as a simple do_action('processing_refund_admin_panel') before the refund is processed. After that, you can hook into the wc_create_refund actions (check which exist there) and when check in your function if( did_action('processing_refund_admin_panel') ){}. You could maybe be sure that this refund is processed through the admin panel. I haven’t tried this yet, but you can try and see if it works.

      Reply

  2. Very helpful post Igor. Many thanks. Where does the $item_meta variable come from?

    Reply

    1. Hi Drake, sorry about that. I’ve added a new line above to show how the item meta is retrieved.

      Reply

      1. Nice work Igor! Many thanks…

        Reply

  3. I am curious about the $refund_tax value. It never seems to be created because $tax_data[0] is never an array. $tax_data is an array but not the first element. Is that the correct way to get the $refund_tax value? It is always set to 0 for me even when I do have taxes that need to be refunded.

    Reply

  4. Hello Igor,

    thanks for this example code. I have a bit of the same problem. The tax never seems to be refunded, even though in the $line_items it is set.

    I have altered your code a bit, since it seemed $tax_data, as Nick says, didn’t always contain the right info.

    The tax_data is now present in the $line_items and is passed to the function, but it doesn’t appear on the refund.

    Maybe anyone has an idea why?

    Also, I can’t seem to find how to return shipping. Hopefully you, or anyone here, has experience wit that?

    Regards,

    Mark

    Reply

  5. Hello Igor,
    Does the wc_create_refund() supposed to automatically change order status to ‘wc-refunded’ ?
    I used your function but the action wc_create_refund() does nothing on my order i can not see any refund and status is not changing.

    Reply

  6. I just added :
    $order->update_status(‘wc-refunded’, ‘order has been refunded’);
    in your function before return $refund;
    now it works but it’s weird because this only line of code seems to do the job itself (even if i comment the call of wc_create_refund) and i can see the total refund amount in the order..

    Reply

    1. Hi Tedd, the WooCommerce function wc_create_refund will set the order status to wc-refunded only if it was possible to refund the order. You can always directly set the Order status to ‘wc-refunded’ with update_status, similar to how you would do manually through the admin area. But that does not mean that the order was actually refunded through the Gateway that was used to pay for that Order.

      You can check the code of that function here https://docs.woocommerce.com/wc-apidocs/source-function-wc_create_refund.html#469 and you’ll see that the function will set the status only if it was fully refunded.

      Reply

  7. Thanks a lot Igor !
    in fact i had set the ‘refund_payment’ to true , but i didn’t have any payment gateway for now.
    It worked changing refund_payment to false for my case

    Reply

Leave a reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.