Woocommerce - woocommerce_order_status_pending hook not calling - php

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!.

Related

Change default order status for COD payment gateway based on user role in Woocommerce

In Woocommerce, when the payment option is COD, the orders go directly to the "Processing" state.
Source: https://docs.woocommerce.com/document/managing-orders/#prettyPhoto
I need this to work like this, except when the client's role is "X".
I have seen that this can be solved with this code:
function cod_payment_method_order_status_to_onhold( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
if ( get_post_meta($order->id, '_payment_method', true) == 'cod' )
$order->update_status( 'on-hold' );
}
add_action( 'woocommerce_thankyou', 'cod_payment_method_order_status_to_onhold', 10, 1 );
However, the problem is that it goes through "Processing", sends the email and then goes to "on hold". I want to avoid sending the "Processing" mail
Any way to do it? Thank you!
You should better use woocommerce_cod_process_payment_order_status dedicated filter hook. You will have to replace "administrator" user role by your "X" role.
The hooked function code:
add_filter( 'woocommerce_cod_process_payment_order_status', 'set_cod_process_payment_order_status_on_hold', 10, 2 );
function set_cod_process_payment_order_status_on_hold( $status, $order ) {
$user_data = get_userdata( $order->get_customer_id() );
if( ! in_array( 'administrator', $user_data->roles ) )
return 'on-hold';
return $status;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

WooCommerce 3.0: can't find hook which corresponds to an admin created backend order

Along the lines of this post, I am trying to connect to my own custom payment gateway when an admin creates an order via the admin panel using my payment gateway.
I have added the following code:
add_action( 'woocommerce_process_shop_order_meta', array( $this, 'process_offline_order' ) );
add_action( 'woocommerce_admin_order_actions_end', array( $this, 'process_offline_order2' ) );
add_action( 'woocommerce_save_post_shop_order', array( $this, 'process_offline_order3' ) );
I have tried to drop in xdebug breakp points into those respective methods, but none of them are getting hit.
After some research and testing, I think that the correct hook for that is one of this WP hooks:
save_post_{$post->post_type}
save_post
wp_insert_post
So I have used the first one as it's the most convenient for "shop_order" post type:
add_action( 'save_post_shop_order', 'process_offline_order', 10, 3 );
function process_offline_order( $post_id, $post, $update ){
// Orders in backend only
if( ! is_admin() ) return;
// Get an instance of the WC_Order object (in a plugin)
$order = new WC_Order( $post_id );
// For testing purpose
$trigger_status = get_post_meta( $post_id, '_hook_is_triggered', true );
// 1. Fired the first time you hit create a new order (before saving it)
if( ! $update )
update_post_meta( $post_id, '_hook_is_triggered', 'Create new order' ); // Testing
if( $update ){
// 2. Fired when saving a new order
if( 'Create new order' == $trigger_status ){
update_post_meta( $post_id, '_hook_is_triggered', 'Save the new order' ); // Testing
}
// 3. Fired when Updating an order
else{
update_post_meta( $post_id, '_hook_is_triggered', 'Update order' ); // Testing
}
}
}
You will be able to test easily with this code. For me it's working fine.
I have also tried with woocommerce_before_order_object_save hook which have 2 arguments:
$order (the WC_Order object )
$data_store (The data to be stored through WC_Data_Store class)
But I didn't get it working, as I was expecting. I have found it in the source code of WC_Order save() method.

Change orders status made with cheque payment method to "processing" status

I need to make WooCommerce push payments made by check into the "processing" status rather than the "on hold" status. I tried the snippet below however it doesn't seem to have an effect.
Here is my code:
add_filter( 'woocommerce_payment_complete_order_status', 'sf_wc_autocomplete_paid_orders' );
function sf_wc_autocomplete_paid_orders( $order_status, $order_id ) {
$order = wc_get_order( $order_id );
if ($order->status == 'on-hold') {
return 'processing';
}
return $order_status;
}
How can I achieve this?
Thanks.
Here is the function you are looking at hooked in woocommerce_thankyou hook:
add_action( 'woocommerce_thankyou', 'cheque_payment_method_order_status_to_processing', 10, 1 );
function cheque_payment_method_order_status_to_processing( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
// Updating order status to processing for orders delivered with Cheque payment methods.
if ( get_post_meta($order->id, '_payment_method', true) == 'cheque' )
$order->update_status( 'processing' );
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This is tested and works.
Related thread: WooCommerce: Auto complete paid Orders (depending on Payment methods)
I didn't want to use the Thank You filter in case the order still got set to On Hold at a previous step, before changing it to my desired status in the filter (a custom status in my case, or Processing in yours). So I used the filter in the Cheque gateway:
add_filter( 'woocommerce_cheque_process_payment_order_status', 'myplugin_change_order_to_agent_processing', 10, 1 );
function myplugin_change_order_to_agent_processing($status){
return 'agent-processing';
}
I hope this helps someone else out there to know that there is another option.
Previous answer from LoicTheAztec is outdated and gives error about accessing object fields directly on the order object.
Correct code should be
add_action( 'woocommerce_thankyou', 'cheque_payment_method_order_status_to_processing', 10, 1 );
function cheque_payment_method_order_status_to_processing( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
// Updating order status to processing for orders delivered with Cheque payment methods.
if ( get_post_meta($order->get_id(), '_payment_method', true) == 'cheque' )
$order->update_status( 'processing' );
}

Stay on same page and not empty the cart session during Woocomerce checkout

I am in the middle of creating an additional plugin which is a custom payment gateway using the Woocommerce plugin and a child theme to style it.
This is working and I see the payment form correctly and items which is great.
The issue I have is with the payment process option.
The checkout page has an i-frame to the payment solution and is supposed to show only when an order is created and an ID is present. And to make sure we have all the persons details etc.
However the process payment take you to the thanks you page instead.
It also dumps the cart session.
even if I redirect the URL back to the cart page by playing around with it, it still kills the cart.
This would be fine in normal circumstances as I'd expect it to go to a payment page, checkout and be done. But I do not want to do this because this site has to mirror one that is currently live and how that works.
The function in my extended class is this.
public function process_payment( $order_id ) {
global $woocommerce;
#$order = wc_create_order();
///
$order = new WC_Order( $order_id );
// Mark as on-hold (we're awaiting the cheque)
$order->update_status('on-hold', __( 'Awaiting Confirmation of Funds', 'woocommerce' ));
// Reduce stock levels
///$order->reduce_order_stock();
// Remove cart
//$woocommerce->cart->empty_cart();
// Return thankyou redirect
return array(
'refresh' => true,
'reload' => false,
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
///return $order_id;
}
As you can see I commented out the bit where to empty the cart and the also the endpoint brings in the thank you template instead of just staying on the same page.
So far I have tried:
Replicating the code on my checkout to the thank you page and that
results in an undefined checkout, because the process removes it by
then
Changing the end-point reference to the same as checkout
Creating another page and putting the same shortcode on it
Nothing works, and I have been through the plugin and can see a few things I could do.
Copy the process_payment function into my extended class and
effectively re-write it
or
Find a filter similar to below that could do what I need
add_action( 'woocommerce_thankyou', function(){
global $woocommerce;
$order = new WC_Order();
if ( $order->status != 'failed' ) {
wp_redirect( home_url() ); exit; // or whatever url you want
}
});
What I need is it to stay on the same page (refresh) the same way it does when it checks the details to refresh the totals.
Create an order with those current details in and return an order number
Will not kill the cart session at that point, so if I was to refresh the browser for arguments sake it would stay live. (I will work out a way to kill the cart when the person navigates away and a unique session has been created at that point).
Its just this bit I have been fighting with for the past couple of days and not sure the best way.
Any help or pointers would be greatly appreciated.
thanks
Andi
Ok figured this one out.
There is a header action that clears the cart.
We needed to add some more statuses to the array so that it ignores it.
1st remove the action and then add your own method.
function st_wc_clear_cart_after_payment( $methods ) {
global $wp, $woocommerce;
if ( ! empty( $wp->query_vars['order-received'] ) ) {
$order_id = absint( $wp->query_vars['order-received'] );
if ( isset( $_GET['key'] ) )
$order_key = $_GET['key'];
else
$order_key = '';
if ( $order_id > 0 ) {
$order = wc_get_order( $order_id );
if ( $order->order_key == $order_key ) {
WC()->cart->empty_cart();
}
}
}
if ( WC()->session->order_awaiting_payment > 0 ) {
$order = wc_get_order( WC()->session->order_awaiting_payment );
if ( $order->id > 0 ) {
// If the order has not failed, or is not pending, the order must have gone through
if ( ! $order->has_status( array( 'failed', 'pending','pending-st-cleared-funds','on-hold' ) ) ) { ///// <- add your custom status here....
WC()->cart->empty_cart();
}
}
}
}
function override_wc_clear_cart_after_payment() {
remove_filter('get_header', 'wc_clear_cart_after_payment' );
add_action('get_header', 'st_wc_clear_cart_after_payment' );
}
add_action('init', 'override_wc_clear_cart_after_payment');

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