WooCommerce reviews + tutorials
Please note that this snippet will work for WooCommerce 2.0 and 2.1, but not 2.2+ – the order status structure has changed in version 2.2 to support refunds. If we post an updated version, we’ll link to it here when published.

WooCommerce virtual orders can be automatically marked as ‘completed’ after payment with a little bit of code added to a custom plugin, or your themes functions.php file. By default WooCommerce will mark virtual-downloadable orders as ‘completed’ after successful payment, which makes sense, but some store owners will want to be able to automatically mark even a virtual order as complete upon payment, for instance in the case of a site which takes donations where no further action is required. To do so, use the following code, which is based on the core virtual-downloadable completed order status:

add_filter( 'woocommerce_payment_complete_order_status', 'virtual_order_payment_complete_order_status', 10, 2 );

function virtual_order_payment_complete_order_status( $order_status, $order_id ) {
  $order = new WC_Order( $order_id );

  if ( 'processing' == $order_status &&
       ( 'on-hold' == $order->status || 'pending' == $order->status || 'failed' == $order->status ) ) {

    $virtual_order = null;

    if ( count( $order->get_items() ) > 0 ) {

      foreach( $order->get_items() as $item ) {

        if ( 'line_item' == $item['type'] ) {

          $_product = $order->get_product_from_item( $item );

          if ( ! $_product->is_virtual() ) {
            // once we've found one non-virtual product we know we're done, break out of the loop
            $virtual_order = false;
          } else {
            $virtual_order = true;

    // virtual order, mark as completed
    if ( $virtual_order ) {
      return 'completed';

  // non-virtual order, return original status
  return $order_status;

Note: This article has been updated to work with WooCommerce 2.0+ and the sample code above will no longer work with WC 1.6.6 and previous

We also have a convenient plugin available that can do this for you, which will continue to be updated even if this tip becomes irrelevant: WooCommerce Order Status Control.

Published by Justin Stern

Justin is one of our co-founders, and is our resident overengineer. He likes to write developer tutorials and make black magic happen in our plugins. He thinks that writing code is a lot easier than writing words.


  1. I am bookmarking this one — thanks again Justin.

  2. Thanks a lot for sharing, it’s exactly what I needed!

  3. Could it be that the code doesn’t work with the latest update? If so, do you have an idea what to change? Thanks in advance, Hendrik

    • Hey Hendrik, sorry to hear it’s not working for you. I just gave this solution a try in the most recent WooCommerce and it worked just fine for me, so not sure why it wouldn’t be working for you. One thing to note is that this will complete an order only if the entire order consists of virtual products.

  4. Thanks Justin,

    If I understand. I have to put the code in my “fonctions.php” of my “inspire-commerce theme” and that’s it?

    I sell a membership for the website so it’s not a physical product and not a downloadable product too. The orders status stay on “Processing” until I put the orders on “Complete”. So the customers can’t reach the membership content until I put the order on “Complete”.

    I hope this will fix my problem.


  5. Hi,

    I’ve pasted that code into my theme’s functions.php at the end, but before the ?>. I’ve set the product to Virtual and it’s still not auto-confirming the order?

    Great site, thanks in advance!

    • hmm, I just took another look at the relevant WooCommerce core code, and I can’t see anything that would cause this not to work. I’ve been unable to reproduce whatever the issue is, so I’m not able to determine why it would not work for you, it should just work assuming that the entire order consists of virtual products. I’m afraid you’d have to do a little debugging to track down the problem, if this is something you’re able to tackle, I do have an introduction to debugging WordPress which you can read through. You’d want to add some error_log() statements: first to make sure the virtual_order_payment_complete_order_status() is being called, and then to figure out whether it’s returning the correct status “completed” when you desired. Hope this helps

  6. Do you think I could use this for a regular product as well? I have a customer who never bothers going into their admin panel so the orders always sit as ‘processing’ and I would like them to automatically be marked as completed. I fairly new to WC so I am having some trouble figuring out how to do this.

    • Sure, that’s a simpler, more general case than what I did here. Get rid of the check for whether the order is virtual, and just return ‘completed’

      • So would that look like this?

        add_action( ‘woocommerce_payment_complete_order_status’, ‘virtual_order_payment_complete_order_status’, 10, 2 );

        function virtual_order_payment_complete_order_status( $order_status, $order_id ) {

        $order = new WC_Order( $order_id );

        if ( $order_status == ‘processing’ &&

        ( $order->status == ‘on-hold’ || $order->status == ‘pending’ || $order->status == ‘failed’ ) ) {

        $order = true;

        if ( count( $order->get_items() ) > 0 ) {

        foreach( $order->get_items() as $item ) {

        if ( $item[‘id’] > 0 ) {

        $_product = $order->get_product_from_item( $item );




        // virtual order, mark as completed

        if ( $order ) {

        return ‘completed’;




        • Well, no, the function should be even simpler, maybe something just like:

          function virtual_order_payment_complete_order_status( $order_status, $order_id ) {

          $order = new WC_Order( $order_id );

          if ( $order_status == 'processing' &&

          ( $order->status == 'on-hold' || $order->status == ‘pending’ || $order->status == ‘failed’ ) ) return 'completed';

          return $order_status;


          • Hi!
            For some reason, this code does not work for me. I can’t figure out why, as the original code (for virtual products only) did work just fine.
            Any ideas?

            Thank you!

          • Unfortunately I’m not sure why the code might cease to work for you. And, it still does work for “virtual products only”, so I don’t think that’s the issue

  7. Hi Justin,

    I had a question about your choice of conditionals….

    if ( $order_status == 'processing' &&

    ( $order->status == 'on-hold' || $order->status == 'pending' || $order->status == 'failed' ) )

    What is the point of checking that original $order->status ? Also, nitpicking, but shouldn’t it be add_filter()? Anyway, I appreciate your sharing this! Cheers!

    • Hey Kathy, thanks for pointing out my action/filter misstype, wordpress is so loose with that sort of thing that I think it still works anyways, but I do prefer using the correct one.

      As for checking the original order status, I based this function off of WC_Order::payment_complete(), and they make the same check there and so I maintained it.


      • Hi Justin,

        One more thing: I presume you are adding this to your theme’s functions.php?? I ask, because I’ve tried putting this in my plugin’s class and my function that is attached to ‘woocommerce_payment_complete_order_status’ never seems to fire.



  8. Hi Justin,

    Looks like you have another useful piece of code I want to use! I am trying to adapt this code so that any orders I get with the status ” On Hold” or “Pending” are updated to “Processing”.

    Simple I thought, but unfortunately I can’t get it to work. I have taken your code and changed it to this:

    function virtual_order_payment_complete_order_status( $order_status, $order_id ) {

    $order = new WC_Order( $order_id );

    if ( $order_status == 'on-hold' &&

    ( $order->status == 'pending' || $order->status == ‘failed’ ) ) return 'processing';

    return $order_status;


    Nothing changes on the backend with the above code. What am I doing wrong?

    Many thanks in advance for your help.


    • Hey Jaime, in this filter $order_status will be the status that the order is being set to, while $order->status will be the current (soon to be previous) order status. So to automatically set on-hold/pending orders to processing, you could simply try replacing your if statement with:

      if ( $order_status == 'on-hold' || $order_status == 'pending' ) return 'processing';

      Where here we don’t even care what the previous order status was, we’re just making all on-hold/pending status’ change to ‘processing’.

      • Hi Justin,

        Many thanks for the explanation. I understand where I went wrong now! I will give the new code a try and post back with my results.

        Little by little I am beginning to understand, it’s a slow process for me though!


        • OK, I tried the new code, but nothing seems to happen. I have placed a couple of orders and they are still at the “On Hold” status.

          Here’s my code below that I’m adding to the theme’s function.php file:

          function virtual_order_payment_complete_order_status( $order_status,

          $order_id ) {

          $order = new WC_Order( $order_id );

          if ( $order_status == 'on-hold' || $order_status == 'pending' )

          return 'processing';

          return $order_status;


          I also tried the same code without the return $order_status at the end:

          function virtual_order_payment_complete_order_status( $order_status,

          $order_id ) {

          $order = new WC_Order( $order_id );

          if ( $order_status == 'on-hold' || $order_status == 'pending' )

          return 'processing';


          Any ideas where I’m going wrong?

          Many thanks,


    • @Jamie, you may have forgotten the “add_filter” line:
      add_filter( ‘woocommerce_payment_complete_order_status’, ‘virtual_order_payment_complete_order_status’, 10, 2 );

  9. am using a theme called Bounce by ghostpool.com, am wanting to add this code to the theme functions… just trying to understand why the redirect is to


    Redirect to Theme Options after Activation

    Does this mean the user upon successful sale is redirected to the theme options page?

    • No, you’re probably talking about the WP Admin theme options page that can be displayed by certain themes when you activate them. This will have nothing to do with the thank-you page a customer sees after checking out

  10. Think I might be doing something wrong? Every time I put the code in my ‘functions.php’ it just makes the code appear at the top of my website for everyone to see.

  11. Great! worked perfectly for me 🙂 really nice work!!

  12. This process seems to have broken after an update to WooCommerce 2.0. It doesn’t seem to be passing $order_id. I’m digging under the hood now, but wanted to see if you have run in to this as well and if you had a solution.


    • Hey John, I just took a look at the WooCommerce code and it’s definitely still passing the order id; must be something else going on in your environment? Did you get this working?

    • Yes, I’m in the same boat as John. Marking orders as complete is no longer working for me. I’m still looking for a solution as this functionality was great to have. Doh!

      • Yeah, sorry about this, this was long overdue, I’ve updated the sample code to be WooCommerce 2.0+ compatible (and no longer compatible with WC 1.6.6 and earlier)

  13. Also not working for me on WooCommerce 2.0. In my case I use payment method “COD” as its a free download, I just want them to go through the checkout process and get download immediately. It’s Virtual and Downloadable order. The order remains in status “On Hold”. Should I perhaps try another payment method like Bank Transfer?

    • Hey Marc, my code will only work for a payment gateway that processes payment. You’d need a different implementation to make this work with one of the “fake” gateways like COD or bank transfer

  14. Hello there,

    Im trying to get your code to work for me. im using variables products though, so i cant seem to get this to work?

    Thanks in advanges

    • Hey Mark, I have updated the code to be WC 2.0 compatible, and tested with a variable virtual product and it is now working. Cheers!

  15. Hi Justin,

    I have applied this a while ago and it worked great until today. I haven’t updated the woocommerce plugin but i have updated the Follow Up Emails for woocommerce plugin because welcome emails were not going out, could this have effected it?

    If not, how would I go about diagnosing why it is not working.

    Thanks again!

    • Hey, it definitely was broken for WC 2.0, I know you said you didn’t upgrade, but I guess I’d recommend upgrading now if you haven’t already and then trying out the updated code that I just posted

  16. Hi Justin,

    I recently upgraded to WC 2.0 and have found that this function has stopped working as before. All my orders (virtual or not) are being marked as completed now. I have looked at the code and can’t see any obvious reasons why this has stopped working. (FYI, this seems to be impacting variable products.)

    Any help would be really appreciated.




  17. THANK YOU kind sir. I was able to easily modify this code to work for my specific needs.

    I used the same hook to submit data to a CRM to manage my customers better.

    Thanks again!

  18. Hope you can give me an idea on where to start troubleshooting this — the code works – virtual orders are being marked as complete.

    However, I’m testing a Simple product which is *not* marked as virtual, and it too is being marked complete upon successful purchase. Hrm.

    If I remove the code, then virtual products and simple products return to default functionality, and show up as pending.

    Any idea on where to start looking?

    Somehow the code is returning that all purchase are virtual no matter what.

    I can’t see where I can put in another conditional to bail out of the script if the product is not virtual… as that test is already right there.

    Stumped. I’ve checked and double checked that the product is just a regular old physical product, no downloads no nothing — shipping rates show up, tax shows up… ????

  19. Face –> Palm.

    Just read the last comment before the one I posted and see that I had old version of the code from somewhere else.

    New version = working.

    Thank you !!!

    • ha ha ok cool, I just tested the code in my dev environment and it worked fine so I was about to ask whether you had the latest. You beat me to it!

  20. Will this help fix my issue?, I can seem to go through the whole process of adding a virtual product…in my case a mp3 file, but it wont show the download links on the order page or even in the email woocommerce sends out. I managed to get it working for a pretend user I created but I had to manually go in as admin to the order page and grant access to that file (product) so it shows up under the “My Account” page when I log back in as a user. I am very confused. I have been searching google and ended up here. any help would be great!

    I think it’s basically not auto approving it somehow. I am just paying myself between 2 of my pay pal accounts and the transactions are working. Just the available download links are not working.

    Many thanks.


    • Hey Jeramiah, sounds like the orders aren’t being completed properly. You’ll want to make sure PayPal is sending the payment notifications correctly by looking at the order notes for the order. If you don’t see “PayPal IPN Completed”, then you’ll need to look into that.

  21. Hi There,

    This looks to be the code i’m after but nothing happens… I have setup my WooCommerce product to be virtual and downloadable and when the i complete the order with the default “Direct Bank Transfer” as admin the order stays on-hold and not completed.

    WooCommerce looks great for a membership site offering digital files, but really a must have is being able to auto approve customers rather them having to wait to get manually approved to have access to the files.

    I’m updated to WooCommerce 2.0.10.

    Would love to get this working 😉

    • Hey Matt, “Direct Bank Transfer” changes the order status to ‘on-hold’, which doesn’t indicate to WooCommerce that payment is complete for the order. You can add a bit of code to automatically complete orders paid for with “direct bank transfer”, but you then run into the issue of people submitting fake orders in order to get immediate access.

  22. Hey is there anyway to do it without a hook?

    simply by order id?….because the action im taking is outside of woocommerce

    i simply want to place inside of my existing function this order id update to completed

    i thought of doing it just through update_post_meta but i was scared the completed email wouldnt fire off

    • Sure, if you have an order ID you can complete the order like this:

      $order = new WC_Order( $order_id );


  23. Hi Justin,

    Brilliant! … works perfectly …. I’m using it with The Events Calendar & WooTickets … It would be great if I could get “Virtual” to be the default setting on every product… Any thoughts??

    Thanks again!

  24. Hi Justin,

    I’ve placed the conde on the functions.php, right after the opening php line, the product is marked as virtual and downloable but the orders holds on pending and no automatic status chage are made >,< (WC 2.0.10)

    • This code only works for orders that payment has been received for, so if it’s pending it won’t change the order status. If you’re using PayPal, make sure that IPN is working and orders being correctly moved into the “processing” status first 🙂

  25. Note for those (like me) who tried this code solution and saw no results: if you’re not calling the add_filter() soon enough, it won’t kick in. I’m using a child theme, and so had to make sure I placed

    add_filter( ‘woocommerce_payment_complete_order_status’, ‘virtual_order_payment_complete_order_status’, 10, 2 );

    in the action hook “after_setup_theme”. Then it worked perfectly! Even paypal standard worked quickly, and my virtual orders are auto-completing (without having to be “downloads” too)

  26. Hello

    I’m trying a simple thing but no success. I just want to skip whole “pending” and “on-hold” status. I want that all orders after they are payed go automatically to “processing” status so user receives email notification.

    Could you please put whole code for this, since many of us are just beginning to learn php, so this simple task is not so simple for us 🙂

    This is what I came up with help of this thread, but it’s doesn’t work.

    /*Order status*/
    function global_pending( $order_status, $order_id ) {

    $order = new WC_Order( $order_id );

    if ( $order_status == ‘on-hold’ || $order_status == ‘pending’ ) return ‘processing’;

    return $order_status;

    add_filter( ‘woocommerce_payment_pending_order_status’, ‘global_pending’);

    • That filter you’re using doesn’t exist 🙂 The code above only works for orders that have received payment, so if you’re using something like PayPal, make sure that IPN’s are working correctly and orders are being moved into the “processing” status first.

  27. Thank you for sharing your solution. It perfectly works on my site!

  28. Thanks ! this code worked for me .

  29. Hello,

    Thanks for sharing that code, it’s very useful!
    Is there a compatibility issue between this code and the Follow Up Emails for Woocommerce plugin? Looks like none of the auto emails are triggered when using this code (triggers based on status=complete)? Would the plug-in you sell work better?

    Thanks. Olivier

    • Hey Olivier, unfortunately there is a bug with the Follow Up Emails plugin that prevents it from working correctly when order statuses are changed directly from pending to completed — you’ll want to submit a support ticket on http://support.woothemes.com so they can let the Follow Up Emails dev know 🙂

  30. Hey there
    Is there a way to auto select/default the virtual checkbox as I am using wp user frontend to load products and need both virtual and downloadable checkboxes to be automatically selected?

    Please help!

    • Well anything’s possible, but I’m actually not familiar with WP User Frontend. Perhaps someone else out there has an idea?

  31. Hello Justin,

    I am using downloadable products for my site with woocommerce, and i want order becomes auto complete after users payment and redirect orders received with downloadable link. i am doing this thing manually in orders with change the status “Completed”. after that user got the mail of order received with downloadable link. i want to do this automatically. Thanks

    • If your orders are already being marked as “processing” you can set the option under WooCommerce > Settings > General > “Grand Access to downloadable products after payment” which should work for you.

  32. Hmm unfortunately, it is not working on my site… I have the WooCommerce combined with Wootickets (for The Events Calendar), and as a payment gateway I am using Sisow IDEAL (in test mode). Any idea what could be the problem?

    Would be great if there would be a way to autocomplete the order. Right now my wordpress is not even sending out a notification of a new order, because of the status ‘pending’. Would be perfect if it could at least move from pending to processing without my help. Could this be because of the test environment maybe? or the maintenance mode my site is in?

    • This code will only work if your payment gateway is marking the order as payment completed first. The Mollie gateway relies on a payment notification that your site must process first, so I’d check to make sure orders are being marked as “processing” — if they always show as “pending”, then that’s your issue 🙂 It could be because of a test environment, especially if it’s local to your computer or is otherwise prevented from receiving the notification from Mollie’s servers.

  33. I’m using WooCommerce to process orders of non-virtual products that will later be invoiced, so no PayPal, and therefore no way to automatically mark the orders as payment completed. I’m using the “cash on delivery” option to receive payment. Is there a way I can get the payment to mark as completed automatically so I can use the bit of code Justin posted on 12 October 2012 to mark orders as complete? (The people handling invoices will have nothing to do with the website aside from getting emails indicating that the order has been placed, but I want the “order again” feature on previous orders to work.)

    PS – I’m good and copying and pasting, but know pretty much no PHP. 🙂

    • Hello,

      I have the same problem than Marlies. I have the WooCommerce combined with Wootickets (for The Events Calendar) and I would like to process just those tickets, so I use your code changing the type of the item from ‘line’ to ‘tribe_wooticket’. Anyway, it’s not working and it has the same effect if I comment the line with the “add_filter” code.

      add_filter( ‘woocommerce_payment_complete_order_status’, ‘virtual_order_payment_complete_order_status’, 10, 2 );
      function virtual_order_payment_complete_order_status( $order_status, $order_id ) {
      $order = new WC_Order( $order_id );

      if ( ‘processing’ == $order_status && ( ‘on-hold’ == $order->status || ‘pending’ == $order->status || ‘failed’ == $order->status ) )
      $virtual_order = null;

      if ( count( $order->get_items() ) > 0 )
      foreach( $order->get_items() as $item )
      if ( ‘tribe_wooticket’ == $item[‘type’] )
      $_product = $order->get_product_from_item( $item );

      if ( ! $_product->is_virtual() )
      // once we’ve found one non-virtual product we know we’re done, break out of the loop
      $virtual_order = false;
      $virtual_order = true;

      // virtual order, mark as completed
      if ( $virtual_order ) {
      return ‘completed’;

      // non-virtual order, return original status
      return $order_status;

      I’m using a free product, so there’s no payment. Can that be the source of the problem?


  34. Hi,
    I would like to do it the opposite way. Currently and order are mark as “Processing” when a payment is done. I wan’t it to be marked as “Pending”. Is it possible?

    • Hey Lars, it can be done but would require some custom coding, something like the following in your theme’s functions.php, which should always set the order status to ‘pending’ after payment is complete:

      add_filter( 'woocommerce_payment_complete_order_status', 'woocommerce_payment_complete_order_status_pending', 10, 2 );
      function woocommerce_payment_complete_order_status_pending( $new_order_status, $order_id ) {
      return 'pending';

      Just note that WooCommerce defines the “pending” status as “order received (unpaid)”, so just be certain this makes sense for your business processes.

  35. You guys rock, this is the exact code I needed on a member association site for a client.

  36. i add the code to my themes function.php file and it brings down the whole site. the message i get is:

    Internal Server Error
    The server encountered an internal error or misconfiguration and was unable to complete your request.
    Please contact the server administrator, cgiadmin@yourhostingaccount.com and inform them of the time the error occurred, and anything you might have done that may have caused the error.
    More information about this error may be available in the server error log.
    Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.

    i am using the wordpress theme flexform. any idea what i am doing wrong?

    • No, really not sure, this code has been verified to work on numerous systems, and the nature of PHP is that if it works in one environment it will work in another, so I’d have to think the change was some coincidence, or something else was going on. I know it’s been a while, but I hope you got this resolved anyhow!

  37. Why in the world talk about changing the status from another status and no one says anything about change of status from a client action? Example: After the purchase the customer must approve an image by clicking a button of “approved” and automatically change the status?? Is it very difficult?

    • Nope, it’s certainly easy enough to change the status of an order programmatically, be that from a client action like you’ve described, or otherwise. The WC_Order object defines a method update_status() which can be used to update the status of an order like so: $order->update_status( 'completed' );

  38. Hi, thanks for sharing your code! I will try it right now but I have a doubt: will your code work with downloadable products (free products) ? Thanks man!

    • Hi, there’s a setting (I think under WooCommerce > Settings > General) to complete an order once a downloadable product is purchased, so you won’t even need to use this code for that 🙂

      • Beka,

        There is only this setting

        Grant access to downloadable products after payment
        Enable this option to grant access to downloads when orders are “processing”, rather than “completed”.

        This code makes transactions completed for virtual products, since if the box is checked for the option you mentioned, the admin will still have to mark the order as completed but when the code is used, that extra step is no longer necessary.

  39. Hi, I tried the function.php hook and it works fine, thanks but:
    Is that possible to also force sending the completed order e-mail to the customer ?
    i’m selling a virtual product which usage is described into the completed order e-mail (template override to display customized information).

    • Actually the completed order email *should* be sent to the customer when the status is changed. If it’s not happening, there’s probably some other issue at play

  40. What if product is not virtual? that product have shipping and tax what you advice to add in this code

    • This code simply shows an approach to marking virtual orders automatically as “complete”. It certainly could be adapted to perform in other cases, it all depends on what you’re trying to do

  41. Thanks for this. It works as expected, however, how can I make sure all other actions from other plugins fire when triggered by autocompletion? Is there a woocommerce hook/action that is supposed to fire when the order is manually completed (by hitting the button, for instance.)?

    I have another plugin that is triggered by completion to trade data with another system. It does not seems to fire when autocompletion occurs.

    Thanks very much!

    • You’d have to find out which hook the plugin is using, as this set of code should trigger the same actions that would normally be run when a gateway completes an order.

  42. Thanks for this code. I have it up and working. I’m wondering if this functionality could be moved into a homemade extension. I tried that first and my website didn’t seem to like it so I deleted the homemade extension and put the code into the functions.php file. I’d rather not have to edit a theme related file so a homemade extension would be ideal.

  43. Hi there thx for the great solution but i need something else related to this. I need this solution to works for all orders that are made and paid by PayPal and other gateways. I also want to be able to manualy process and complete the orders that are made using bank transfer or pay by cheque? What do i need to change ?


    • Hi there, the code provided should work just as you’ve described, as it won’t autocomplete orders via check, bank transfer, or manual gateways.

  44. Thank you very much! This is a very useful article.

  45. I am designing a meal plan website and I can’t seem to figure out how to get orders that have used a 100% off coupon to have the order autocomplete. It doesn’t seem to be working when the price they pay is $0. any ideas?

    • Hey there, since free orders don’t use your payment gateway, the order will go straight to processing for anything with a $0 cost. You’d need some custom code specific to free orders to get this to work.

  46. I’ve been trying to use this function but it seems that when trying to make payment via paypal, WooCommerce is not doing the payment_complete function. I’ve tried to fiddle with the checkout class to confirm this.

  47. Hi

    I get this error message after copying the code to my functions file:

    Fatal error: Cannot redeclare virtual_order_payment_complete_order_status() in /public_html/wp-content/themes/retail-therapy/functions.php on line 34

    Maybe I should just buy the plugin, but do you know what I am doing wrong? 🙂

    • Sounds like code may have gotten duplicated – make sure there’s only one function virtual_order_payment_complete_order_status() as you may have pasted twice.

  48. Hi Justin, would this code work in a site functionality plugin? I have this snippet in a plugin in my mu-plugins directory but it doesn’t work. It works though when it’s in functions.php

  49. Hi, i am having an entirely different problem here. For some reason all our orders are marked as completed automatically without us making any changes at all? We are trying to make it default to processing but it wouldnt. We are selling physical goods and have not ticked virtual goods on our products. We cant for our life figure out why its doing that. We have not added any codes anywhere or plugins that would lead to this. Wondering if you can help?

  50. just reviewing my problem. we are selling physical goods. by default which im not sure why its marking all our orders completed when we dont want to as we need to dispatch it. Did not install any plugins, write any codes or tick the virtual goods checkbox. So we are unsure of why this is happening. Tried using the codes above and it worked by replacing the complete status with processing. However its causing issues in terms of triggering email notifications.

    This is what we are after:
    Processing>Manually Complete – This sends out 2 emails, one order confirmation and another dispatch/completion email.

    Right now this is happening:
    AutoComplete>AutoProcessing>Manually Complete – This sends out 1 email, order confirmation. Whenw e tick the complete order, it does not send out email anymore.

    Can you please advise how we can fix this?

    • Hey James, the scenario you’re after is how WooCommerce works by default. You should remove any code present, as only virtual orders are completed by default. Physical orders are set to processing and manually completed (typically when shipped). Try setting up a staging environment with a default theme and deactivating all plugins except WooCommerce, then place a test order. You should see this workflow. You can then re-enable one-by-one to see if a plugin or some code in your theme’s functions.php is at fault.

  51. Hello,

    I realize this is an old article, but I hope you still read this.

    The code works perfectly. But there is one small issue with causes an error on my website.
    This code bypasses the ”processing” status.

    Is it possible to, instead of going from ”pending payment -> completed” go from ”pending payment -> processing -> completed” automatically once payment is received?

  52. Hi guys!
    Thanks for your great snippet!
    I have a question, though: is it possible to make order status as complete by adding a custom field within the order? I’m thinking about the tracking code. I need to flag order as complete only as soon as my carrier has taken the purchased items.
    What do you think about?
    Thanks in advance for your help.

  53. Thanks for providing the snippet. Unfortunately it’s not working in my child theme functions.php… virtual orders don’t autocomplete. : (

  54. Thank you so much for this useful code! I really needed the orders to autocomplete and didn’t know how to do it. You have saved my life 🙂

    Thank you!!

  55. This is awesome. I have a custom variation in which I want to auto complete all orders except for those which are reduced to zero cost, as I need to be able to vet those orders. Is there a way to make the above possible but only for orders which cost > 0 ?

  56. hello,
    I have a problem,my oder is going to pending but payment process is completed.I want its going to completed process not in pending there is any option not manualy in beckend.How i complete my process ,please revert me as soon as possible.

  57. Is there a way to do this to “on-hold” orders? We would really like all of our orders to automatically list as “completed” (even the invoice options). Is there a way to do this?

  58. Hi Justin,

    Any new updates for the latest version or woocommerce? The hook doesn’t work even you will only do something like this:

    add_filter( ‘woocommerce_payment_complete_order_status’, ‘virtual_order_payment_complete_order_status’, 10, 2 );

    function virtual_order_payment_complete_order_status( $order_status, $order_id ) {
    $order = new WC_Order( $order_id );
    return ‘completed’;

    …any idea why it doesn’t changed the order status?

    Thank you!

Comments are closed.

Error: Please enter a valid email address

Error: Invalid email

Error: Please enter your first name

Error: Please enter your last name

Error: Please enter a username

Error: Please enter a password

Error: Please confirm your password

Error: Password and password confirmation do not match