How to allow Woocommerce checkout when an account is already registered

The Problem: Existing WooCommerce users get an error when logged out and placing an order.

If you have enabled mandatory user accounts in the WooCommerce settings, when a user attempts to checkout on your Woocommerce store they must either login with an existing account or complete user registration for a new account.  If they are not logged in but their entered billing email matches an existing account on your store, the checkout will fail with an error message such as An account is already registered with your email address. Please log in.

This is disruptive to the checkout process and results in a poor user experience.

This happens because the default behavior of the Woocommerce checkout validation process will check the email address entered by the user. If that email address matches an exisiting registerd wordpress user, then Woocommerce won't process the order until the user logs in.

The Solution: Modify the WooCommerce checkout process with the supplied PHP code so that existing users can be identified.

  1. Make sure guest checkout is enabled. You can do this from WP Admin > WooCommerce > Settings > Acconts and Privacy. Below you will see typical recommended settings, though the settings will vary based on your store setup.
  2. Add the below PHP Check for Existing Account code snippet  to your site. This code can be placed in the functions.php file of either your theme or child theme, in a plugin such as code snippets, or in a custom plugin.

Check for Existing Account code snippet

/**
*
* @param {object} $data the http post data from the checkout form
*
* @return $data
*/
add_filter( 'woocommerce_checkout_posted_data', 'filter_woocommerce_checkout_posted_data', 10, 1);
function filter_woocommerce_checkout_posted_data( $data) {
// Exit function if user is logged in to let checkout process as normal
if ( is_user_logged_in()) {
return $data;
}

/*
* If we have a user, we need to set the WP current user so that
* WooCommerce has a user and doesn't think it needs
* to create another one for that user's email.
* If an existing user is not found, then create a new one.
*/
if ( !is_user_logged_in() && is_checkout()) {
// Make sure not logged in and are on checkout page.
$user = get_user_by('email', $data['billing_email']);if ( !empty($user->ID) ) {
wp_set_current_user($user->ID);
$data['createaccount'] = 0; // Unset flag to create a new user.
}
else {
$data['createaccount'] = 1; // Set the flag to create a new user.
}
}

return $data;
}

What does the "Check For Existing Account" code snippet do?

This code utilizes the WooCommerce filter woocommerce_checkout_posted_data to intercept the checkout form data after the order now button is clicked, but before the data is actually processed.

It will first check if the user is logged in. If so, then we don't need to do anything.

However, if the user is not logged in then it checks to see if there is an existing WordPress account that matches the entered billing user email address. If there is an existing account then this code will set the WP current user to match that of the billing email address.

As a final step, the code will set a flag to create (or not) a new user account.

Reference:

The typical recommended settings for WooCommerce checkout
WooCommerce account is already registered notice