Hide WooCommerce payment methods for specific shipping zones and min subtotal - php

In WooCommerce, I'm trying to remove "Cash on delivery" payment method when cart subtotal is up to $250 for specific shipping zones names (Zone 1, Zone 4 and Zone 7).
All others zones must not have this restriction.
Here is my incomplete code based on this thread:
add_filter( 'woocommerce_available_payment_gateways', 'change_payment_gateway', 20, 1);
function change_payment_gateway( $gateways ){
$zone = $shipping_zone->get_zone_name();
if( WC()->cart->subtotal > 250 ) && if($zone=='Zone 1','Zone 4','Zone 7'){
unset( $gateways['cod'] );
}
return $gateways;
}
Any help is appreciated.

The following will remove "Cash on delivery" payment gateway for specific shipping zones and when cart subtotal is up to 250:
add_filter( 'woocommerce_available_payment_gateways', 'conditionally_remove_payment_methods', 20, 1);
function conditionally_remove_payment_methods( $gateways ){
// Not in backend (admin)
if( is_admin() )
return $gateways;
// HERE below your targeted zone names
$targeted_zones_names = array('Zone 1','Zone 4','Zone 7');
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); // The chosen shipping mehod
$chosen_method = explode(':', reset($chosen_methods) );
$shipping_zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $chosen_method[1] );
$current_zone_name = $shipping_zone->get_zone_name();
if( WC()->cart->subtotal > 250 && in_array( $current_zone_name, $targeted_zones_names ) ){
unset( $gateways['cod'] );
}
return $gateways;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Related

Display message based on shipping zone and shipping class on woocommerce checkout

i'm trying to display a message based on user's shipping zone when the users have a product with a specific shipping class in cart, in order to inform them the product isn't available for shipping in their shipping zone
so far, what i get is this, which i found on a similar post ( based on shipping zones x categories) and tried to adapt to my situation :
add_action( 'woocommerce_before_checkout_form', 'shipping_zone_targeted_postcodes_custom_notice' );
add_action( 'woocommerce_before_cart_table', 'shipping_zone_targeted_postcodes_custom_notice' );
function shipping_zone_targeted_postcodes_custom_notice() {
// HERE DEFINE YOUR SHIPPING ZONE NAME(S)
$targeted_zones_names = array('Province', 'Zone 1', 'Zone 2', 'Outre Mer 1', 'Outre Mer 2'); // <====== <====== <====== <======
// Get the customer shipping zone name
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); // The chosen shipping mehod
$chosen_method = explode(':', reset($chosen_methods) );
$shipping_zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $chosen_method[1] );
$current_zone_name = $shipping_zone->get_zone_name();
// Set your special category name, slug or ID here:
$shipping_classes = array('specific-shipping-class');
$bool = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( has_term( $shipping_classes, $cart_item['product_id'] ) )
$bool = true;
}
if( ! in_array( $current_zone_name, $targeted_zones_names ) && $bool ){
echo '<p class="zone-message-text"><span style="background:#e02b20;padding:20px;">MY CUSTOM MESSAGE</p>';
}
}
But it doesn't work. How could i fix this ?

Minimum order amount except for specific shipping method in WooCommerce

