WooCommerce custom order action does not work with trash status - php

I want to use woocommerce hook woocommerce_order_status_changed.
I want to fire something when new status of order is trash.
I used this function, which is working good for rest order statuses, except trash.
This is my code:
function custom_order_actions ( $order_id, $old_status, $new_status ){
$order = new WC_Order($order_id);
if ($new_status == 'trash') {
// Do something
}
}
add_action( 'woocommerce_order_status_changed', 'custom_order_actions', 99, 3 );

woocommerce_order_status_changed can not pick up the trash status since it's not one of the registered statuses on woocommerce according to their github page.
However, you could use wp_trash_post action hook instead!
add_action('wp_trash_post', 'custom_order_actions');
function custom_order_actions($order_id)
{
if ('shop_order' == get_post_type($order_id)) {
$order = new WC_Order($order_id);
// Do something
}
}
wp_trash_postDocs
Let me know if it works for you!

Related

WooCommerce order status hook not triggering

I'm using this little function here to detect if an order is set into pending. This happens between the payment page and the payment provider notification:
add_action( 'woocommerce_order_status_pending', 'status_pending' );
function status_pending( $related_job ) {
error_log('Triggered');
}
The problem is that I don't get any error log which shows me that the function work. But it becomes crazier. When I update the status via the dashboard from completed to pending, the log appears. So I've absolutely no idea why it's not working during the checkout process. Any recommendations or ideas what could be the problem?
The "pending" order status is the default status for orders before customer get on a payment gateway, just after order creation.
So the best way is to use a hook once the order is created, before payment method process:
1) try first the woocommerce_checkout_order_processed action hook (3 args):
add_action( 'woocommerce_checkout_order_processed', 'order_processed_with_pending_status', 10, 3 );
function order_processed_with_pending_status( $order_id, $posted_data, $order ) {
error_log('Triggered');
}
2) Alternatively try the woocommerce_checkout_update_order_meta action hook (2 args):
add_action( 'woocommerce_checkout_update_order_meta', 'order_processed_with_pending_status', 10, 2 );
function order_processed_with_pending_status( $order_id, $data ) {
error_log('Triggered');
}
Both should work…
That's because the hook is only triggering on order status change not on order creation, there is another hook that you can use to detect new orders, you can use the order ID to get order object which you can use to find out the order status:
add_action( 'woocommerce_new_order', 'prefix_new_wc_order', 1, 1 );
function prefix_new_wc_order( $order_id ) {
$order = new WC_Order( $order_id );
}
The hook above is only triggered in checkout process, so creating orders on backend won't trigger it.

Woocommerce disable automatic order status change pending->processing

