WooCommerce - disable postcode validation - wordpress

Does anybody know how to disable the Postcode validation on the checkout page in WooCommerce?
My country is set up as Switzerland, but I want also people from Austria and Germany allow to order.
So when I enter a German Postcode with 5 digits (in Switzerland there are only 4), the shop says it's an invalid postcode. (but in the settings I allowed every country).
Any idea how to fix that?

Adding this code to the functions.php file should work:
function custom_override_default_address_fields( $address_fields )
{
unset( $address_fields['postcode'] );
return $address_fields;
}
EDIT:
// Hook into the checkout fields (shipping & billing)
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Hook into the default fields
add_filter( 'woocommerce_default_address_fields' , 'custom_override_default_address_fields' );
function custom_override_checkout_fields( $fields )
{
unset( $fields['billing']['billing_postcode'] );
unset( $fields['shipping']['shipping_postcode'] );
return $fields;
}
function custom_override_default_address_fields( $address_fields )
{
unset( $address_fields['postcode'] );
return $address_fields;
}
ANOTHER EDIT:
add_filter( 'woocommerce_default_address_fields' , 'custom_override_default_address_fields' );
function custom_override_default_address_fields( $address_fields )
{
$address_fields['postcode']['required'] = false;
return $address_fields;
}

So I didn't actually find a simple code solution for this one but I noticed that if I set
WooCommerce > Preferences > General > Geolocate address
it will work (if settings are set to "Sell to all countries", in my case)

This code only removes validation of address fields in my-account page, what you need:
add_filter( 'woocommerce_default_address_fields',
'custom_override_default_address_fields' );
function custom_override_default_address_fields($address_fields)
{
$address_fields['postcode']['validate'] = false;
return $address_fields;
}
for billing and shipping:
add_filter( 'woocommerce_checkout_fields' , 'remove_postcode_validation', 99 );
function remove_postcode_validation( $fields ) {
unset($fields['billing']['billing_postcode']['validate']);
unset($fields['shipping']['shipping_postcode']['validate']);
return $fields;
}
Also i think with removing "validate-required" class in wc-template-function.php, this feature will be deactivated (no test).
Sorry for bad English and hope this solutions solve your problem.

The previous answers don't seem to address the question! The postcode is still a required field, it's matter of whether other postcodes can be allowed that WooCommerce is saying is wrong.
For a checkout I'm building I've used this filter to allow any postcode to be considered valid regardless of country/postcode given.
add_filter( 'woocommerce_validate_postcode' , 'mycode_override_postcode_check', 99, 3 );
function mycode_override_postcode_check( $valid, $postcode, $country ) {
return true;
}
You can change that return true; for more complex code logic that reviews the postcode and country, this can help if your version of WooCommerce doesn't cover new postcode/zip code rules and you need them to be accepted.
Source: https://github.com/EloxZ/wordpresscrm/blob/main/wp-content/plugins/woocommerce/includes/class-wc-validation.php#L123

Related

WooCommerce - get shipping country for non registered user

