I'm trying to minimize the billing address from checkout if the user has already filled up the billing form (from a previous order or if the user has done it previously from the "my account" page).
I have tried this method to hide the billing address completely but it doesn't work at all
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
if( is_user_logged_in() && !has_billing()){
unset($fields['billing']);
$fields['billing'] = array();
}
return $fields;
}
// Check the meta of Postcode and Country if they are entered.
function has_billing($user_id = false){
if(!$user_id)
$user_id = get_current_user_id();
$shipping_postcode = get_user_meta( $user_id, 'billing_postcode', true );
$shipping_country = get_user_meta( $user_id, 'billing_country', true );
// Fetch more meta for the condition has needed.
if($shipping_postcode && $shipping_country){
return true;
}
return false;
}
What I'm doing wrong?
You are unsetting the form fields that are being submitted. If you hide them in CSS that should work or you will need to populate the forms dynamically when you click the checkout button.
Related
We just moved and merged the WooCommerce account password field on the checkout page from the "Account" group to the "Billing" field group. This works nicely. Also, we create a new checkbox field and add this to the billing section. Without that, the "Create an account" checkbox will still be at the default position. To do so, we created a new checkbox with jQuery.
Thanks to the following articles:
How to move the create account checkbox on Woocommerce checkout page
Reordering checkout fields in WooCommerce 3
With our current code, the moved password field is always visible. We want to have it the same way as WooCommerce default works. This means the password field should only be visible when the checkbox is active. WooCommerce by default has an excellent hide & Show CSS in place. However, I'm not able to use the identical CSS (or maybe script?!).
How can we connect the custom checkbox with the account password field?
// Move Account password field into billing section
function move_password_field($checkout_fields){
// Move Account Password into Billing
$checkout_fields['billing']['account_password'] = $checkout_fields['account']['account_password'];
// Remove Password from Billing
unset($checkout_fields['account']['account_password']);
return $checkout_fields;
}
add_filter('woocommerce_checkout_fields', 'move_password_field', 999);
// CSS rules
add_action( 'woocommerce_before_checkout_billing_form', 'move_checkout_create_an_account_css' );
function move_checkout_create_an_account_css() {
if( ! is_user_logged_in() ) :
?><style>
.woocommerce-account-fields label.woocommerce-form__label-for-checkbox {display: none !important;}
#account_cb_field {margin-top: 32px;}
#account_cb_field input {margin-right: 6px;}
</style>
<?php
endif;
}
// Add a checkbox to billing section
add_filter( 'woocommerce_checkout_fields', 'move_checkout_create_an_account_checkbox' );
function move_checkout_create_an_account_checkbox( $fields ) {
if( ! is_user_logged_in() ) {
// Make email field on half on left side
$fields['billing']['billing_email']['class'] = array('form-row-wide');
// Custom checkbox on half right side
$fields['billing']['account_cb'] = array(
'type' => 'checkbox',
'label' => __("Create an account?", "woocommerce"),
'class' => array('form-row-wide'),
);
}
return $fields;
}
// remove "(optional)" from the new checkbox
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() && $key === 'account_cb' ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// The jQuery code
add_action( 'wp_footer', 'move_checkout_create_an_account_js' );
function move_checkout_create_an_account_js() {
if ( ! is_user_logged_in() && is_checkout() && ! is_wc_endpoint_url() ) :
?><script>
(function($){
$('input[name=account_cb]').on( 'click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
</script>
<?php
endif;
}
I need update WordPress account email with woocommerce billing email after successful checkouts. I used this code but it does not work :
/* Update account email based on woocommerce billing email */
add_filter( 'woocommerce_thankyou' , 'custom_update_checkout_fields', 10, 2 );
function custom_update_checkout_fields($user_id, $old_user_data ) {
$current_user = wp_get_current_user();
// Updating Billing info
if($current_user->user_email != $current_user->billing_email)
update_user_meta($user_id, 'billing_email', $current_user->user_email);
}
Am I used an outdated code?
There are some mistakes. Try the following instead:
add_filter( 'woocommerce_thankyou' , 'thankyou_update_wordpress_user_email' );
function thankyou_update_wordpress_user_email( $order_id ) {
$order = wc_get_order( $order_id );
$user = $order->get_user();
$billing_email = $order->get_billing_email();
// Updating user account email
if( is_a($user, 'WP_User' ) && $user->user_email != $billing_email ) {
$user_data = wp_update_user( array( 'ID' => $user->ID, 'user_email' => $billing_email ) );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should work.
Note: When changing user email, WordPress Send an email to the new user email.
In WooCommerce I am using Boss Learndash plugin and in a template file of this plugin plugins/boss-learndash/templates/learndash/single-sfwd-course.php, I am trying to add once more button to users who have bought the course/product. For that Im trying to call wc_customer_bought_product woocommerce function in the template but seems like it is not able to call that function.
I tried by adding global $woocommerce; and also tried by wc->user->wc_customer_bought_product but couldnt fix it.
What I am doing wrong?
The wc_customer_bought_product() function is not a method of any WooCommerce class. It's just a conditional function with 3 arguments $customer_email, $user_id and $product_id:
wc_customer_bought_product( $customer_email, $user_id, $product_id );
It will return a boolean true or false, so you will use it in an if statement as a conditional function.
To get the user ID and the customer email, you can use:
// Get the current user data:
$user = wp_get_current_user();
$user_id = $user->ID; // Get the user ID
$customer_email = $user->user_email; // Get the user email
// OR
// $customer_email = get_user_meta( $user->ID, 'billing_email', true ); // Get the user billing email
// The conditional function (example)
// IMPORTANT: $product_id argument need to be defined
if( wc_customer_bought_product( $customer_email, $user_id, $product_id ) ) {
echo "Has bought the product";
} else {
echo "Has not bought the product yet";
}
I'm looking for a way to hide the billing address on the checkout page of my woocommerce theme if the user has already filled up the billing form (from a previous order or if the user has done it previously from the "my account" page).
I've found ways to hide the billing / shipping form completely on the checkout page if the user is logged in (see below), however I can't find a way to do the above.
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
if( is_user_logged_in() ){
unset($fields['billing']);
$fields['billing'] = array();
}
return $fields;
}
Any idea?
Thank you!
It will depend what you consider to be a fully completed address i made snippet function you can use to go further with.
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
function custom_override_checkout_fields( $fields ) {
if( is_user_logged_in() && !has_billing()){
unset($fields['billing']);
$fields['billing'] = array();
}
return $fields;
}
// Check the meta of Postcode and Country if they are entered.
function has_billing($user_id = false){
if(!$user_id)
$user_id = get_current_user_id();
$shipping_postcode = get_user_meta( $user_id, 'billing_postcode', true );
$shipping_country = get_user_meta( $user_id, 'billing_country', true );
// Fetch more meta for the condition has needed.
if($shipping_postcode && $shipping_country){
return true;
}
return false;
}
Note: the prefix shipping_ there is one for billing ( billing_ ).
Edit: Here the meta key billing_address_1 and billing_address_2 always the prefix can be either billing_ or shipping_
Also if for some reason you don't have a shipping or billing address associated in the user meta keys but the customer once did an order you can check this code to fetch order address.
Woocommerce WC_Order get_shipping_address() not returning as array (old post might not be valid anymore)
By default Woocommerce saves the billing and shipping address on the checkout page.
I am searching for a way to prevent Woocommerce from saving the values in the shipping address. So all the fields in the shipping address should be empty.
In another thread I found a partial solution. It works great, but it also makes the billing address empty:
add_filter('woocommerce_checkout_get_value','__return_empty_string',10);
Is there a way to do this only for shipping address?
Big thx!
You could change the code like this...
add_filter( 'woocommerce_checkout_get_value', 'reigel_empty_checkout_shipping_fields', 10, 2 );
function reigel_empty_checkout_shipping_fields( $value, $input ) {
/*
Method 1
you can check the field if it has 'shipping_' on it...
if ( strpos( $input, 'shipping_' ) !== FALSE ) {
$value = '';
}
Method 2
put all the fields you want in an array...
*/
$shipping_fields = array(
//'shipping_first_name',
//'shipping_last_name',
'shipping_company',
'shipping_country',
'shipping_address_1',
'shipping_address_2',
'shipping_city',
'shipping_state',
'shipping_country',
'shipping_postcode'
);
if ( in_array( $input, $shipping_fields ) ) {
$value = '';
}
return $value;
}