woocommerce_thankyou hook is not working after successful payment - php

I am creating a payment gateway for woocommerce but I am facing an issue that after successful payment I am redirecting to thank you page and my order status is not updating to 'processing' or 'completed'.
I am using woocommerce_thankyou hook in my plugins main file.
add_action( 'woocommerce_thankyou_epg', 'my_change_status_function', 10, 1 );
function my_change_status_function( $order_id ) {
$order = new WC_Order( $order_id );
$order->update_status( 'processing', __( 'Payment received.', 'wc-gateway-offline' ) );
}
Actually in this functions before updating the status I want to send a API call to check the status of the payment and than according to the response I want to update the status of the order.
Can anybody help me in sorting this out.

Change the hook to:
add_action( 'woocommerce_thankyou', 'my_change_status_function', 20, 1 );
function my_change_status_function( $order_id ) {
$order = new WC_Order( $order_id );
$order_pay_method = get_post_meta( $order->id, '_payment_method', true );
if($order_pay_method == 'epg'){
$order->update_status( 'processing', __( 'Payment received.', 'wc-gateway-offline' ) );
}
}
Corrected the hook.

add_action( 'woocommerce_thankyou', 'my_change_status_function', 10, 1 );
function my_change_status_function( $order_id ) {
$order = new WC_Order( $order_id );
$order->update_status( 'processing', __( 'Payment received.', 'wc-gateway-offline' ) );
}

Related

Woocommerce change status based on payment method

I would like to immidialtey change the order status from specific orders (payment method = stripe_sofort) to a custom status, that I already have in use:
add_action( 'woocommerce_thankyou', 'woocommerce_auto_processing_orders');
function woocommerce_auto_processing_orders( $order_id ) {
if ( ! $order_id )
return;
$order = wc_get_order( $order_id );
// If order is "on-hold" update status to "processing-melle"
if( $order->get_payment_method() == 'stripe_sofort' && $order->has_status( 'on-hold' ) ) {
$order->update_status( 'my_status' );
}
}
this code does not work, but I actually don't understand why. do you guys have an idea?
thanks!

How to set custom checkout payment fields from custom WooCommerce Payment gateway

I created the plugins and added custom fields on the checkout page like payment_mode & transaction id.
public function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$order->update_status($this->order_status, __( 'Awaiting payment', 'payment' ));
wc_reduce_stock_levels( $order_id );
$wcorder = wc_get_order($order_id);
$payment_mode = $_POST['payment_mode'];
$transaction = $_POST['transaction'];
if( isset($transaction) && isset($payment_mode) ) {
$wcorder->add_meta_data( 'payment_mode', $payment_mode );
$wcorder->add_meta_data( 'transaction_id', $transaction );
$wcorder->save();
}
}
Here the payment mode & transaction is custom filed, It gets the data from users and adds the database table.
In the above coding, $order->update_status - Its working fine. But $wcorder->add_meta_data is not working. It does not show any error and the data is not added to the table.
Try replacing add_meta_data with update_meta_data.
Alternatively you can try with:
update_post_meta( $order_id, 'payment_mode', $payment_mode );
update_post_meta( $order_id, 'transaction_id', $transaction );
instead of:
$wcorder->add_meta_data( 'payment_mode', $payment_mode );
$wcorder->add_meta_data( 'transaction_id', $transaction );

Avoid repetitive emails notification on some auto completed orders

