woocommerce_order_status_completed not triggered - php

I want to write a custom plugin that does some action after woocommerce order is completed, but I can't get this hook to work. I can see this question asked many times.
Like here: https://wordpress.stackexchange.com/questions/134463/woocommerce-order-status-completed-action-hook-not-working
Here: https://wordpress.org/support/topic/woocommerce_order_status_completed-is-not-working
And here: https://wordpress.org/support/topic/woocommerce_order_status_completed-action-hook-not-working
But I cannot help myself with answers that these guys received.
I tried to add the action a few different ways:
add_action( 'woocommerce_order_status_completed', 'ikwoocommerceorderstatuscompleted_func');
add_action( 'woocommerce_order_status_completed', array($this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
add_action( 'woocommerce_order_status_completed', array(&$this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
Also tried with a class:
class IKHooks {
function __construct() {
add_action( 'woocommerce_order_status_completed', array($this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
}
public function ikwoocommerceorderstatuscompleted_func( $order_id ) {
}
}
I even tried to put the action outside of the class:
add_action( 'woocommerce_order_status_completed', array(IKHooks,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
None of these examples work. :(

Check the following steps before calling your hook.
Check if order completion email is sent.
Hook is properly registered in plugin file or theme functions.php
add_action( 'woocommerce_order_status_completed','callback_function_name' );
function callback_function_name(){
global $wp_filter;
print_r($wp_filter);
exit;
}
Check if the name of your callback function is in the hook array:
[woocommerce_order_status_completed] => Array
(
[10] => Array
(
[wc_paying_customer] => Array
(
[function] => wc_paying_customer
[accepted_args] => 1
)
[wc_downloadable_product_permissions] => Array
(
[function] => wc_downloadable_product_permissions
[accepted_args] => 1
)
[callback_function_name] => Array
(
[function] => callback_function_name
[accepted_args] => 3
)
)
)
If you find it then everything is ok, it means that probably there's an issue with your theme or functions.php file. Check for the hook or callback function in your files and then look for remove_action or remove_all_actions that's probably what's preventing your hook from being called.
You can also check in this way
add_action( 'woocommerce_order_status_completed', 'callback_function_name', 1);
Change the priority of your hook from 10 to 1 so it is called first than any other action or hook.

You can use this hook
add_action( 'woocommerce_order_status_changed', 'your_function', 99, 4 );
And the function will look like
function your_function( $order_id, $old_status, $new_status, $order ){
if( $new_status == "completed" ) {
//your code here
}
}
Hope this will be helpful.

I faced the similar issue earlier and solved it as:
Following code update the order status as completed
add_action( 'woocommerce_thankyou', 'your_wc_autocomplete_order' );
function your_wc_autocomplete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Once order is completed, if you want to do something, see the following code:
add_action('woocommerce_order_status_completed','payment_complete');
function payment_complete($order_id)
{
//global $items;
//$order = new WC_Order($order_id);
// do something ...
}
Hopefully, it will work :)

woocommerce_order_status_changed and woocommerce_order_status_completed actually work for me. After struggling for 2 days i realized that you just can't var_dump or var_export or print_r or whatever in the admin panel, it just won't work.
So if you are a newbie like me and thought those actions weren't working, just try triggering another action like sending a mail for example.
This code works:
function your_function( $order_id ){
$order = new WC_Order( $order_id );
$to_email = 'testing_mail#sample.com';
$payment = $order->get_payment_method_title();
$headers = 'From: Your Name <Your_site_mail#address.com>' . "\r\n";
wp_mail($to_email, 'subject', $payment, $headers );
}
add_action( 'woocommerce_order_status_completed', 'your_function');

Try using action hook woocommerce_order_status_changed.
It takes 4 parameters. order id, old status new status and order. Further code reference HERE
This may not be exactly suitable to your requirement, but seems to be worth of an alternative. Hope this helps.

I think you might be after this guy. woocommerce_payment_complete
function mysite_woocommerce_payment_complete( $order_id ) {
error_log( "Payment has been received for order $order_id", 0 );
}
add_action( 'woocommerce_payment_complete', 'mysite_woocommerce_payment_complete' );

Related

Unset some data from create_order( $data ) inside WooCommerce

Im trying to clean up some default database entries that WooCommerce adds to the postmeta table. The two primary entries that I do not need are _customers_ip_address & _customer_user_agent.
I found _customers_ip_address in create_order() function in file class-wc-checkout.php
do_action( 'woocommerce_checkout_create_order', $order, $data ); seems to be what is setting the data. Although I also found it was being set in wc-core-functions.php # function wc_create_order()
Im not 100% sure how to edit this. Im thinking a simple do_filter, but unset seems to not work inside the do_filter, but obviously I am doing it all wrong. Im not that familiar with do_filter but seems like something simple like the code below.
function cleanup_woocommerce_checkout_create_order($order, $data) {
unset($order->set_customer_ip_address());
return $order;
}
add_filter('woocommerce_checkout_create_order', 'cleanup_woocommerce_checkout_create_order');
The code above gives a WordPress Error of :
Fatal error: Can't use method return value in write context
First woocommerce_checkout_create_order is an action hook (but not a filter hook). Also you can not unset any method applied to an object as you are doing.
What you can do is to try setting an empty value, like:
add_action('woocommerce_checkout_create_order', 'cleanup_specific_order_metadata', 10, 2 );
function cleanup_specific_order_metadata( $order, $data ) {
$order->set_customer_ip_address('');
$order->set_customer_user_agent('');
}
It should work.
If it doesn't work, you can try to use woocommerce_checkout_update_order_meta action hook to remove this meta data afterwards once order data has been saved to database, this way:
add_action('woocommerce_checkout_update_order_meta', 'cleanup_specific_order_metadata', 10, 2 );
function cleanup_specific_order_metadata( $order_id, $data ) {
delete_post_meta( $order_id, '_customer_ip_address' );
delete_post_meta( $order_id, '_customer_user_agent' );
}
This last one should work anyways.
As I can see in this article, https://docs.woocommerce.com/wc-apidocs/source-class-WC_Checkout.html#397
do_action( 'woocommerce_checkout_create_order', $order, $data );
so you should use add_action function
add_action('woocommerce_checkout_create_order', 'cleanup_woocommerce_checkout_create_order', 10, 2 );
function cleanup_woocommerce_checkout_create_order( $order, $data ) {
$order->set_customer_ip_address(0);
}
Or updating the post meta
update_post_meta($order_id, '_customer_ip_address', 0);
or
delete_post_meta($order_id, '_customer_ip_address');

Woocommerce - woocommerce_order_status_pending hook not calling

I am having trouble with checking order status of woocommerce order.
I have a plugin that I am creating and I need to know, when the order become "pending" and then "completed". But all hooks are working only if I set the order status manually in wordpress admin.
function order_status_changed_clbk( $order_id ){
...some code...
}
add_action( 'woocommerce_order_status_pending', 'order_status_changed_clbk' );
UPDATE
I've found out that there is a little problem. If the user cancels the payment for example at PayPal, he maybe get's redirected to the checkout again. Now let's expect that he repeats the checkout again. In this case the hook get's called a second time which could be problematic. So I've implemented myself a payment_counter:
add_action( 'woocommerce_checkout_order_processed', 'order_status_changed_clbk' );
function order_status_changed_clbk( $order_id ) {
$payment_counter = (int) get_post_meta( $order_id, 'payment_counter', true );
if ( empty( $payment_counter ) ) {
update_post_meta( $order_id, 'payment_counter', 1 );
error_log( 'Function works!' ); //Get's called only once
} else {
update_post_meta( $order_id, 'payment_counter', ++ $payment_counter ); //Cool thing for statistics maybe, but not really needed
}
}
Maybe this hook works for you:
function order_status_changed_clbk( $order_id ){
error_log( 'Function works!' );
}
add_action( 'woocommerce_checkout_order_processed', 'order_status_changed_clbk' );
I'm using it within my plugin. If the order is processed, it's also "pending" so maybe this is the solution your'e looking for.
Try it out and check your debug.log for Function works!.

Woocommerce Order Delivery plugin change display location

I'm working on a Woocommerce site that is using the following plugin: https://docs.woothemes.com/document/woocommerce-order-delivery/ ("WooCommerce Order Delivery")
The plugin is now displayed on the Checkout page under the billing fields in the checkout_shipping section, I am trying to change this location to the checkout_order_review section by hooking in to the functions.
But I can't seem to get it working.
My code in my functions.php:
function action_woocommerce_checkout_shipping( $instance ) {
global $woocommerce;
if ( is_checkout() && $woocommerce->cart->needs_shipping() ) {
echo 'Hi World!';
if ( wc_od() ){
echo 'Found wc_od function';
}
remove_action( 'woocommerce_checkout_shipping', 'checkout_content' );
}
};
// add the action
add_action( 'woocommerce_checkout_shipping', 'action_woocommerce_checkout_shipping' );
My thought behind this code was that I remove the function 'checkout_content' which retrieves the plugin template and then add the action to the woocommerce_checkout_order_review function to display it in the order review section.
But my remove_action doesn't seem to work.
The code in the plugin that adds the checkout_content action:
protected function __construct() {
// WP Hooks.
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
// WooCommerce hooks.
add_action( 'woocommerce_checkout_shipping', array( $this, 'checkout_content' ), 99 );
add_action( 'woocommerce_checkout_process', array( $this, 'validate_delivery_date' ) );
add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'update_order_meta' ) );
// Delivery date validation hooks.
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_delivery_day' ), 10, 2 );
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_minimum_days' ), 10, 2 );
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_maximum_days' ), 10, 2 );
add_filter( 'wc_od_validate_delivery_date', array( $this, 'validate_no_events' ), 10, 2 );
}
Can someone maybe give me a push in the right direction?
Am I doing this wrong ? or is there a better way of achieving this?
You have two issues.
Firstly you need to specify the execution priority when you remove action, or at least you do when it is anything other than the default, 10. In your case the execution priority is 99.
Secondly, checkout_content() is a class function, not a standalone function so you need to specify this in the function reference.
So your remove_action line of code will be:
remove_action( 'woocommerce_checkout_shipping', array( $the_class_variable, 'checkout_content' ), 99 );
where $the_class_variable is the instance of the class containing that __construct() function. How you refer to this depends on how the class has been instantiated in the plugin.
You can read about different ways of instantiating a class and the corresponding remove_action at http://jespervanengelen.com/different-ways-of-instantiating-wordpress-plugins/
You can read about remove_action this in https://codex.wordpress.org/Function_Reference/remove_action

Woocommerce - Call custom function after payment is completed

I am using Woocommerce for some project and i need to send the order id to some remote site when the payment is made. I am not finding the accurate hook to do this. Can anyone help me to find what's the correct hook to perform certain action after order is completed.
Here is what i have tried
add_action( 'woocommerce_thankyou', 'woo_remote_order' );
function woo_remote_order( $order_id ) {
// Lets grab the order
$order = new WC_Order( $order_id );
//Some action to make sure its working.
wp_mail( 'sagarseth9#example.com',' Woocommmerce Order ID is '.$order_id , 'Woocommerce order' );
}
Not sure which is the proper hook to perform this action. I am using paypal payment gateway for payment and orders successfully passes through.
looks like you need add accepted_args on last parameters,
Try this :
add_action( 'woocommerce_thankyou', 'your_func', 10, 1 );
function your_func($order_id) {
$order = new WC_Order( $order_id );
/* Do Something with order ID */
}
Maybe try one of the following.
woocommerce_checkout_order_processed
woocommerce_new_order
add_action( 'woocommerce_subscription_payment_complete', 'YourFunction', 1, 2);
function YourFunction ($order_id)
{
$order = new WC_Order( $order_id );
wp_mail( 'sagarseth9#example.com',' Woocommmerce Order ID is '.$order_id , 'Woocommerce order' );
}
The add_action call must be placed at the very beginning of your plugin, if using wordpress, or if a theme, in functions.php.

Woocommerce Sessions: woocommerce_get_cart_item_from_session

I have created a plugin mainly following this guide, which simply adds a small bit of data to a given product.
I know Woocommerce have made some changes outlined here.
The problem I'm having is that when I add my item to the cart, and access the cart page, I am getting a blank screen. I believe the problem stems from the use of this filter:
add_filter('woocommerce_get_cart_item_from_session'...
If I comment the line with this filter, my checkout page works (but without the extra details added to my product). I can't work out why this filter is not working, or what problem it is having??
The woocommerce changes said:
WooCommerce 2.0 no longer uses the PHP session_start function, instead it makes use of WordPress’ transients, which is great, unless your code happens to rely on $_SESSION.
I'm not starting any new sessions as far as I can see (my code is 90% the same as the first link). Maybe this is a problem with my server? Any ideas?
i was browsing a lot and i recommend that you read the following:
The solution is to hook in there and also restore your custom cart item data.
Example Code:
add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
$cartItemData['myCustomData'] = 'someCustomValue';
return $cartItemData;
}, 10, 3 );
add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
if ( isset( $cartItemSessionData['myCustomData'] ) ) {
$cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
}
return $cartItemData;
}, 10, 3 );
To also show the data at the cart/checkout page you can use the following code:
add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
if ( isset( $cartItem['myCustomData'] ) ) {
$data[] = array(
'name' => 'My custom data',
'value' => $cartItem['myCustomData']
);
}
return $data;
}, 10, 2 );
The final thing now is to save the data when the order is made:
add_action( 'woocommerce_add_order_item_meta', function ( $itemId, $values, $key ) {
if ( isset( $values['myCustomData'] ) ) {
wc_add_order_item_meta( $itemId, 'myCustomData', $values['myCustomData'] );
}
}, 10, 3 );
You dont have to do anything else the show the data inside the backend, all order item meta data gets display automatically.
this is from
How to retrieve cart_item_data with WooCommerce?
you have to add this stuff to the functions.php file of your theme for example.

Categories