WooCommerce checkout - how to give free shipping for a specific address - php

The following code will allow free shipping for a specific product:
function wcs_my_free_shipping( $is_available ) {
global $woocommerce;
// set the product ids that are eligible
$eligible = array( '360' );
// get cart contents
$cart_items = $woocommerce->cart->get_cart();
// loop through the items looking for one in the eligible array
foreach ( $cart_items as $key => $item ) {
if( in_array( $item['product_id'], $eligible ) ) {
return true;
}
}
// nothing found return the default value
return $is_available;
}
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'wcs_my_free_shipping', 20 );
What I would like to do is allow free shipping not for a product, but for a specific street and zip code combination in the delivery address. I found out how to check this for a logged-in user, but can't seem to find the right variables that have this information at checkout. Any help would be greatly appreciated.
Thanks in advance,
-Ben

There are Shipping zones available in Woocommerce already. For each specific zone you can set the shipping method either "Flat rate" or "Free Shipping". You can check it under Woocommerce->Settings. Find Shipping tab.
Screenshot for shipping tab

Yes you can, there is an extra parameter you can pass into this hook names $package.
for eg.
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'wcs_my_free_shipping', 20,2 );
function wcs_my_free_shipping( $is_available, $package){
//Your code for free shipping for a selected address found in $package
return $is_available
}
$package contains the address you entered so you can use this to apply free shipping for selected zip codes or streets

Related

Disable free shipping for specific coupon codes in WooCommerce

