I have a woocommerce website & using PayU payment system. As of now when customer order fails, then the redirection is happening to order-pay endpoint & when order is success, page is redirecting to order-received endpoint. I need customer to redirect to a specific custom url when order fails and for success order, instead of redirecting to order-received endpoint, I would like to show the order summary details & prevent user from redirecting to home page.
I tried the below in functions.php
add_action( 'woocommerce_thankyou', 'test_func');
function test_func( $order_id ) {
$order = wc_get_order( $order_id );
$url1 = 'https://yoursite.com/custom-url-1';
$url2 = 'https://yoursite.com/custom-url-2';
if ( ! $order->has_status( 'failed' ) ) {
wp_safe_redirect( $url1 );
exit;
} else {
wp_safe_redirect( $url2 );
exit;
}
}
But still it is redirecting to the checkout end points mentioned.
I know that it is taking from the woocommerce checkout endpoints mentioned in the Advance Section, but can somebody please help me to find a workaround for this?
Any help would be really appreciated.
Thanks in Advance.
I have prepared a solution for your problem. I have tested your code and it looks like woocommerce has changed something or I don't know and this kind of code is not working anymore. But no worries. I have searched over the internet and found a good solution for you which I have prepared and tested on my staging website and it works great.
You need to use template_redirect and set it for checkout endpoint url (your case - order-received). Then you need to do the rest with the right functionality to make it work as you expect. Put my code bellow into the functions.php file of your theme and your problem should be solved. Do not forget to change endpoint url with the endpoint url of your website (order-received) and then change the url for failed order status (google.com) and other statuses (yahoo.com)
add_action( 'template_redirect', 'wc_thank_you_redirect' );
function wc_thank_you_redirect(){
if( isset( $_GET['key'] ) && is_wc_endpoint_url( 'order-received' ) ) { //change order-received to your endpoint if you will change it in the future
$order_id = wc_get_order_id_by_order_key( $_GET['key'] );
if ( ! empty( $order_id ) ) {
$order = wc_get_order( $order_id );
$order_status = $order->get_status();
if ('failed' == $order_status ) { //failed order status
wp_redirect( 'https://google.com' ); //change url here
exit;
} else {
wp_redirect( 'https://yahoo.com' ); //change url here for other statuses redirect
exit;
}
}
}
}
To do this with order-pay you could easily modify my function and change your endpoint url to order-pay and remove else from the function. To display order summary you need to set template for your new URL. Maybe it is better to redirect only failed orders and modify existing woocommerce template for your thank you page.
Related
In Wordpress/Woocommerce when clicking an order button, I would like it to skip the basket and immediately go to checkout. To this end, I implemented the following hook:
add_filter('add_to_cart_redirect', 'cw_redirect_add_to_cart');
function cw_redirect_add_to_cart() {
global $woocommerce;
$cw_redirect_url_checkout = $woocommerce->cart->get_checkout_url();
return $cw_redirect_url_checkout;
}
This works. However, in the scenario that the user already has the product in their basket and clicks on the order button, this would normally produce an error message "You cannot add another productname to your basket", which would be displayed on the basket page. But with the code snippet, in this scenario it just refreshes the page where the user clicked the order button and nothing happens. A user will not understand why the button doesn't work (only if they would manually type in the basket url, they will see the error message).
How, in this scenario, can I still redirect to the checkout page?
The hook add_to_cart_redirect you are using is deprecated from version 3.0.0 as the get_checkout_url method is deprecated from version 2.5.
The updated function can be found here: Woocommerce add to cart button redirect to checkout
Your problem is related to the woocommerce_add_to_cart_redirect hook not being executed in case there are any error notices. Below you will find the part of the code extracted from the WooCommerce source code:
// If we added the product to the cart we can now optionally do a redirect.
if ( $was_added_to_cart && 0 === wc_notice_count( 'error' ) ) {
$url = apply_filters( 'woocommerce_add_to_cart_redirect', $url, $adding_to_cart );
if ( $url ) {
wp_safe_redirect( $url );
exit;
} elseif ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
wp_safe_redirect( wc_get_cart_url() );
exit;
}
}
So to fix the problem you can find a solution here.The post includes a Fix for "Sold Individually" Products section that answers your question.
I'm redirecting woocomerce order received page when click on purchase buttom, but i need to show the product order details in my custom thankyou page, do you have any idea how to do this?
this is the code that I use to redirect to my custom thankyou page
add_action( 'woocommerce_thankyou', 'redirectcustom');
function redirectcustom( $order_id ){
$order = wc_get_order( $order_id );
$url = 'my_url_thankyoupage';
if ( ! $order->has_status( 'failed' ) ) {
wp_safe_redirect( $url );
exit;
}
}
you need to pass encrypted order id with url so you will have access to order detail from order id.
this is simple way to complete task otherwise there are many plugins available to change default thank you page
I have developed a web page and integrated Cc Avenue gateway for payment and it is working fine.
My problem is, after a successful payment from bank customer gets redirected to thank you page which will have details like order no, date, customer details etc. The URL looks something like: https://mysite/checkout/order-received/785/?key=wc_order_5b909f1966e92
If I manually change key=wc_order_5b909f1966e92 to key=wc_order_5b909f1966e81 it should show error on 'thank you' page like "invalid order". Instead it is showing "Thank you. Your order has been received." without any order details on the page.
Before changing key:
After changing key:
The following function will check order key validity. If the order key doesn't match, it will display a custom error notice (and optionally redirect to shop page if needed):
add_action( 'template_redirect', 'check_thankyou_order_key' );
function check_thankyou_order_key() {
if( is_wc_endpoint_url('order-received') && isset($_GET['key']) ) {
global $wp;
$order_id = absint( $wp->query_vars['order-received'] );
$order = wc_get_order( $order_id );
if( $order->get_order_key() != wc_clean($_GET['key']) ){
// Display a custom error notice
wc_add_notice( __('Oups! The order key is invalid…', 'woocommerce'), 'error');
// Optionally redirect to shop page (uncomment code below)
// wp_redirect( get_permalink( wc_get_page_id( 'shop' ) ) );
// exit();
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
With the optional redirection to shop page:
In Woocommerce, I would like to hide "paypal" gateway on the "checkout" page before the order is created for the first time and just show "cash on delivery" gateway (labeled as Reserve).
On the other hand, on checkout/order-pay page when the order status is "pending", hide the 'Reserve' gateway and show "paypal". (this happens when we change the status of the order to "pending" manually and send the invoice to the customer with a payment link).
I thought it should be done by checking order status and using the woocommerce_available_payment_gateways filter hook. But I have problems with getting current order status.
Also I'm not sure what's the status of a newly created order which the user is on the checkout page and still the order is not shown in the admin backend.
This is my incomplete code:
function myFunction( $available_gateways ) {
// How to check if the order's status is not pending payment?
// How to pass the id of the current order to wc_get_order()?
$order = wc_get_order($order_id);
if ( isset($available_gateways['cod']) && /* pending order status?? */ ) {
// hide "cod" gateway
} else {
// hide "paypal" gateway
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'myFunction' );
I also tried WC()->query_vars['order'] instead of wc_get_order(); to get the current order and check its status but it didn't work too.
I saw woocommerce_order_items_table action hook but couldn't get the order either.
How could I retrieve the Id and the status of the order on the checkout/order-pay page?
Update 2021
If I have correctly understood, You want to set/unset your available payment gateways, depending on the live generated order which status has to pending to have the "paypal" gateway. Ian all other cases the available gateway is only "reserve" (renamed "cod" payment gateway).
This code retrieve the live order ID using the get_query_var(), this way:
add_filter( 'woocommerce_available_payment_gateways', 'custom_available_payment_gateways' );
function custom_available_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
if ( is_wc_endpoint_url( 'order-pay' ) ) {
$order = wc_get_order( absint( get_query_var('order-pay') ) );
if ( is_a( $order, 'WC_Order' ) && $order->has_status('pending') ) {
unset( $available_gateways['cod'] );
}Â else {
unset( $available_gateways['paypal'] );
}
} else {
unset( $gateways['paypal'] );
}
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or theme) or also in any plugin file.
The code is tested and works.
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');