In WooCommerce, I use the following code to set a minimum order amount:
add_action( 'woocommerce_checkout_process', 'wc_minimum_order_amount' );
add_action( 'woocommerce_before_cart' , 'wc_minimum_order_amount' );
function wc_minimum_order_amount() {
$minimum = 50; // Hier gibst du den Mindestbestellwert ein
if ( WC()->cart->total < $minimum ) {
if( is_cart() ) {
wc_print_notice( sprintf( 'Der Mindestbestellwert beträgt %s pro Bestellung. Der aktuelle Bestellwert beträgt %s.' , // Text fuer Warenkorb
wc_price( $minimum ),
wc_price( WC()->cart->total )
), 'error' );
} else {
wc_add_notice( sprintf( 'Der Mindestbestellwert beträgt %s pro Bestellung. Der aktuelle Bestellwert beträgt %s.' , // Text fuer Kasse
wc_price( $minimum ),
wc_price( WC()->cart->total )
), 'error' );
}
}
}
Now if the customer chooses "self pickup" ("Local pickup shipping method), I don't want any minimum required order amount.
How can I set Minimum order amount except for "Local pickup" shipping method in WooCommerce?
Based on Getting minimum order amount for 'Free Shipping' method in checkout page answer code and also Set a minimum order amount in WooCommerce answer code, here is the correct way to set a Minimum order amount except for specific shipping method in WooCommerce:
add_action( 'woocommerce_check_cart_items', 'wc_minimum_required_order_amount' );
function wc_minimum_required_order_amount() {
// HERE Your settings
$minimum_amount = 50; // The minimum cart total amount
$shipping_method_id = 'local_pickup'; // The targeted shipping method Id (exception)
// Get some variables
$cart_total = (float) WC()->cart->total; // Total cart amount
$chosen_methods = (array) WC()->session->get( 'chosen_shipping_methods' ); // Chosen shipping method rate Ids (array)
// Only when a shipping method has been chosen
if ( ! empty($chosen_methods) ) {
$chosen_method = explode(':', reset($chosen_methods)); // Get the chosen shipping method Id (array)
$chosen_method_id = reset($chosen_method); // Get the chosen shipping method Id
}
// If "Local pickup" shipping method is chosen, exit (no minimun is required)
if ( isset($chosen_method_id) && $chosen_method_id === $shipping_method_id ) {
return; // exit
}
// Add an error notice is cart total is less than the minimum required
if ( $cart_total < $minimum_amount ) {
wc_add_notice( sprintf(
__("The minimum required order amount is %s (your current order amount is %s).", "woocommerce"), // Text message
wc_price( $minimum_amount ),
wc_price( $cart_total )
), 'error' );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
or also you can use:
add_action( 'woocommerce_checkout_process', 'wc_minimum_required_order_amount' );
add_action( 'woocommerce_before_cart' , 'wc_minimum_required_order_amount' );
function wc_minimum_required_order_amount() {
// HERE Your settings
$minimum_amount = 100; // The minimum cart total amount
$shipping_method_id = 'local_pickup'; // The targeted shipping method Id (exception)
// Get some variables
$cart_total = (float) WC()->cart->total; // Total cart amount
$chosen_methods = (array) WC()->session->get( 'chosen_shipping_methods' ); // Chosen shipping method rate Ids (array)
// Only when a shipping method has been chosen
if ( ! empty($chosen_methods) ) {
$chosen_method = explode(':', reset($chosen_methods)); // Get the chosen shipping method Id (array)
$chosen_method_id = reset($chosen_method); // Get the chosen shipping method Id
}
// If "Local pickup" shipping method is chosen, exit (no minimun is required)
if ( isset($chosen_method_id) && $chosen_method_id === $shipping_method_id ) {
return; // exit
}
// Add an error notice is cart total is less than the minimum required
if ( $cart_total < $minimum_amount ) {
$text_notice = sprintf(
__("The minimum required order amount is %s (your current order amount is %s).", "woocommerce"), // Text message
wc_price( $minimum_amount ),
wc_price( $cart_total )
);
if ( is_cart() ) {
wc_print_notice( $text_notice, 'error' );
} else {
wc_add_notice( $text_notice, 'error' );
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Applied coupons disable Free shipping conditionally in Woocommerce

I am trying to get it so that if a customer were to add a coupon code (Any of them) the Free Shipping option would go away and the flat rate fee would be implemented. - You would think this would be an easy thing to implement, there would be 100's of plugins and ways described to do this, but I have not found any. I do not want to pay $89 for the plugin to do this one thing
A side bonus would be if they are using a coupon but are spending over $249 they can still qualify for Free shipping. I read some where how to do this, but it requires me to get the POST ID, which with the latest WooCommerce is not possible like it was before, I do not know the shipping ID so I am at a lost Here is the code
add_filter( 'woocommerce_shipping_packages', function( $packages ) {
$applied_coupons = WC()->session->get( 'applied_coupons', array() );
if ( ! empty( $applied_coupons ) ) {
$free_shipping_id = 'free_shipping:2';
unset($packages[0]['rates'][ $free_shipping_id ]);
}
return $packages;
} );
Thanks
Edited
add_filter( 'woocommerce_package_rates', 'coupons_removes_free_shipping',
10, 2 );
function coupons_removes_free_shipping( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
$min_total = 250; // Minimal subtotal allowing free shipping
// Get needed cart totals
$total_excl_tax = WC()->cart->get_total();
$discount_excl_tax = WC()->cart->get_discount_total();
// Calculating the discounted subtotal including taxes
$discounted_subtotal_incl_taxes = $total_excl_tax - $discount_excl_tax;
$applied_coupons = WC()->cart->get_applied_coupons();
if( sizeof($applied_coupons) > 0 && $discounted_subtotal_incl_taxes < $min_total ) {
foreach ( $rates as $rate_key => $rate ){
// Targeting "Free shipping"
if( 'free_shipping' === $rate->method_id ){
unset($rates[$rate_key]);
}
}
}
return $rates;
}
The below code will enable "Free shipping" for applied coupons only if cart subtotal reaches a minimal amount (discounted including taxes):
add_filter( 'woocommerce_package_rates', 'coupons_removes_free_shipping', 10, 2 );
function coupons_removes_free_shipping( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
$min_subtotal = 250; // Minimal subtotal allowing free shipping
// Get needed cart subtotals
$subtotal_excl_tax = WC()->cart->get_subtotal();
$subtotal_incl_tax = $subtotal_excl_tax + WC()->cart->get_subtotal_tax();
$discount_excl_tax = WC()->cart->get_discount_total();
$discount_incl_tax = $discount_total + WC()->cart->get_discount_tax();
// Calculating the discounted subtotal including taxes
$discounted_subtotal_incl_taxes = $subtotal_incl_tax - $discount_incl_tax;
$applied_coupons = WC()->cart->get_applied_coupons();
if( sizeof($applied_coupons) > 0 && $discounted_subtotal_incl_taxes < $min_subtotal ){
foreach ( $rates as $rate_key => $rate ){
// Targeting "Free shipping"
if( 'free_shipping' === $rate->method_id ){
unset($rates[$rate_key]);
}
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
Original answer:
The below code will remove "Free shipping" shipping methods when any coupon is applied without any settings need. There is some mistakes in your actual code. Try the following:
add_filter( 'woocommerce_package_rates', 'coupons_removes_free_shipping', 10, 2 );
function coupons_removes_free_shipping( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
$applied_coupons = WC()->cart->get_applied_coupons();
if( sizeof($applied_coupons) > 0 ){
// Loop through shipping rates
foreach ( $rates as $rate_key => $rate ){
// Targeting "Free shipping" only
if( 'free_shipping' === $rate->method_id ){
unset($rates[$rate_key]); // Removing current method
}
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
By default WooCommerce will still allow a free shipping method to be selected if the coupon code is filled in and active in the shopping cart. The following code can be added to your child’s functions.php page to hook in and hide any free shipping option if a coupon code is used.
add_filter( 'woocommerce_shipping_packages', function( $packages ) {
$applied_coupons = WC()->session->get( 'applied_coupons', array() );
if ( ! empty( $applied_coupons ) ) {
$free_shipping_id = 'free_shipping:2';
unset($packages[0]['rates'][ $free_shipping_id ]);
}
return $packages;
} );
Simply change the $free_shipping_id in the above code to the ID of your free shipping option. You may find your ID by going to WooCommerce > Settings > Shipping Options and then click on your Free Shipping option. The post ID will be in the URL of the page that displays the Free Shipping details/settings.
i.e www.yourdomain.com/wp-admin/post.php?post=40107&action=edit
Where 40107 is the shipping ID in this example. Your shipping ID will be different.

Change Flat rate shipping method cost if a specific coupon is applied in Woocommerce

I have a specific coupon which is special50. When someone applied this coupon on the store then a new shipping method need to add. When current shipping method price is $50 (flat rate) and after applying coupon new shipping method, pricing will be $25. In a word, if you apply this coupon you will receive 50% OFF on products(which WooCommerce has already provided to us) and 50% OFF on shipping(which really I need).
add_action( 'woocommerce_flat_rate_shipping_add_rate', 'add_another_custom_flat_rate', 10, 2 );
function add_another_custom_flat_rate( $method, $rate ) {
$new_rate = $rate;
$new_rate['id'] .= ':' . 'custom_rate_name';
$new_rate['label'] = 'Shipping and handling';
global $woocommerce, $wpdb;
$coupon = "SELECT post_title FROM {$wpdb->posts} WHERE post_title='special50' AND post_type ='shop_coupon' AND post_status ='publish'";
if(in_array($coupon_id, $woocommerce->cart->applied_coupons)){
$cost = 25;
}
$new_rate['cost'] = $cost;
$method->add_rate( $new_rate );
}
This can be done using the following custom function hooked in woocommerce_package_rates filter hook, without any need of creating an additional discounted flat rate. The following code will change the "flat rate" shipping method cost when 'special50' coupon is applied.
You should first "Enable debug mode" in Woocommerce settings > shipping > Shipping options.
The code:
add_filter('woocommerce_package_rates', 'coupon_discount_on_flat_rate', 10, 2);
function coupon_discount_on_flat_rate( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
// Checking for 'special50' in applied coupons
if( in_array( 'special50', WC()->cart->get_applied_coupons() ) ){
foreach ( $rates as $rate_key => $rate ){
$has_taxes = false;
// Targeting "flat rate" shipping method
if( $rate->method_id === 'flat_rate' ){
// Set 50% of the cost
$rates[$rate_key]->cost = $rates[$rate_key]->cost / 2;
// Taxes rate cost (if enabled)
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $rates[$rate_key]->taxes[$key] > 0 ){
$has_taxes = true;
// set 50% of the cost
$taxes[$key] = $rates[$rate_key]->taxes[$key] / 2;
}
}
if( $has_taxes )
$rates[$rate_key]->taxes = $taxes;
}
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Dont forget to disable "Enable debug mode" once this has been tested and works.

Tiered Shipping based on cart subtotal in Woocommerce

In Woocommerce, I need to set up shipping costs based on cart subtotal as following:
if price is below 20€ the shipping cost is 5,90€,
if price start from 20€ and below 30€ the shipping cost 4,90€
if price start from 30€ and up the shipping cost 3,90€.
I have very basic PHP knowledge and have modified a code snippet that I have found.
This is my code:
add_filter('woocommerce_package_rates','bbloomer_woocommerce_tiered_shipping', 10, 2 );
function bbloomer_woocommerce_tiered_shipping( $rates, $package){
$threshold1 = 20;
$threshold2 = 30;
if ( WC()->cart->subtotal < $threshold1 ){
unset( $rates['flat_rate:5'] );
unset($rates['flat_rate:6']);
} elseif((WC()->cart->subtotal>$threshold1)and(WC()->cart->subtotal<$threshold2) ) {
unset( $rates['flat_rate:1'] );
unset( $rates['flat_rate:6'] );
} elseif((WC()->cart->subtotal > $threshold2) and (WC()->cart->subtotal > $threshold1) ) {
unset( $rates['flat_rate:1'] );
unset( $rates['flat_rate:5'] );
}
return $rates;
}
This seems to be working, but sometimes (and I have not figured out the trigger!) it doesn't and all three shipping methods show up in the cart. I think I noticed that it only happens when a user is logged in, but I am not 100% sure on this.
Is my function is correct? Do need to change or improve anything?
I have revisited your code a bit. You should try the following:
add_filter('woocommerce_package_rates','subtotal_based_tiered_shipping', 10, 2 );
function subtotal_based_tiered_shipping( $rates, $package ){
$threshold1 = 20;
$threshold2 = 30;
$subtotal = WC()->cart->subtotal;
if ( $subtotal < $threshold1 )
{ // Below 20 ('flat_rate:1' is enabled)
unset( $rates['flat_rate:5'] );
unset( $rates['flat_rate:6'] );
}
elseif ( $subtotal >= $threshold1 && $subtotal < $threshold2 )
{ // Starting from 20 and below 30 ('flat_rate:5' is enabled)
unset( $rates['flat_rate:1'] );
unset( $rates['flat_rate:6'] );
}
elseif ( $subtotal >= $threshold2 )
{ // Starting from 30 and up ('flat_rate:6' is enabled)
unset( $rates['flat_rate:1'] );
unset( $rates['flat_rate:5'] );
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme).
It should works now as intended.
To make it work with "Free shipping" methods too, you will have to disable "Free shipping requires..." option (set to "N/A").
Sometimes you should need to refresh shipping caches:
Once saved this code and emptied cart, go to your shipping settings. In your shipping zone, disable save and re-enable save your shipping methods.

Categories