Good morning everybody.
I need to implement a method to subtract shipping costs from the total in case the shipping destination is included in a specific array of values.
This is not a case of free shipping, because this costs will be added later for other reasons.
I cannot base my decision on the user country, for two reasons:
user can be not registered
user country and shipping country can be different.
I see that WooCommerce reload the order totals when I change billing/shipping country. I believe I need to intercept this kind of change an trigger an action to insert a new cart fee (a negative one, of course).
Well, how can I do that?
This is a part of my code
function delayShippingCosts(){
global $woocommerce;
$EUcountries = ['IT','AT','BE','BG','CY','HR','DK','EE','FI','FR','DE','GR','IE','LV','LT','LU','MT','NE','PL','PT','CZ','RO','SK','SI','ES','SE','HU'];
return in_array( $woocommerce->customer->get_country() , $EUcountries);
}
add_action( 'woocommerce_cart_calculate_fees', 'scc_detract_shipping_costs' );
function scc_detract_shipping_costs(){
global $woocommerce;
if(delayShippingCosts()){
$shippingCosts = WC()->cart->get_shipping_total() * -1;
if(current_user_can('administrator')) {
$woocommerce->cart->add_fee( 'Delayed shipping costs', $shippingCosts, true, 'standard' );
}
}
}
The problem is that now I'm looking to my customer data, and these are not dynamic (and void for unregisterd / unlogged users).
Any suggestions?
Thanks!!
EDIT
Almost OK
I managed to retrieve the shipping country from "woocommerce_checkout_update_order_review" hook, like that:
function action_woocommerce_checkout_update_order_review($posted_data) {
global $shipTo;
$data = array();
$vars = explode('&', $posted_data);
foreach ($vars as $k => $value){
$v = explode('=', urldecode($value));
$data[$v[0]] = $v[1];
}
WC()->cart->calculate_shipping();
$shipTo = $data['shipping_country'] ? $data['shipping_country'] : $data['billing_country'];
// REMOVE ALL NOTICES, IF PRESENTS...
wc_clear_notices();
}
add_action('woocommerce_checkout_update_order_review', 'action_woocommerce_checkout_update_order_review', 10, 1);
add_action( 'woocommerce_cart_calculate_fees', 'scc_detract_shipping_costs' );
function scc_detract_shipping_costs(){
global $woocommerce;
... something ...
if(condition) {
wc_add_notice("info message", "error");
}
}
My problem is that the notice is not removed when "condition" in false.
I tried to call wc_remove_notices() both in woocommerce_cart_calculate_fees and woocommerce_checkout_update_order_review. No big difference! :(
Any hint?
The delayShippingCosts() function is not needed. You can get the list of European countries via the get_european_union_countries method of the WC_Countries class (unless you want to customize the list).
Also you are getting the country with the get_country() method of the WC_Customer class.
The WC_Customer::get_country function is deprecated since version 3.0.
You can get the country like this:
WC()->customer->get_shipping_country() the country of the shipping address
WC()->customer->get_billing_country() the country of the billing address
Finally, note that to apply the standard tax class for the fee you have to set the 4th parameter as an empty string instead of 'standard'. See here for more information.
TO GET THE COUNTRY FIELD FROM A USER NOT LOGGED IN WITH THE woocommerce_cart_calculate_fees HOOK
You can send an AJAX call to send the billing and shipping country value when the respective fields change in the checkout.
To make sure that the AJAX function is executed before the woocommerce_cart_calculate_fees hook it is necessary to remove the update_totals_on_change class from the billing and shipping country fields (to avoid the AJAX call being made to update the checkout) and update the checkout only after the call AJAX has been completed.
This method may take a few extra milliseconds/second to update the checkout because you have to wait for the AJAX call to create the option to complete.
See this answer for more details on how to submit an AJAX call in Wordpress.
Add the following code inside your active theme's functions.php:
// enqueue the script for the AJAX call
add_action('wp_enqueue_scripts', 'add_js_scripts');
function add_js_scripts(){
wp_enqueue_script( 'ajax-script', get_stylesheet_directory_uri().'/js/script.js', array('jquery'), '1.0', true );
wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}
// update options with checkout country values
add_action( 'wp_ajax_nopriv_set_option_country', 'set_option_country' );
add_action( 'wp_ajax_set_option_country', 'set_option_country' );
function set_option_country() {
if ( isset( $_POST ) ) {
// get the countries valued in the checkout by the user (guest or logged in)
$countries = $_POST['countries'];
$billing_country = $countries['billing_country'];
$shipping_country = $countries['shipping_country'];
// update options
update_option( 'guest_billing_country', $billing_country );
update_option( 'guest_shipping_country', $shipping_country );
// returns the output as a response to the AJAX call
echo 'success';
}
// always die in functions echoing AJAX content
die();
}
Create a script.js file and add it inside your child theme (because I used get_stylesheet_directory_uri() instead of get_template_directory_uri()) in the directory: /child-theme/js/script.js:
jQuery(function($){
// disable AJAX update
$('#billing_country_field').removeClass('update_totals_on_change');
$('#shipping_country_field').removeClass('update_totals_on_change');
// when the country fields change
$('#billing_country, #shipping_country').change(function(){
var countries = {
'billing_country': $('#billing_country').val(),
'shipping_country': $('#shipping_country').val(),
};
$.ajax({
url: ajax_object.ajaxurl,
type : 'post',
data: {
'action': 'set_option_country',
'countries': countries
},
complete: function(){
// update checkout via AJAX
$(document.body).trigger('update_checkout');
},
success:function(data) {
console.log(data);
},
error: function(errorThrown){
console.log(errorThrown);
}
});
});
});
The code has been tested and works.
So, the correct scc_detract_shipping_costs function will be:
add_action( 'woocommerce_cart_calculate_fees', 'scc_detract_shipping_costs' );
function scc_detract_shipping_costs(){
$countries = new WC_Countries();
// get the list of countries of the european union
$eu_countries = $countries->get_european_union_countries();
// get countries from checkout
$billing_country = get_option( 'guest_billing_country' );
$shipping_country = get_option( 'guest_shipping_country' );
// if the shipping country is part of the European Union
if ( in_array( $shipping_country, $eu_countries ) ) {
$shippingCosts = WC()->cart->get_shipping_total() * -1;
if ( current_user_can('administrator') ) {
WC()->cart->add_fee( 'Delayed shipping costs', $shippingCosts, true, '' );
}
}
}
The code has been tested and works. Add it to your active theme's functions.php.
TO GET THE COUNTRY FIELD FROM A USER NOT LOGGED IN WITH THE woocommerce_calculate_totals HOOK
add_action( 'woocommerce_calculate_totals', 'get_post_checkout_data' );
function get_post_checkout_data( $cart ) {
// get post data
if ( isset( $_POST['post_data'] ) ) {
parse_str( $_POST['post_data'], $post_data );
} else {
$post_data = $_POST;
}
if ( ! empty( $post_data ) ) {
$billing_country = $post_data['billing_country'];
$shipping_country = $post_data['shipping_country'];
// ...
}
}
Add the code in your active theme's functions.php.

How to call function in other ajax of function

I have a change_flat_rates_cost() function, but it works only when loading the page. but it is necessary for me that function worked at each change of the field "city", (in checkout fields).
I have tried to use ajax function and to call there add_filter() function, but it doesn't help.
I do it to change delivery cost without reset of the page depending on the chosen city
change_flat_rates_cost function (changes the shipping price)
function change_flat_rates_cost($rates, $package) {
$userid = get_current_user_id();
$meta_city = get_user_meta( $userid, 'billing_city', true );
if ( isset( $rates['shipping_method_1'] ) ) {
if ($meta_city == 'City1'){
$rates['shipping_method_1']->cost = 100;
}
if ($meta_city == 'City2'){
$rates['shipping_method_1']->cost = 200;
}
}
return $rates;
}
add_filter( 'woocommerce_package_rates', 'change_flat_rates_cost', 10, 2 );
ajax function:
add_action( 'wp_ajax_change_shipping', 'change_shipping' );
add_action( 'wp_ajax_nopriv_change_shipping', 'change_shipping' );
function change_shipping() {
global $woocommerce;
add_filter( 'woocommerce_package_rates', 'change_flat_rates_cost', 10, 2 );
die();
}
You can add filter as normal "add_filter". No need to put it there in ajax, because anyways there are conditions mentioned in your function.
So, do add_filter normally and instead of using add_filter in ajax function, you should use "apply_filters". This will call your custom shipping function.
I hope I've made it clear.

Clear checkout fields in woocommerce

I'm trying to remove the autoloaded user info in the various checkout fields but cannot seem to find any way to access the fields value. I've tried the following which clears formatting, removes, the field, etc. but nothing I can find shows how to remove just the value. Does anyone know how to access this?
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
$fields['billing']['billing_first_name']['placeholder'] = '';
$fields['billing']['billing_last_name']['value'] = '';
unset($fields['billing']['billing_company']);
return $fields;
}
Register filter:
add_filter( 'woocommerce_checkout_get_value' , 'clear_checkout_fields' );
Add this function. All fields will be empty.
function clear_checkout_fields($input)
{
return '';
}