I am trying to remove the free shipping option in Woocommerce when someone uses a specific coupon code. I found this question which is very relevant to my question. The answer bellow seems really close to what I am looking for. I am new to php and trying to figure out where I would add an id for the coupon code I want to exclude.
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;
});
This is my first question on stack over flow but this site has helped me so much with so many issues. Forgive me if I am asking too much. Thanks in advance for any help/guidance.
Use instead woocommerce_package_rates filter hook. In the code below you will set the related coupon codes that will hide the free shipping method:
add_filter( 'woocommerce_package_rates', 'hide_free_shipping_method_based_on_coupons', 10, 2 );
function hide_free_shipping_method_based_on_coupons( $rates, $package )
{
$coupon_codes = array('summer'); // <== HERE set your coupon codes
$applied_coupons = WC()->cart->get_applied_coupons(); // Applied coupons
if( empty($applied_coupons) )
return $rates;
// For specific applied coupon codes
if( array_intersect($coupon_codes, $applied_coupons) ) {
foreach ( $rates as $rate_key => $rate ) {
// Targetting "Free shipping"
if ( 'free_shipping' === $rate->method_id ) {
unset($rates[$rate_key]); // hide free shipping method
}
}
}
return $rates;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Clearing shipping caches:
You will need to empty your cart, to clear cached shipping data
Or In shipping settings, you can disable / save any shipping method, then enable back / save.

Hide shipping address at woocommerce checkout based on a shipping table rate choice

I have been working to hide my woocommerce checkout shipping address if a user selects a shipping table rate option that has a Label of "Local Pickup". Most code snippets I have found trigger based on shipping_method. I tried a shipping-method like `table_rate:10:1', to no avail. Any ideas?
Also, I am not completely clear on how to designate the specific row in the table - I inspected the code and found the value above, but am unsure if its correct.
Shipping related plug-ins: Woocommerce Table Rate Shipping
Trying to use the following code as a base:
add_filter( 'woocommerce_checkout_fields', 'xa_remove_billing_checkout_fields' );
function xa_remove_billing_checkout_fields( $fields ) {
global $woocommerce;
// Set the desired shipping method to hide the checkout field(s).
$shipping_method = 'table_rate:10:1';
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( $chosen_shipping == $shipping_method ) {
// Add/change field name to be hide
unset($fields['billing']['billing_address_1']);
unset($fields['billing']['billing_address_2']);
}
return $fields;
}
website: camp4coffee.com

Set "flat rate" shipping method as default in woocommerce

I have a woocommerce website and I have set 2 shipping methods:
Flat Rate
Local pickup
I would like to set the "Flat rate" shipping method as default (selected) in the cart or checkout page.
1) You can use the following code (to set "flat rate" shipping method as default) In cart page:
add_action( 'woocommerce_before_cart', 'set_default_chosen_shipping_method', 5 );
function set_default_chosen_shipping_method(){
//
if( count( WC()->session->get('shipping_for_package_0')['rates'] ) > 0 ){
foreach( WC()->session->get('shipping_for_package_0')['rates'] as $rate_id =>$rate)
if($rate->method_id == 'flat_rate'){
$default_rate_id = array( $rate_id );
break;
}
WC()->session->set('chosen_shipping_methods', $default_rate_id );
}
}
Code goes in function.php file of your active child theme (active theme or in any plugin file).
Tested and Works in WooCommerce 3+
2) You can also reorder the shipping rates in your shipping zones settings (but it doesn't really works as the last chosen shipping method take the hand).
You could use the following code to set 'any' shipping method as default.
function reset_default_shipping_method( $method, $available_methods ) {
$default_method = 'wf_fedex_woocommerce_shipping:FEDEX_GROUND'; //provide the service name here
if( array_key_exists($method, $available_methods ) )
return $default_method;
else
return $method;
}
Let's say, you're using a Carrier shipping plugin like WooCommerce FedEx Shipping Plugin. You can fetch the value Id (shown below) and paste it under the '$default_method' in the above code.
You will have to copy and paste the code in WordPress Dashboard->Appearance–>Editor–>functions.php of your theme.
Hope that helped. :)
copy the value Id from here

I'm attempting to hide Table Rate Shipping when UPS Shipping Method is Available

I have already tried editing the following code from woothemes site for hiding a shipping method which was this:
// woocommerce_package_rates is a 2.1+ hook
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
// Hide shipping rates when free shipping is available
// #param array $rates Array of rates found for the package
// #param array $package The package array/object being shipped
// #return array of modified rates
//
function hide_shipping_when_free_is_available( $rates, $package ) {
// Only modify rates if free_shipping is present
if ( isset( $rates['free_shipping'] ) ) {
// To unset a single rate/method, do the following. This example unsets flat_rate shipping
unset( $rates['flat_rate'] );
// To unset all methods except for free_shipping, do the following
$free_shipping = $rates['free_shipping'];
$rates = array();
$rates['free_shipping'] = $free_shipping;
}
return $rates;
}
I editted the code from 'free_shipping' to 'ups' which I believed would be all I needed to do but alas nothing came of it.
I'm using Table Rate Shipping 2.9.0 by Mike Jolley
Woocommerce 2.4.6
and UPS shipping method 3.1.1 by woothemes
Any help would be appreciated.
What I am trying to accomplish is this:
Not all my products have dimensions. On the products that do have dimensions and can checkout via UPS I would like them to ONLY be able to checkout using UPS.
If there is a mixed cart or products without dimensions, I want it to use the Table Rate shipping.
What I specifically don't want is both UPS and table rate to be displayed at the same time.
The main problem with using that snippet is that UPS and Table Rate Shipping have multiple rates.... and therefore multiple rate IDs. So you can't effectively test for the presence of a particular rate with a simple isset($rates['ups']) nor unset another with a unset($rates['table_rate']);
Take a look at this var_dump of my sample shipping rates. I'm using USPS because that's what I have on hand, but I expect it to be pretty similar to UPS.
So as far as I can tell, to achieve your aim, we'll need to test the keys for the presence of the "ups" or "table_rate" strings in the array keys. Fortunately, that's pretty easy with strpos.
I tested this against USPS and it seemed to work. I used the WooCommerce tools to set the site into Shipping Debug mode. Otherwise, WooCommerce stores the rates in a transient for an hour. (see: admin.php?page=wc-status&tab=tools on your site)
Here's my final code:
// remove any table_rate rates if UPS rates are present
add_filter( 'woocommerce_package_rates', 'hide_table_rates_when_ups_available', 10, 2 );
function hide_table_rates_when_ups_available( $rates, $package ) {
// Only modify rates if ups is present
if ( is_ups_available( $rates ) ) {
foreach ( $rates as $key => $rate ){
$pos = strpos( $key, 'table_rate' );
if( false !== $pos ){
unset( $rates[$key] );
}
}
}
return $rates;
}
// loops through the rates looking for any UPS rates
function is_ups_available( $rates ){
$is_available = false;
foreach ( $rates as $key => $rate ){
$pos = strpos( $key, 'ups' );
if( false !== $pos ){
$is_available = true;
break;
}
}
return $is_available;
}

WooCommerce - Add free shipping for certain products and when the cart which reaches an amount

I run an online store with WooCommerce and sell normal products and books. I want to reach the following:
If somebody has a cart value of < 50 he should pay for shipping
If somebody has a cart value of > 50 shipping should be free
If somebody adds a book to the cart shipping is always free
I try this with the following code:
function custom_free_per_class( $return, $package ) {
// Setup an array of shipping classes that allow Flat Rate Shipping
$shippingclass_array = array( 'bookshipping');
// loop through the cart checking the shipping classes
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$shipping_class = get_the_terms( $values['product_id'], 'product_shipping_class' );
if ( isset( $shipping_class[0]->slug ) && in_array( $shipping_class[0]->slug, $shippingclass_array ) ) {
return true;
break;
}//if
}//foreach
}//function
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'custom_free_per_class', 10, 2 );
add_filter( 'woocommerce_package_rates', 'hide_shipping_when_free_is_available', 10, 2 );
/**
* Hide shipping rates when free shipping is available
*
* #param array $rates Array of rates found for the package
* #param array $package The package array/object being shipped
* #return array of modified rates
*/
function hide_shipping_when_free_is_available( $rates, $package ) {
// Only modify rates if free_shipping is present
if ( isset( $rates['free_shipping'] ) ) {
// To unset all methods except for free_shipping, do the following
$free_shipping = $rates['free_shipping'];
$rates = array();
$rates['free_shipping'] = $free_shipping;
}
return $rates;
}
I set it up in the WooCommerce backend that free shipping should be available after a cart value of 50 has been reached. But however this does not work. The above code works - so free shipping is guaranteed when somebody adds a book, but this seems to hinder the other intention (cart > 50) from working. If I remove the code
add_filter( 'woocommerce_shipping_free_shipping_is_available', 'custom_free_per_class', 10, 2 );
the functionality with adding free shipping when 50 is reached works, but surely books are not free anymore.
Des anybody has an idea what is going wrong here?
I would really appreciate it if anyone can help me.
Thanks!
I solved it by myself. The input parameter for the function is not ($return, $package) - it is just ($is_available).

Categories