I want to dissable this option:
Whenever someone makes and order on my site and the payment is successfull the order status automaticaly changes from pending to processing.
However I don`t want this feature to have enabled. Rather I want to do it manually when i proces the orders.
I found this function in the woocommerce which is making this feature possible. I don`t want to directly change it there but rather with some kind of php snippet which overrides this function.
Here is the function which i need to change : http://woocommerce.wp-a2z.org/oik_api/wc_orderpayment_complete/
PS: I just having a hard time to do it correctly.
Update
May be this payment_complete() is not involved in the process you are looking for. Alternatively, what you could try is the woocommerce_thankyou action hook instead:
add_action( 'woocommerce_thankyou', 'thankyou_order_status', 10, 1 );
function thankyou_order_status( $order_id ){
if( ! $order_id ) return;
$order = new WC_Order( $order_id ); // Get an instance of the WC_Order object
if ( $order->has_status( 'processing' ) )
$order-> update_status( 'pending' )
}
You can use the same alternative hook: woocommerce_thankyou_{$order->get_payment_method()} (replacing $order->get_payment_method() by the payment method ID slug)
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works.
Using a custom function hooked in woocommerce_valid_order_statuses_for_payment_complete filter hook, where you will return the desired orders statuses that can be taken by the related function payment_complete() which is responsible of auto change the order status.
By default the array of order statuses in the filter is:
array( 'on-hold', 'pending', 'failed', 'cancelled' ).
And we can remove 'on-hold' order status this way:
add_filter( 'woocommerce_payment_complete_order_status', 'disable_auto_order_status', 10, 2 );
function disable_auto_order_status( $order_statuses, $order ) {
$return array( 'pending', 'failed', 'cancelled' );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested on Woocommerce 3+ and works.
Add the following code to your functions.php file.function
ja_order_status( $order_status, $order_id ) {
$order = new WC_Order( $order_id );
if ( 'processing' == $order_status ) {
return 'pending';
}
return $order_status;
}
add_filter( 'woocommerce_payment_complete_order_status', 'ja_order_status', 10, 2 );
Tested on WooCommerce with Storefront paid via Stripe test mode.

Set WooCommerce order status when order is created from processing to pending

When a woocommerce order is created the status of the order is "processing". I need to change the default order-status to "pending".
How can I achieve this?
The default order status is set by the payment method or the payment gateway.
You could try to use this custom hooked function, but it will not work (as this hook is fired before payment methods and payment gateways):
add_action( 'woocommerce_checkout_order_processed', 'changing_order_status_before_payment', 10, 3 );
function changing_order_status_before_payment( $order_id, $posted_data, $order ){
$order->update_status( 'pending' );
}
Apparently each payment method (and payment gateways) are setting the order status (depending on the transaction response for payment gateways)…
For Cash on delivery payment method, this can be tweaked using a dedicated filter hook, see:
Change Cash on delivery default order status to "On Hold" instead of "Processing" in Woocommerce
Now instead you can update the order status using woocommerce_thankyou hook:
add_action( 'woocommerce_thankyou', 'woocommerce_thankyou_change_order_status', 10, 1 );
function woocommerce_thankyou_change_order_status( $order_id ){
if( ! $order_id ) return;
$order = wc_get_order( $order_id );
if( $order->get_status() == 'processing' )
$order->update_status( 'pending' );
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works
Note: The hook woocommerce_thankyou is fired each time the order received page is loaded and need to be used with care for that reason...
Now the function above will update the order status only the first time. If customer reload the page, the condition in the IF statement will not match anymore and nothing else will happen.
Related thread: WooCommerce: Auto complete paid Orders (depending on Payment methods)
Nowadays, if the payment gateway that you use properly sets the order status using WC_Order->payment_complete(), you can use the woocommerce_payment_complete_order_status filter.
This is better than using woocommerce_thankyou hook since we are setting the order status immediately, rather than applying it after it has been already set.
function h9dx3_override_order_status($status, $order_id, $order) {
if ($status === 'processing') {
$status = 'pending';
}
return $status;
}
add_filter('woocommerce_payment_complete_order_status', 'h9dx3_override_order_status', 10, 3);
Again, this will only work if the payment gateway uses the proper payment_complete wrapper method rather than setting status directly with set_status. You can just search the gateway code for 'payment_complete(' and 'set_status(' to see what it does.
If you develop a plugin for everyone, you will be better off with using woocommerce_thankyou, or you could use a combined approach and use woocommerce_thankyou as the fallback if the order status was not updated.
The hook woocommerce_thankyou suffers from the problem that you can pay for an order and then close the browser or go somewhere else and therefore never click "Return to Merchant" (which is displayed after paying via paypal) to get to the thankyou page. And then the code will never be executed.
// Rename order status 'Processing' to 'Order Completed' in admin main view - different hook, different value than the other places
add_filter( 'wc_order_statuses', 'wc_renaming_order_status' );
function wc_renaming_order_status( $order_statuses ) {
foreach ( $order_statuses as $key => $status ) {
if ( 'wc-processing' === $key )
$order_statuses['wc-processing'] = _x( 'Order Completed', 'Order status', 'woocommerce' );
}
return $order_statuses;
}

Can not get the product details from order_id on the new order hook function

With WooCommerce, I have the following hook in my function.php after the new order is submitted:
add_action( 'woocommerce_new_order', 'create_job_openings');
function create_job_openings($order_id) {
$order = new WC_Order($order_id);
$items = $order->get_items();
foreach ($order->get_items() as $key => $item) {
$product_name = $item['name'];
var_dump($product_name);
}
}
The above code is not giving me any output i'e it is not entering inside the foreach loop that's why var_dump() not giving me any output, but if I mention the order_id specifically like create_job_openings($order_id=517) it works, even I tried echo $order_id before foreach loop, it is giving me the order_id, then why it is not entering the foreach loop?
note: when I try var_dump($items); before foreach loop its giving me
array(0) {
}
Why it is not able to get the product details even if there are products in it after new order is made?
Update 2 — The working solution (using an email notification hook)
The problem is when using email notification hook can fire an action 2 times, for example when a new order is made (notification for the Shop manager and notification for the customer).
You want to use this "New Order" event for Orders that are in "processing" status.
To avoid your action to be fired 2 times using New order notification WooCommerce event, we use 'customer_processing_order' instead of 'new_order' email ID (notification event).
Here we don't need to get the $order object, as we got it as an argument in this hooked function.
So here is your final functional code:
add_action( 'woocommerce_email_before_order_table', 'custom_action_on_completed_customer_email_notification', 10, 4 );
function custom_action_on_completed_customer_email_notification( $order, $sent_to_admin, $plain_text, $email ) {
if( 'customer_processing_order' == $email->id ){ // for processing order status customer notification…
foreach ($order->get_items() as $item_id => $item_values) {
$product_name = $item_values['name'];
echo $product_name;
break; // (optional) stop loop to first item
}
}
}
This is the validated and working answer to this question
Related Working Answers:
Sending an SMS for specific email notifications and order statuses
Avoid repetitive emails notification on some auto completed orders
Change the user role on purchase for specific products when order status is completed
Update 1 (hook alternative)
Trying using woocommerce_thankyou hook, that is fired on review order after order has been processed:
add_action( 'woocommerce_thankyou', 'create_job_openings', 10, 1 );
function create_job_openings( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
foreach ($order->get_items() as $item_id => $item_values) {
$product_name = $item_values['name'];
var_dump($product_name);
break; // (optional) stop loop to first item
}
}
(Not working for the OP)
You should try this instead wc_get_order() function this way and your code will be:
add_action( 'woocommerce_new_order', 'create_job_openings', 10, 1);
function create_job_openings($order_id) {
$order = wc_get_order( $order_id );
$order_items = $order->get_items();
foreach ($order_items as $item_id => $item_values) {
$product_name = $item_values['name'];
var_dump($product_name);
break; // (optional) stops on first item
}
}
You can have a look to
How to get WooCommerce order details where a lot of things are explained…
(Not working for the OP)
you can use save_post action when post is added in wordpress. for more visit: Link
function wc_order_add_action($post_id, $post, $update)
{
$post_type = get_post_type($post_id);
// If this isn't a 'shop_order' post, don't update it.
if ("shop_order" != $post_type) return;
$order = wc_get_order($post_id);
foreach($order -> get_items() as $key => $item)
{
$product_name = $item['name'];
var_dump($product_name);
}
}
add_action('save_post', 'wc_order_add_action');
To get the items and product details from the new order, you simply need to request two parameters for woocommerce_new_order. The second passed parameter will be the new order object. Example:
add_action( 'woocommerce_new_order', 'so41605256_new_order', 10, 2 );
function so41605256_new_order( $order_id, $order ) {
// Directly access items from $order variable, do not use wc_get_order...
foreach ($order->get_items() as $item_id => $item) {
//...
}
}
This works for both programmatically created and user created orders, regardless of WC email configuration.
Reference: create and update methods in WC_Order_Data_Store_CPT core class. Kudos to this post which helped me discover this.
Faced the same issue. I fixed it by changing the hook to woocommerce_checkout_order_processed. It works perfectly for both instant payment and cash on delivery since it runs as soon as an order is placed. Note that, this will run before payment completion. So, it doesn't have any relation with payment.
User clicks on proceed to checkout button and then this hook fires.

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.

Categories