disable postcode validation in WooCommerce checkout page

Does anybody know how to disable the Postcode validation on the checkout page in WooCommerce?
I want to input 'text content' in "billing_postcode" field, but the shop says it's an invalid postcode.
Does anyone know how I can disable Postcode validation or allow text characters?
Just do this:
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields', 99 );
function custom_override_checkout_fields( $fields ) {
unset($fields['billing']['billing_postcode']['validate']);
unset($fields['shipping']['shipping_postcode']['validate']);
return $fields;
}
You can put this pretty much anywhere, but preferably in a custom plugin or in your theme's functions.php
You could try this:
add_filter( 'woocommerce_default_address_fields', 'custom_override_address_fields', 999, 1 );
function custom_override_address_fields( $address_fields ) {
// set as not required
$address_fields['postcode']['required'] = false;
// remove validation
unset( $address_fields['postcode']['validate'] );
return $address_fields;
}

WooCommerce Payment Gateway for Logged In users only

I would like logged in users to be able to use 'cheque' payment option.
I found the following relevant thread: WooCommerce Show Payment Gateways for Logged In Customers Only However, placing the following code in functions.php no longer works for Woocommerce version 2.3.7:
add_filter( "woocommerce_available_payment_gateways", "rp_filter_gateways", 9999 );
function rp_filter_gateways($args) {
if(!is_user_logged_in() && isset($args['cheque'])) {
unset($args['cheque']);
}
return $args;
}
Please can someone provide me with an updated solution?
Many thanks
woocommerce_available_payment_gateways is still a valid hook. The following code has been tested with the latest version of WooCommerce:
function rp_filter_gateways( $args ) {
if( !is_user_logged_in() && isset($args['cheque']) ) {
unset( $args['cheque'] );
}
return $args;
}
add_action( 'woocommerce_available_payment_gateways', 'rp_filter_gateways' );

Resources