Woocommerce: redirect hook overruled by error - php

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.

Related

Change Woocommerce checkout end points to show order summary details

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.

Remove WooCommerce admin order action from order preview

I want to remove, for shop-managers, the ability to mark an order as completed. To do so, I used the following based on "Hide a specific action button conditionally in Woocommerce admin Orders list" answer in my theme's functions.php file:
add_filter( 'woocommerce_admin_order_actions', 'custom_admin_order_actions', 900, 2 );
function custom_admin_order_actions( $actions, $the_order ){
if(isset(wp_get_current_user()->roles[0]) && wp_get_current_user()->roles[0] == 'shop-manager')
unset($actions['complete']);
return $actions;
}
By this, I succesfully removed the complete button from the shop_order page. However, the shop-manager is still able to complete the order using the Complete button that appears in the order preview. To avoid this, I tried the next action after the previous one:
add_action( 'woocommerce_admin_order_preview_start', 'custom_display_order_data_in_admin' );
function custom_display_order_data_in_admin(){
// Call the stored value and display it
echo '<div>Class = "button hidden wc-action-button wc-action-button-complete complete"</div><br>';
}
However, this does not remove the button from the preview window because it does not substitute the line in the code.
Is there a way to remove this ability from the shop_order page and the order preview at once? If not, how can I hide this button from the preview window?
To remove the "complete" update order status button from admin order preview for "Shop manager" user role, use the following:
add_filter( 'woocommerce_admin_order_preview_actions', 'filter_admin_order_preview_actions', 10, 2 );
function filter_admin_order_preview_actions( $actions, $order ) {
if( current_user_can('shop-manager') && isset($actions['status']['actions']['complete']) ) {
unset($actions['status']['actions']['complete']);
}
return $actions;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Show an error if the order key is changed manually in URL on Woocommerce thankyou

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:

WooCommerce - Empty Cart on Page Reload

I have skipped the cart on my course membership site so 'Buy Now' brings you straight to checkout.
However, if you were logged in when you clicked 'Buy Now' then exit without buying, the item remains in the cart the next time you are logged in. If you go to purchase the same item during the next visit, it says "This item is already in your cart" but since I have the cart hidden from the front end, they can't access it.
Is it possible to empty the cart when page reloads with WooCommerce so it always goes straight to checkout when the user clicks 'Buy Now'?
Seems you're selling product individually. In this solution we're bypassing the filter hook woocommerce_add_to_cart_sold_individually_found_in_cart. When $found_in_cart is true users getting the message "This item is already in your cart". That's why we're resetting the quantity to 1. For more details please check https://docs.woocommerce.com/wc-apidocs/source-class-WC_Cart.html#1064
function op_bypass_add_to_cart_sold_individually_found_in_cart( $found_in_cart, $product_id ) {
if ( $found_in_cart ) {
$cart_contents = WC()->cart->get_cart_contents();
foreach ( $cart_contents as $key => $item ) {
if ( $product_id === $item['product_id'] ) {
WC()->cart->set_quantity( $key, 1 );
break;
}
}
return false;
}
return $found_in_cart;
}
add_filter( 'woocommerce_add_to_cart_sold_individually_found_in_cart', 'op_bypass_add_to_cart_sold_individually_found_in_cart', 10, 2 );
In my case " WC()->cart->set_quantity( $key, 1 );" from the answer #obiPlabon didn't worked proper, so I simplified function.
Since $found_in_cart is already fire only when amount of sold individually products in cart is more then one, I decided to simplify code and just make redirect to checkout page just it run.
if ( $found_in_cart ) {
global $woocommerce;
wp_redirect( wc_get_checkout_url() );
exit;
}

Woocommerce check if coupon already applied?

So on the checkout page, how can i tell if a coupon has previously been applied from the cart page? I can check this condition via jquery but the doesnt function how i want because that doesnt happen until the DOM has already loaded. I want the form-checkout.php page to check for the coupon before its sent to the user, so i can either hide or show <p class="woocommerce-info">Have a coupon? Click here to enter your code</p>
Try this code. This will hide 'Coupon form' on checkout page, if any coupon is already applied from cart
add_filter( 'woocommerce_coupons_enabled', 'woocommerce_coupons_enabled_checkout' );
function woocommerce_coupons_enabled_checkout( $coupons_enabled ) {
global $woocommerce;
if ( ! empty( $woocommerce->cart->applied_coupons ) ) {
return false;
}
return $coupons_enabled;
}
Hope this will be helpful

Categories