WooCommerce - Different shipping methods for recurring orders - php

I am developing a site with the following plugins:
WooCommerce
WooCommerce Subscriptions
Pakkelabels.dk for WooCommerce
"Pakkelabels.dk" is a packaging label plugin for carriers in Denmark. This plugin is using the standard WooCommerce filters and hooks to add additional shipping methods.
I am using a mixed checkout. The cart totals currently looks like this:
This is what I wan't to do
For recurring orders I wan't to limit the shipping methods to just "DAO Pakkeshop" and "Local pick up" (sorry for the Danish language in the image).
I have added this to functions.php, which unsets the shipping methods I don't wan't to have, when a specific product ID (the subscription product) is in the cart:
add_filter( 'woocommerce_package_rates', 'hide_shipping_methods_woo_sg', 10, 2 );
function hide_shipping_methods_woo_sg( $rates, $package ) {
$product_id = get_field('product_auto_cart', 'option');
if($product_id){
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
if($in_cart) {
unset( $rates['pakkelabels_shipping_dao_direct'] );
unset( $rates['pakkelabels_shipping_gls_private'] );
unset( $rates['pakkelabels_shipping_gls_business'] );
unset( $rates['pakkelabels_shipping_gls'] );
unset( $rates['pakkelabels_shipping_pdk'] );
unset( $rates['pakkelabels_shipping_postnord_private'] );
unset( $rates['pakkelabels_shipping_postnord_business'] );
// unset( $rates['local_pickup:19'] );
}
return $rates;
}
}
My problem is, that this removes the shipping methods for both the order and recurring order, as you can see on the image.
I need some sort of conditional, so that I can target only the recurring order shipping methods and unset those.
How can I achieve this?

Okay - that was a simple fix. WC()->cart->recurring_carts was the conditional I needed. My code now looks like this:
add_filter( 'woocommerce_package_rates', 'hide_shipping_methods_woo_sg', 10, 2 );
function hide_shipping_methods_woo_sg( $rates, $package ) {
$product_id = get_field('product_auto_cart', 'option');
if($product_id){
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
if($in_cart && WC()->cart->recurring_carts) {
unset( $rates['pakkelabels_shipping_dao_direct'] );
unset( $rates['pakkelabels_shipping_gls_private'] );
unset( $rates['pakkelabels_shipping_gls_business'] );
unset( $rates['pakkelabels_shipping_gls'] );
unset( $rates['pakkelabels_shipping_pdk'] );
unset( $rates['pakkelabels_shipping_postnord_private'] );
unset( $rates['pakkelabels_shipping_postnord_business'] );
// unset( $rates['local_pickup:19'] );
}
return $rates;
}
}
The above shipping methods are now removed for recurring carts.
My cart totals now looks like this:

Related

WooCommerce after add to cart redirect to checkout

we are using WooCommerce Subscription and we want, that after a subscription is added to the cart redirect the customer to the checkout page. In the past I think there was a setting to set for this but I'm not able to find it. However, now I try to do it via code.
We use AJAX in order to add to the cart. But I think this will not work. And I have to disable ajax add to cart only for some products? Like check for a category?
So I have to disable ajax add to cart only for specific products and then redirect the customer when adding such a product to the cart to checkout. The code below works if I deactivate ajax add to cart for all products and also all product will redirect to the checkout. However, we only need it for specific products.
// redirect customer to checkout page
add_filter( 'woocommerce_add_to_cart_redirect', 'custom_skip_cart_redirect_checkout' );
function custom_skip_cart_redirect_checkout( $url ) {
return wc_get_checkout_url();
}
// Fix for “Sold Individually” Products
add_filter( 'woocommerce_product_add_to_cart_url', 'custom_fix_for_individual_products', 10, 2 );
function custom_fix_for_individual_products( $add_to_cart_url, $product ){
if( $product->get_sold_individually() // if individual product
&& WC()->cart->find_product_in_cart( WC()->cart->generate_cart_id( $product->id ) ) // if in the cart
&& $product->is_purchasable() // we also need these two conditions
&& $product->is_in_stock() ) {
$add_to_cart_url = wc_get_checkout_url();
}
return $add_to_cart_url;
}
// Remove “The product has been added to your cart” message
add_filter( 'wc_add_to_cart_message_html', 'custom_remove_add_to_cart_message' );
function custom_remove_add_to_cart_message( $message ){
return '';
}
Maybe it could help:
add_filter( 'woocommerce_add_to_cart_redirect', 'redirect_to_checkout_if_product_is_subscription', 99, 1 );
function redirect_to_checkout_if_product_is_subscription( $url ) {
if ( ! isset( $_REQUEST['add-to-cart'] ) ) {
return $url;
}
$product_id = intval( $_REQUEST['add-to-cart'] );
if ( $product_id <= 0 ) {
return $url;
}
$product = wc_get_product( $product_id );
if ( WC_Subscriptions_Product::is_subscription( $product ) ) {
$url = wc_get_checkout_url();
}
return $url;
}

Hide WooCommerce Payment Method Function Disables WordPress nav-menus.php

I have made hidden the other payment methods if selected COD method (which is flat_rate:5 in my case). I. am using Show hide payment methods based on selected shipping method in Woocommerce answer where I have made some minor edits.
The code works exactly as it should be however, I can't edit menus in "Appearance -> Menus" screen. It seems no problem in front-end.
function payment_gateways_based_on_chosen_shipping_method( $gateways ) {
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:5', $chosen_shipping_methods ) )
{
unset( $gateways['bacs'] );
unset( $gateways['iyzico'] );
}
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
I am totally confused where is the bug and why it only appears on "Appearence -> Menus" page.
Also this guy from WordPress support forum had encounter similar issue with different code but in same filter (woocommerce_available_payment_gateways).
Thank you.
That's because WC()->session is null on backoffice. So you can't call method "get".
You need to check if you are in admin area before execute your code:
function payment_gateways_based_on_chosen_shipping_method( $gateways ) {
if(is_admin()){
return $gateways;
}
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:5', $chosen_shipping_methods ) ){
unset( $gateways['bacs'] );
unset( $gateways['iyzico'] );
}
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );

Disable Free Shipping based on shipping classes in Woocommerce

I'm trying to write a function for WooCommerce that will disable free shipping if a product with a certain shipping class is present in the cart.
Here is what I have which is not working. e-packet is the shipping class that should disable free shipping if it is present in the cart.
function hide_shipping_when_class_is_in_cart( $rates, $package ) {
$shipping_classes = array('e-packet');
$if_exists = false;
foreach( $package['contents'] as $key => $values ) {
if( in_array( $values[ 'data' ]->get_shipping_class(), $shipping_classes ) )
$if_exists = true;
}
if( $if_exists ) unset( $rates['free_shipping:9'] );
return $rates;
}
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_class_is_in_cart', 10, 2 );
Based on similar: Unsetting WooCommerce shipping method based on cart items shipping classes
I have make very small changes. This code is tested and works (see the note at the end):
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_class_is_in_cart', 100, 2 );
function hide_shipping_when_class_is_in_cart( $rates, $package ) {
// Initialisation
$free_shipping_method = 'free_shipping:9';
$shipping_classes = array('e-packet');
$class_exists = false;
foreach( $package['contents'] as $cart_item )
if( in_array( $cart_item['data']->get_shipping_class(), $shipping_classes ) ) {
$class_exists = true;
break; // Stop the loop
}
if( $class_exists )
unset( $rates[$free_shipping_method] );
return $rates;
}
Code goes in function.php file of your active child theme (or active theme).
You should need to refresh the shipping caches:
1) First this code is already saved on your function.php file.
2) In Shipping settings, enter in a Shipping Zone and disable a Shipping Method and "save". Then re-enable that Shipping Method and "save". You are done.

Disable shipping method when a cart item has a specific shipping class?

I try to disable a shipping method if a specific shipping class is in the cart. I'm using the newest woocommerce version.
Below is my Code for my task.
It's placed at the end of my functions.php file of my Theme.
Sadly its not working.
add_filter( 'woocommerce_package_rates', 'businessbloomer_hide_free_shipping_for_shipping_class', 10, 2 );
function businessbloomer_hide_free_shipping_for_shipping_class( $rates, $package ) {
$shipping_class_target = 513; // ID OF MY SHIPPING_CLASS
$in_cart = false;
foreach( WC()->cart->cart_contents as $key => $values ) {
if( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
$in_cart = true;
break;
}
}
if( $in_cart ) {
unset( $rates['flat_rate:2'] ); //VALUE:ID OF MY SHIPPING METHOD
}
return $rates;
}
I have tested simplifying a little your code (with the ids of my WC settings) and it works:
add_filter( 'woocommerce_package_rates', 'custom_hide_shipping_methods', 10, 2 );
function custom_hide_shipping_methods( $rates, $package ) {
foreach( WC()->cart->get_cart() as $cart_item ) {
$product = $cart_item[ 'data' ]; // The WC_Product object
$shipping_class_id = $product->get_shipping_class_id();
if( isset($rates['flat_rate:2']) && $shipping_class_id == 513 ) { // <== ID OF MY SHIPPING_CLASS
unset( $rates['flat_rate:2'] ); // Removing specific shipping method
break; // we stop the loop
}
}
return $rates;
}
So your code should work too (if you have set the correct IDs)
BUT you need (after saving your code to the function.php file of your active theme):
To remove all cart items that are remaining in cart when testing.
To refresh the shipping caches:
To do it, you can go in a shipping zone and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done.
Now you can test again and it should work

Disabling BACS payment method for local delivery shipping method

How to disable BACS payment method for local delivery shipping method?
I have included the code below to my functions.php file, but it doesn't work.
Maybe someone could help me with this.
function my_custom_available_payment_gateways( $gateways ) {
$chosen_shipping_rates = WC()->session->get( 'chosen_shipping_methods' );
// When 'local delivery' has been chosen as shipping rate
if ( in_array( 'local_delivery', $chosen_shipping_rates ) ) :
// Remove bank transfer payment gateway
unset( $gateways['bacs'] );
endif;
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'my_custom_available_payment_gateways' );
You are not far. To make your code working you need to manipulate the data in the array of chosen shipping methods to get only the slugs in a foreach loop.
Here is the code:
add_filter( 'woocommerce_available_payment_gateways', 'unset_bacs_for_local_delivery' );
function unset_bacs_for_local_delivery( $gateways ) {
// Not in backend (admin)
if( is_admin() )
return $gateways;
// Initialising variables
$chosen_shipping_method_ids = array();
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
// Iterating and manipulating the "chosen shipping methods" to get the SLUG
foreach( $chosen_hipping_methods as $shipping_method_rate_id ) :
$shipping_method_array = explode(':', $shipping_method_rate_id);
$chosen_shipping_method_ids[] = $shipping_method_array[0];
endforeach;
//When 'local delivery' has been chosen as shipping method
if ( in_array( 'local_delivery', $chosen_shipping_method_ids ) ) :
// Remove bank transfer payment gateway
unset( $gateways['bacs'] );
endif;
return $gateways;
}
This code is tested and is fully functional.
Code goes in functions.php file of your active child theme (or theme). Or also in any plugin php files.

Categories