I use the following code to display the delivery method "local pickup" only for one city (Paris). I use the code together with the plugin "States, Cities, and Places for WooCommerce" (https://wordpress.org/plugins/states-cities-and-places-for-woocommerce/) and everything works correctly.
add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 );
function shipping_package_rates_filter_callback( $rates, $package ) {
// Define the allowed cities for local pickup
$allowed_cities = array( 'Paris' );
// The defined method id
$pickup_method_id = 'local_pickup:3';
// Get the shipping city for the current order
$shipping_city = isset( $package['destination']['city'] ) ? strtolower( $package['destination']['city'] ) : '';
// Check if the shipping city is in the allowed cities and the pickup method is available
if ( in_array( $shipping_city, $allowed_cities ) && isset( $rates[$pickup_method_id] ) ) {
return $rates;
} else {
// Hide the pickup method
unset( $rates[$pickup_method_id] );
return $rates;
}
}
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
$bool = true;
// Define the allowed cities for local pickup
$allowed_cities = array( 'Paris' );
// Check if the shipping city is in the allowed cities
$shipping_address = WC()->customer->get_shipping();
if ( isset( $shipping_address['city'] ) && in_array( strtolower( $shipping_address['city'] ), $allowed_cities ) ) {
$bool = false;
}
// Mandatory to make it work with shipping methods
foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
}
WC()->cart->calculate_shipping();
}
My problem is that I would like the "local pickup" delivery method to be checked by default when choosing the city of Paris.Although I put this method in the first position, the default checked method is one of the methods that appears before selecting the city (the one in the 2nd place). I tried to modify the following code, but it doesn’t seem to work. How could I solve the problem?
add_action( 'woocommerce_before_checkout_form', 'ahir_select_free_shipping_by_default' );
function ahir_select_free_shipping_by_default() {
if ( isset(WC()->session) && ! WC()->session->has_session() )
WC()->session->set_customer_session_cookie( true );
// Check if "free shipping" is already set
if ( strpos( WC()->session->get('chosen_shipping_methods')[0], 'free_shipping' ) !== false )
return;
// Loop through shipping methods
foreach( WC()->session->get('shipping_for_package_0')['rates'] as $key => $rate ){
if( $rate->method_id === 'free_shipping' ){
// Set "Free shipping" method
WC()->session->set( 'chosen_shipping_methods', array($rate->id) );
return;
}
}
}
2
Answers
I don't know if I did it right, but I found a solution to make it work the way I want. Based on the answer here https://stackoverflow.com/a/67083089/21533506 I added the following code:
After that I added the following code to hide all delivery methods until the address is filled in:
After that I modified the code from here https://stackoverflow.com/a/77896304/21533506 to display the local fetch in the first position:
To set/define the default shipping method when the city is "Paris", try the following that uses
woocommerce_shipping_chosen_method
filter hook:Code goes in functions.php file of your child theme (or in a plugin). It could work.
Note that in your existing code, for the 2 first functions, you should replace
strtolower(
withucfirst(
if you want to get it working with the defined city(s).