woocommerce / woocommerce

A customizable, open-source ecommerce platform built on WordPress. Build any commerce solution you can imagine.
https://woocommerce.com
9.3k stars 10.74k forks source link

woocommerce_order_status_completed doesn't fire #15969

Closed patchcad closed 7 years ago

patchcad commented 7 years ago

Prerequisites

Expected behavior and actual behavior

I sell software on my website and have written some code that's been working for months which automates the licensing process. When an order is placed and is paid for, woocommerce_payment_complete_order_status fires a function which converts the order into a completed one and normally woocommerce_order_status_completed would fire also which would then generate a license and WC would send a New Order email to me.

Since updating to WC version 3.1, woocommerce_order_status_completed stopped firing when an order has been converted to completed and no New Order email is being sent. I can send it manually by going to the order page and actioning a "Resent Completed order" command.

Like I said, this was working perfectly and untouched for months now until this update :(

Any advise and help is very very appreciated!

Environment

``` ### WordPress Environment ### Home URL: http://www.patchcad.com Site URL: http://www.patchcad.com WC Version: 3.1.0 Log Directory Writable: ✔ WP Version: 4.8 WP Multisite: – WP Memory Limit: 512 MB WP Debug Mode: – WP Cron: ✔ Language: en_GB ### Server Environment ### Server Info: Apache PHP Version: 7.0.18 PHP Post Max Size: 128 MB PHP Time Limit: 30 PHP Max Input Vars: 4000 cURL Version: 7.45.0 OpenSSL/1.0.1e SUHOSIN Installed: – MySQL Version: 5.6.34 Max Upload Size: 128 MB Default Timezone is UTC: ✔ fsockopen/cURL: ✔ SoapClient: ✔ DOMDocument: ✔ GZip: ✔ Multibyte String: ✔ Remote Post: ✔ Remote Get: ✔ ### Database ### WC Database Version: 3.1.0 WC Database Prefix: wp_ woocommerce_sessions: ✔ woocommerce_api_keys: ✔ woocommerce_attribute_taxonomies: ✔ woocommerce_downloadable_product_permissions: ✔ woocommerce_order_items: ✔ woocommerce_order_itemmeta: ✔ woocommerce_tax_rates: ✔ woocommerce_tax_rate_locations: ✔ woocommerce_shipping_zones: ✔ woocommerce_shipping_zone_locations: ✔ woocommerce_shipping_zone_methods: ✔ woocommerce_payment_tokens: ✔ woocommerce_payment_tokenmeta: ✔ MaxMind GeoIP Database: ✔ ### Security ### Hide errors from visitors: ✔ ### Active Plugins (13) ### VaultPress: by Automattic – 1.9.1 Akismet Anti-Spam: by Automattic – 3.3.2 Divi Commerce: by Bolt Themes – 1.9.1.2 Easy Table: by Takien – 1.6 Jetpack by WordPress.com: by Automattic – 5.0 MailChimp for WooCommerce: by MailChimp – 2.0.0 PatchCAD: by Adam Crowe – 1.0 Social Media Feather: by socialmediafeather – 1.8.4 WordPress Shortcodes: by Synved – 1.6.36 Ultimate FAQ: by Etoile Web Design – 1.5.38 W3 Total Cache: by Frederick Townes – 0.9.5.4 WooCommerce: by Automattic – 3.1.0 Yoast SEO: by Team Yoast – 4.9 ### Settings ### API Enabled: ✔ Force SSL: – Currency: GBP (£) Currency Position: left Thousand Separator: , Decimal Separator: . Number of Decimals: 2 Taxonomies: Product Types: external (external) grouped (grouped) simple (simple) variable (variable) Taxonomies: Product Visibility: exclude-from-catalog (exclude-from-catalog) exclude-from-search (exclude-from-search) featured (featured) outofstock (outofstock) rated-1 (rated-1) rated-2 (rated-2) rated-3 (rated-3) rated-4 (rated-4) rated-5 (rated-5) ### WC Pages ### Shop base: ❌ Page not set Basket: #106 - /basket/ Checkout: #107 - /checkout/ My account: #108 - /my-account/ ### Theme ### Name: Divi Version: 3.0.53 Author URL: http://www.elegantthemes.com Child Theme: ❌ – If you are modifying WooCommerce on a parent theme that you did not build personally we recommend using a child theme. See: How to create a child theme WooCommerce Support: ✔ ### Templates ### Overrides: Divi/single-product.php ```

Isolating the problem

mikejolley commented 7 years ago

If I test this by forcing complete status:

$this->set_status( apply_filters( 'woocommerce_payment_complete_order_status', 'completed', $this ) );

Forcing BACS to set complete status:

$order->payment_complete( 'test' );

And logging the events:

protected function status_transition() {
        if ( $this->status_transition ) {
            error_log( 'woocommerce_order_status_' . $this->status_transition['to'] );

I can see that the event does fire because it's logged. If you're finding that the event is not firing and execution is stopping before emails go out, it means you're most likely getting an error elsewhere which is halting execution.

I suggest you look at the PHP error log for any clues/fatal errors. Feel free to reply here and I'll take a look at them, but there does not appear to be a bug.

Like I said, this was working perfectly and untouched for months now until this update :(

Maybe it wasn't 3.x compatible. The order transitions methods do not appear to have been touched in the 3.1 minor release.

Also note it could be something hooking into woocommerce_order_status_completed at fault too.

patchcad commented 7 years ago

A thousand thank you Mike for your detailed reply!

However, it doesn't look like this is it. For the past few months I had the following hook setup to convert a pending order to a completed one as I'm only selling a download:

add_filter( 'woocommerce_payment_complete_order_status', array( 'PatchCAD', 'patchcad_woocommerce_update_order_status' ), 5, 2 );

public static function patchcad_woocommerce_update_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 ) )
        {
            return 'completed';
        }

        return $order_status;
    }

This worked beautifully. I've just did some debugging and it looks like the current version of WC sets the $order_status to "completed" before this hook even engages. Furthermore, I have checked with a mail logger than no email confirmation of any kind is sent out, and the order notes say "IPN payment completed".

Emails do get sent if I resend them manually from the order page. woocommerce_order_status_completed action never gets triggered also.

I am utterly lost and puzzled. The only plugin that got updated was WC to v3.1. Am I using the hook incorrectly? If I revert the order to "pending" and then back to "completed", the hooks trigger correctly and I can resend the completed email manually with the license key, but it's a little embarrassing if I get an order while I'm asleep and don't react to it promptly O_o.

Again, sincerest and biggest thank you for your time!

mikejolley commented 7 years ago

There are several things wrong with that function.

wc_get_order should be used, not creating an instance of WC_Order $order->status should be replaced with either $order->get_status() or $order->has_status( 'x' ) or notices will be thrown.

Notices include a backtrace which may have timed it out.

patchcad commented 7 years ago

Little update… After the previous post, a new version of Jetpack came out and I ran the update. After this, the normal functionality came back. None of my code changed, none of the WC settings changed.

Still very puzzled and confused.

bretweinraub commented 7 years ago

Battling the same..... hooks on order status no longer fire. Updated everything, including swapping out Mystile for Storefront.

In PHP logs, a whole lot of nada.....

newjie commented 2 years ago

I am facing the same issue. If a normal user places and pays for an order, woocommerce_order_status_completed won't fire. However, if I go to backend and manually change an order's status from "on hold" to "completed" woocommerce_order_status_completed will fire. I check $wp_filter and can see that my custom function is successfully registered with the filter. image

bretweinraub commented 2 years ago

If my memory serves, I think I discovered that the callbacks where stack tracing. Don't remember how I discovered it....

IT-Mesteren commented 2 years ago

I just experienced this as well, but I don't know why

bretweinraub commented 2 years ago

check the log files in woocommerce, that's where I found the stack traces of the callbacks