Reputation: 197
I currently use below code to set default country (based on User's current Geo-location).
function custom_update_allowed_countries( $countries ) {
// Only on frontend
if( is_admin() ) return $countries;
if( class_exists( 'WC_Geolocation' ) ) {
$location = WC_Geolocation::geolocate_ip();
if ( isset( $location['country'] ) ) {
$countryCode = $location['country'];
} else {
// If there is no country, then return allowed countries
return $countries;
}
} else {
// If you can't geolocate user country by IP, then return allowed countries
return $countries;
}
// If everything went ok then I filter user country in the allowed countries array
$user_country_code_array = array( $countryCode );
$intersect_countries = array_intersect_key( $countries, array_flip( $user_country_code_array ) );
return $intersect_countries;
}
add_filter( 'woocommerce_countries_allowed_countries', 'custom_update_allowed_countries', 30, 1 );
The above code affects not only the Billing Section but also the Shipping Section. In this case, a US user can only ship to US; a user from Canada can only ship to Canada and so on.
If there's a way that it will still default to the Goelocated country on the Billing, but User can be able to ship to Other countries?
Upvotes: 1
Views: 956
Reputation: 5281
I've checked every hook/filter and found nothing useful. So I came up with this solution. Add this code to your child theme functions.php
file:
add_action( 'wp_enqueue_scripts', 'wp_enqueue_scripts_action' );
function wp_enqueue_scripts_action() {
wp_register_script( 'test-script', get_stylesheet_directory_uri() . '/test.js', [ 'jquery', ] );
wp_enqueue_script( 'test-script' );
wp_localize_script( 'test-script', 'test_script', [
'customer_country' => get_customer_geo_location_country()
]
);
}
/**
* Returns the customer country
*
* @return string|null
*/
function get_customer_geo_location_country(): ?string {
if ( class_exists( 'WC_Geolocation' ) ) {
$location = WC_Geolocation::geolocate_ip();
if ( isset( $location['country'] ) ) {
return $location['country'];
}
}
return null;
}
add_action( 'woocommerce_after_checkout_validation', 'woocommerce_after_checkout_validation_action', 10, 2 );
function woocommerce_after_checkout_validation_action( $fields, $errors ) {
$billing_country = $fields['billing_country'];
if ( ! empty( $billing_country ) && $billing_country !== get_customer_geo_location_country() ) {
$errors->add( 'validation', 'You are not allowed to select this billing country!' );
}
}
First we add a new script. If you already have a script, you can just copy the wp_localize_script
function and change the handler and the object name.
With this function we can pass the current country of the customer to our JavaScript file. Inside this file we do this stuff:
(function ( $ ) {
$( document ).ready( function () {
if (test_script.customer_country) {
$( '#billing_country option' ).each( function () {
if ($( this ).val() !== test_script.customer_country) {
$( this ).remove();
}
} );
}
} );
})( jQuery );
This little function removes every country from our billing select that doesn't match the customers country. If you want you can remove all countries in an else
statement to be sure the customer can't order in case there is no country available.
The customer should now only see his home country in the billing country dropdown.
To be sure he don't hacks us, we add a little validation to the checkout where we verify the selected country again.
If you test this on localhost, no country will be available so be sure it's on a live website in the web (or even staging).
This is a basic idea. You need to test it and maybe adjust it too your needs.
Upvotes: 2