I'm using this little peace of code on WooCommerce from this answer to auto-complete paid processing orders based on payment gateways:
/**
* AUTO COMPLETE PAID ORDERS IN WOOCOMMERCE
*/
add_action( 'woocommerce_thankyou', 'custom_woocommerce_auto_complete_paid_order', 10, 1 );
function custom_woocommerce_auto_complete_paid_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
// No updated status for orders delivered with Bank wire, Cash on delivery and Cheque payment methods.
if ( ( get_post_meta($order->id, '_payment_method', true) == 'bacs' ) || ( get_post_meta($order->id, '_payment_method', true) == 'cod' ) || ( get_post_meta($order->id, '_payment_method', true) == 'cheque' ) ) {
return;
}
// "completed" updated status for paid Orders with all others payment methods
else {
$order->update_status( 'completed' );
}
}
This is working mostly perfect
Mainly using a special payment gateway by SMS which API is bridged on 'cod' payment method and that can process payment after 'woocommerce_thankyou, out side frontend. In that case the ON HOLD status orders are passed afterward to PROCESSING status. To automate an autocomplete behavior on those cases, I use this other peace of code from this answer and it works:
function auto_update_orders_status_from_processing_to_completed(){
// Get all current "processing" customer orders
$processing_orders = wc_get_orders( $args = array(
'numberposts' => -1,
'post_status' => 'wc-processing',
) );
if(!empty($processing_orders))
foreach($processing_orders as $order)
$order->update_status( 'completed' );
}
add_action( 'init', 'auto_update_orders_status_from_processing_to_completed' );
THE PROBLEM: I am getting repetitive emails notifications concerning the new completed orders.
How can I avoid this repetitive email notifications cases?
Thanks
Updated (2019)
Added version code for Woocommerce 3+ - Added Woocommerce version compatibility.
To avoid this strange fact of repetitive email notifications, is possible to create a custom meta key/value for each processed order, when changing order status to completed, using WordPress update_post_meta() function. Then we will test before in a condition, if this custom meta data key/value exist with get_post_meta() function for each processed order.
So your two code snippets will be now:
1) AUTO COMPLETE PAID ORDERS IN WOOCOMMERCE (2019 update)
For woocommerce 3+:
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order ) {
if ( ! $order->has_status('completed') && $order->get_meta('_order_processed') != 'yes') {
$order->update_meta_data('_order_processed', 'yes');
$status = 'completed';
}
return $status;
}
For all woocommerce versions (compatibility since version 2.5+):
add_action( 'woocommerce_payment_complete_order_status', 'wc_auto_complete_paid_order', 10, 3 );
function wc_auto_complete_paid_order( $status, $order_id, $order = null ) {
// Getting the custom meta value regarding this autocomplete status process
$order_processed = get_post_meta( $order_id, '_order_processed', true );
// Getting the WC_Order object from the order ID
$order = wc_get_order( $order_id );
if ( ! $order->has_status( 'completed' ) && $order_processed != 'yes' ) {
$order = wc_get_order( $order_id );
// setting the custom meta data value to yes (order updated)
update_post_meta($order_id, '_order_processed', 'yes');
$order->update_status( 'completed' ); // Update order status to
}
return $status;
}
2) SCAN ALL "processing" orders to auto-complete them (added Woocommerce compatibility)
add_action( 'init', 'auto_update_orders_status_from_processing_to_completed' );
function auto_update_orders_status_from_processing_to_completed(){
if( version_compare( WC_VERSION, '3.0', '<' ) {
$args = array('numberposts' => -1, 'post_status' => 'wc-processing'); // Before WooCommerce version 3
} else {
$args = array('limit' => -1, 'status' => 'processing'); // For WooCommerce 3 and above
}
// Get all current "processing" customer orders
$processing_orders = (array) wc_get_orders( $args );
if( sizeof($processing_orders) > 0 ){
foreach($processing_orders as $order ) {
// Woocommerce compatibility
$order_id = method_exists( $order, 'get_id' ) ? $order->get_id() : $order->id;
// Checking if this custom field value is set in the order meta data
$order_processed = get_post_meta( $order_id, '_order_processed', true );
if (! $order->has_status( 'completed' ) && $order_processed != 'yes' ) {
// Setting (updating) custom meta value in the order metadata to avoid repetitions
update_post_meta( $order_id, '_order_processed', 'yes' );
$order->update_status( 'completed' ); // Updating order status
}
}
}
}
Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
I have test this code and it should work for you (due to your particular SMS bridged payment method)

update woocommerce order status after payment process complete and redirect to store

I am using woo-commerce for my shopping site. I want to update the order status to complete after payment was made and then return to a success page.
I used the following code:
add_filter( 'woocommerce_payment_complete_order_status', 'my_change_status_function', 10, 2 );
function my_change_status_function ($order_status, $order_id) {
$order = new WC_Order($order_id);
return 'completed';
}
But this function is called before the payment was made and redirects to the payment page.
I want to change the status after the payment was completed and then return to redirect URL.
Here is my redirect link:
http://example.com/checkout/order-received/82/?key=wc_order_5614e28c9d183&state=return
But the status is not changing when I use the woocommerce_payment_complete_order_status hook.
The hook should be called after the payment is completed.
Try using the following code in your plugin
add_action( 'woocommerce_payment_complete', 'my_change_status_function' );
function my_change_status_function( $order_id ) {
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Check out this piece of code
add_action('woocommerce_checkout_order_processed', 'do_something');
function do_something($order_id) {
$order = new WC_Order( $order_id );
// Do something
}
For Cash On Delivery method, this worked for me:
add_filter( 'woocommerce_cod_process_payment_order_status', 'prefix_filter_wc_complete_order_status', 10, 3 );
function prefix_filter_wc_complete_order_status( $status, $order ) {
return 'on-hold';
}
For most other methods, this worked:
add_filter( 'woocommerce_payment_complete_order_status', 'prefix_filter_wc_complete_order_status', 10, 3 );
function prefix_filter_wc_complete_order_status( $status, $order_id, $order ) {
return 'on-hold';
}
Working with WooCommerce v4.4, other answers were not working for me. I had to do it this way: https://stackoverflow.com/a/64285242/7198947

Woocommerce simple filter php

My php skills is very low. I need some help this this function.
What it should do: When a order is marked as "failed" it should redirect to the woocommerce cart with an error message.
But problem is that this code redirect ALL status to the cart with the error message (even if payment is approved).
add_action( 'woocommerce_thankyou', function(){
global $woocommerce;
$order = new WC_Order();
if ( $order->status != 'failed' ) {
wp_redirect( $woocommerce->cart->get_cart_url() ); // or whatever url you want
wc_add_notice ( __( 'Payment Failed', 'woocommerce' ), 'error');
exit;
}
});
Currently you are cheching if status IS NOT failed and then redirect.
Change
if ( $order->status != 'failed' ) {
to
if ( $order->get_status() == 'failed' ) {
See PHP comparison operators.
Also, you are not getting correct order. Your function should take $order_id and load correct order.
add_action( 'woocommerce_thankyou', function( $order_id ){
$order = new WC_Order( $order_id );
if ( $order->get_status() == 'failed' ) {
wp_redirect( $woocommerce->cart->get_cart_url() ); // or whatever url you want
wc_add_notice ( __( 'Payment Failed', 'woocommerce' ), 'error');
exit;
}
}, 10, 1);
First of all you need to use the hook "woocommerce_order_status_failed" instead of "woocommerce_thankyou" as it will trigger only when the order status is failed.
Secondly you need to pass the order id in the function new WC_Order() so that it will get the details of that order. and then you can use the if statement to check if the order status if failed or not. You are using wrong operator "!=" in the if statement, so it is going to cart page for All status except failed one. You should use the "==" operator so that if the order status is equal to failed only then the statement will processed. The function you are using to get url is not compatible with new version of woocommerce, However you can use get_permalink( wc_get_page_id( 'cart' ) ) function to get the url of cart page.
Here is an example :
add_action( 'woocommerce_order_status_failed', 'mysite_failed');
function mysite_failed($order_id) {
$url = get_permalink( wc_get_page_id( 'cart' ) );
$order = new WC_Order( $order_id );
if ( $order->get_status() == 'failed' ) {
wp_redirect($url);
wp_redirect( $woocommerce->cart->wc_get_cart_url() ); // or whatever url you want
wc_add_notice ( __( 'Payment Failed', 'woocommerce' ), 'error');
exit;
}
}

Categories