I'm using woocommerce bookings.
I'm trying to trigger woocommerce order status to refund if the woocommerce_booking status is cancelled. I tried this code but it's not working.
global $woocommerce;
$order = new WC_Order( $order_id );
if ( 'cancelled' == $order->status ) {
$order->update_status('refund', 'order_note');
}
To update order status on cancel status
add_action('woocommerce_cancelled_order','change_status_to_refund', 10, 1);
function change_status_to_refund($order_id) {
$order = new WC_Order( $order_id );
$order->update_status('refund', 'order_note');
exit;
}
I hope it will help you. Thanks :)
add_action( 'woocommerce_order_status_changed', 'wc_order_status_changed', 99, 3 );
function wc_order_status_changed( $order_id, $old_status, $new_status ){
if( $new_status == "cancelled" || $new_status == "refunded" ) {
//code here.
}
}
If you want use in some class action must be like this:
add_action( 'woocommerce_order_status_changed', array($this, 'wc_order_status_changed'), 99, 3 );
You need to fetch the status of your order and then check your required condition and update it accordingly.
$order_status = $order->get_status();
I know this is an old post, but i have just make it on my latest wordpress/woocommerce install
add_action('woocommerce_booking_cancelled', 'my_booking_cancelled_handler', 10, 1);
function my_booking_cancelled_handler ( $booking_id ) {
$booking = new WC_Booking( $booking_id );
$order_id = $booking->get_order_id();
// check order for your business logic
// refund or not ;-) it's up to you
}
I hope this helps someone.
//Try this
add_action( 'woocommerce_order_status_changed', 'auto_destroy_failed_orders', 10, 4 );
function auto_destroy_failed_orders( $order_id, $old_status, $new_status, $order )
{
if ( ( $new_status == 'completed' )) {
// Order status complete
$order->update_status( 'custom-status' );
}else if ( ( $new_status == 'failed' )) {
$order->update_status( 'custom-status' );
}else if ( ( $new_status == 'b2c-shipment' )) {
// custome status
$order->update_status( 'custom-status' );
}else if ( ( $new_status == 'on-hold' )) {
// Order status to on-hold
$order->update_status( 'custom-status' );
}else if ( ( $new_status == 'refunded' )) {
// Order status to refunded
$order->update_status( 'custom-status' );
}else if ( ( $new_status == 'failed' )) {
// Order status to failed
$order->update_status( 'custom-status' );
}else if ( ( $new_status == 'processing' ) ) {
// Order status to processing
$order->update_status( 'custom-status' );
}
}
Hey you can try this hook!!
https://therichpost.com/change-product-order-status-woocommerce-hook
Hope this will help you
Related
I want when a customer chooses to pay through Email Transfer (Interac) to go ahead and set the order status to Pending etransfer.
– My custom gateway name is custom_b9599316cc4fd28.
– My custom status slug is pending-etransfer.
add_action( 'woocommerce_order_status_changed', 'woocommerce_payment_complete_order_status', 10, 3 );
function woocommerce_payment_complete_order_status( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
if ( $order->data['status'] == 'processing' ) {
$payment_method = $order->get_payment_method();
if ( $payment_method != 'custom_b9599316cc4fd28' ) {
$order->update_status( 'pending-etransfer' );
}
}
}
Any help is greatly appreciated.
The code as you see it.
I need Telegram notifications to be sent when the order status is "Processing", so I have this code:
add_action( 'woocommerce_new_order', 'new_order_send_tg', 1, 1 );
function new_order_send_tg( $order_id ) {
$order = wc_get_order( $order_id );
$msg .= '✅ Order № '.$order_id . ' *success*';
$userId = '-xxxxxxxxxxxxxx'; // ID Chat
$token = 'xxxxxxxxxxxxxxxxxxxxxxxx'; // Token bot
if( 'processing' == $order->get_status() ) {
file_get_contents('https://api.telegram.org/bot'. $token .'/sendMessage?chat_id='. $userId .'&text=' . urlencode($msg) . '&parse_mode=markdown'); // Send
} else {
//
}
}
Without the if( 'processing' == $order->get_status() ) condition, everything works as expected. But with the if condition added this doesn't seem to be the case. Any advice?
It looks like the woocommerce_new_order hook is executed before the order status is changed to processing
function action_woocommerce_new_order( $order_id, $order = null ) {
// Get order
$order = is_a( $order, 'WC_Order' ) ? $order : wc_get_order( $order_id );
$status = $order->get_status();
// Result: status = pending
}
add_action( 'woocommerce_new_order', 'action_woocommerce_new_order', 10, 2 );
So you can use the woocommerce_order_status_' . $status_transition['to'] composite action hook instead, where you will replace $status_transition[to] by processing
function action_woocommerce_order_status_processing( $order_id, $order ) {
// Do your thing
}
add_action( 'woocommerce_order_status_processing', 'action_woocommerce_order_status_processing', 10, 2 );
I need to automatically set a certain order status (different than processing) when getting a new order.
This is achieved by this function:
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) { return; }
$order = wc_get_order( $order_id );
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
This totally works. Now I only need this to happen when a product has a customization.
The way to customize a product is filling an input field before adding to cart. The input is attached to the item data:
// Add custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_cart_item_data', 10, 2 );
function add_custom_cart_item_data( $cart_item_data, $product_id ){
if( isset($_POST['custom_text']) ) {
$cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
$cart_item_data['unique_key'] = md5( microtime().rand() ); // Make each item unique
}
return $cart_item_data;
}
Then the custom text is retrieved and displayed in cart and in the order data using this:
// Display custom cart item data on cart and checkout
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_item_data, $cart_item ) {
if ( !empty( $cart_item['custom_text'] ) ){
$cart_item_data[] = array(
'name' => __('Customization', 'woocommerce'),
'value' => $cart_item['custom_text'] // Already sanitized field
);
}
return $cart_item_data;
}
// Save and display custom item data everywhere on orders and email notifications
add_action( 'woocommerce_checkout_create_order_line_item', 'add_product_custom_field_as_order_item_meta', 10, 4 );
function add_product_custom_field_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
if ( isset($values['custom_text']) ) {
$item->update_meta_data('Add on', $values['custom_text'] );
}
}
I'm trying using the if ( isset($values['custom_text']) ) part as a trigger of the function to change the order status only if the product add on is set and other similar methods (like if ( !empty( $cart_item['custom_text'] ) ) but I'm not sure this is the way to go:
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) {return;}
$order = wc_get_order( $order_id );
if ( isset($values['custom_text']) ) {
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
}
This above does nothing. Am I anywhere near it with this approach?
EDIT: I tried this too
add_action('woocommerce_thankyou','change_order_status');
function change_order_status( $order_id ) {
if ( ! $order_id ) {return;}
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item_id => $item ) {
$allmeta = $item->get_meta_data();
if ( isset($values['custom_text']) ) {
if( 'processing'== $order->get_status() ) {
$order->update_status( 'wc-custom-status' );
}
}
}
}
Your code contains some unnecessary steps as well as some shortcomings
For example, the woocommerce_add_cart_item_data hook contains 3 arguments versus 2
So you get:
// Add custom cart item data
function filter_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
// Isset and NOT empty
if ( isset ( $_POST[ 'custom_text' ] ) && ! empty ( $_POST[ 'custom_text' ] ) ) {
$cart_item_data['custom_text'] = sanitize_text_field( $_POST['custom_text'] );
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data', 10, 3 );
// Display custom cart item data on cart and checkout
function filter_woocommerce_get_item_data( $cart_data, $cart_item = null ) {
if ( isset ( $cart_item['custom_text'] ) ) {
$cart_data[] = array(
'name' => __( 'Customization', 'woocommerce' ),
'value' => $cart_item['custom_text']
);
}
return $cart_data;
}
add_filter( 'woocommerce_get_item_data', 'filter_woocommerce_get_item_data', 10, 2 );
// Add the information as meta data so that it can be seen as part of the order
// Save and display custom item data everywhere on orders and email notifications
function action_woocommerce_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
if ( isset ( $values['custom_text'] ) ) {
$item->update_meta_data( 'custom_text', $values['custom_text'] );
}
}
add_action( 'woocommerce_checkout_create_order_line_item', 'action_woocommerce_checkout_create_order_line_item', 10, 4 );
// On thankyou page
function action_woocommerce_thankyou( $order_id ) {
// Get $order object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// Only when the current order status is 'processing'
if ( $order->get_status() == 'processing' ) {
// Loop trough
foreach ( $order->get_items() as $item ) {
// Get meta
$value = $item->get_meta( 'custom_text' );
// NOT empty
if ( ! empty ( $value ) ) {
// Update status (change to desired status)
$order->update_status( 'cancelled' );
// Stop loop
break;
}
}
}
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
Currently it is just checking if the value exists, to compare it effectively
Change
// NOT empty
if ( ! empty ( $value ) ) {
// Update status
$order->update_status( 'cancelled' );
// Stop loop
break;
}
To
// Compare
if ( $value == 'some value' ) ) {
// Update status
$order->update_status( 'cancelled' );
// Stop loop
break;
}
This question already has answers here:
Disable specific payment methods depending on Woocommerce order status
(2 answers)
Closed 2 years ago.
help i get this error
I am doing the same function Disable specific payment methods depending on Woocommerce order status I get
Copy and paste the same code and it didn't work
syntax error, unexpected 'elseif' (T_ELSEIF)
add_filter( 'woocommerce_available_payment_gateways', 'conditionally_hide_payment_gateways', 100, 1 );
function conditionally_hide_payment_gateways( $available_gateways ) {
// 1. On Order Pay page
if( is_wc_endpoint_url( 'order-pay' ) ) {
// Get an instance of the WC_Order Object
$order = wc_get_order( get_query_var('order-pay') );
// Loop through payment gateways 'pending', 'on-hold', 'processing'
foreach( $available_gateways as $gateways_id => $gateways ){
// Keep paypal only for "pending" order status
elseif ($gateways_id !== 'paypal' && $order->has_status('pending') ) {
unset($available_gateways[$gateways_id]);
}
}
}
// 2. On Checkout page
elseif( is_checkout() && ! is_wc_endpoint_url() ) {
// Disable paypal
if( isset($available_gateways['paypal']) ) {
unset($available_gateways['paypal']);
}
}
return $available_gateways;
}
enter image description here
The elseif inside the foreach doesn't have a preceding if, so that's your error.
add_filter( 'woocommerce_available_payment_gateways', 'conditionally_hide_payment_gateways', 100, 1 );
function conditionally_hide_payment_gateways( $available_gateways ) {
// 1. On Order Pay page
if( is_wc_endpoint_url( 'order-pay' ) ) {
// Get an instance of the WC_Order Object
$order = wc_get_order( get_query_var('order-pay') );
// Loop through payment gateways 'pending', 'on-hold', 'processing'
foreach( $available_gateways as $gateways_id => $gateways ){
// Keep paypal only for "pending" order status
if ($gateways_id !== 'paypal' && $order->has_status('pending') ) {
unset($available_gateways[$gateways_id]);
}
}
}
// 2. On Checkout page
elseif( is_checkout() && ! is_wc_endpoint_url() ) {
// Disable paypal
if( isset($available_gateways['paypal']) ) {
unset($available_gateways['paypal']);
}
}
return $available_gateways;
}
I've been asked to configure a specific WooCommerce behaviour, and I can't escape having to do it with filters. Which I'm not really competent in.
What is supposed to happen, exactly, is that when an order consists only of a product from the "abo" category, it is automatically marked as 'Complete' and the admin mail is sent to a different service.
I've gathered a few examples of code, changing the e-mail recipient, the order status, or making generic changes according to the product category. This is my Frankenstein monster of a code. Both the e-mail change and the order status change failed.
/**
* Change email recipient for admin New Order emails when the order only has products from the 'abo' category
*
* #param string $recipient a comma-separated string of email recipients (will turn into an array after this filter!)
* #param \WC_Order $order the order object for which the email is sent
* #return string $recipient the updated list of email recipients
*/
add_filter( 'woocommerce_email_recipient_new_order', 'dada_conditional_email_recipient', 10, 2 );
function dada_conditional_email_recipient( $recipient, $order ) {
// Bail on WC settings pages since the order object isn't yet set yet
// Not sure why this is even a thing, but shikata ga nai
$page = $_GET['page'] = isset( $_GET['page'] ) ? $_GET['page'] : '';
if ( 'wc-settings' === $page ) {
return $recipient;
}
// just in case
if ( ! $order instanceof WC_Order ) {
return $recipient;
}
$items = $order->get_items();
foreach ( $items as $item ) {
$product = $order->get_product_from_item( $item );
// check if there's an "abo" in the order, then if there's anything else.
if ( is_product() && has_term( 'abo', 'product_cat' ) ) {
$abo_in_order = 'true';
}
if ( is_product() && has_term( 'livre', 'product_cat' ) || has_term( 'revue', 'product_cat' ) || has_term( 'livre', 'product_cat' ) ) {
$abo_alone_in_order = 'false';
}
else {
$abo_alone_in_order = 'true';
}
}
// if there's an 'abo' and nothing else, change the e-mail recipient to dada#sotiaf.fr
if ( ($abo_in_order == 'true')&&($abo_alone_in_order == 'true') ) $recipient = 'dada#sotiaf.fr';
return $recipient;
}
/**
* Autocomplete orders with only an 'abo' product
*/
add_filter( 'woocommerce_payment_complete_order_status', 'dada_abo_order_autocomplete', 10, 2 );
function dada_abo_order_autocomplete( $order_status, $order_id ) {
$order = wc_get_order( $order_id );
if ('processing' == $order_status && ('on-hold' == $order->status || 'pending' == $order->status || 'failed' == $order->status)) {
// just in case
if ( ! $order instanceof WC_Order ) {
return $order_status;
}
$items = $order->get_items();
foreach ( $items as $item ) {
$product = $order->get_product_from_item( $item );
// check if there's an "abo" in the order, then if there's anything else.
if ( is_product() && has_term( 'abo', 'product_cat' ) ) {
$abo_in_order = 'true';
}
if ( is_product() && has_term( 'livre', 'product_cat' ) || has_term( 'revue', 'product_cat' ) || has_term( 'livre', 'product_cat' ) ) {
$abo_alone_in_order = 'false';
}
else {
$abo_alone_in_order = 'true';
}
}
// if there's an 'abo' and nothing else, change the order status to 'completed'
if ( ($abo_in_order == 'true')&&($abo_alone_in_order == 'true') ) $order_status = 'completed';
}
return $order_status;
}
Any idea where the issue comes from?
Thank you,
Joss
You should implement "woocommerce_thankyou" hook for order status update instead of "woocommerce_payment_complete_order_status". Because, your current update order status code will trigerr when any order with completed status is placed. But your requirement is to change status to "Completed".
For adding new email recepient dynamically, you should try this hook : "woocommerce_email_recipient_new_order"
Refer to this : WooCommerce send new order email to customer