Allow WooCommerce existing customers to checkout without being logged in

With WooCommerce, if an email is already associated with an account and the "create account" checkbox is ticked on the checkout page, WooCommerce will require the customer to login to his account before processing the payment.

It makes sense but it clearly hinders transformation rate. I'd rather have the customer complete the transaction and transparently associate the order with the email's matching account.

However, I have no clue how I could alter the default behaviour to make this possible.

Any idea?


Solution

Thanks to @Gabriel's answer, if finally found a way. Gabriel pointed me to process_customer function.

It turns out there's a hook before process_customer is called. This hook is woocommerce_checkout_process.

Knowing this, it's just a couple of lines:

  • check if user isn't already logged in createaccount is checked
    • if yes, check if a user account matches the provided email
      • if not, do nothing, default behaviour is good
      • if yes, then use wp_set_current_user to set the email matching account as the current user (won't make the user logged in!). That will have the effect of linking the order to the already existing acount (and updating shipping/billing info).
add_action('woocommerce_checkout_process', function () {
    if (!is_user_logged_in()  $_POST['billing_email']  $_POST['createaccount'] == 1) {
        $user = get_user_by('email', $_POST['billing_email']);
        if ($user) wp_set_current_user($user-ID);
    }
});

Topic woocommerce-offtopic account user-registration users Wordpress

Category Web


You would allow the user to fill the email, use it to find the user id at the database and then use the id for the order.

One possible solution is to replace function wc_create_new_customer( $email, $username = '', $password = '', $args = array() ) with a custom function.

This is where the function is called, all your custom function needs to do is find the correct user_id.

    protected function process_customer( $data ) {
        $customer_id = apply_filters( 'woocommerce_checkout_customer_id', get_current_user_id() );

        if ( ! is_user_logged_in() && ( $this->is_registration_required() || ! empty( $data['createaccount'] ) ) ) {
            $username    = ! empty( $data['account_username'] ) ? $data['account_username'] : '';
            $password    = ! empty( $data['account_password'] ) ? $data['account_password'] : '';
            $customer_id = wc_create_new_customer(
                $data['billing_email'],
                $username,
                $password,
                array(
                    'first_name' => ! empty( $data['billing_first_name'] ) ? $data['billing_first_name'] : '',
                    'last_name'  => ! empty( $data['billing_last_name'] ) ? $data['billing_last_name'] : '',
                )
            );

            if ( is_wp_error( $customer_id ) ) {
                throw new Exception( $customer_id->get_error_message() );
            }

            wc_set_customer_auth_cookie( $customer_id );

            // As we are now logged in, checkout will need to refresh to show logged in data.
            WC()->session->set( 'reload_checkout', true );

            // Also, recalculate cart totals to reveal any role-based discounts that were unavailable before registering.
            WC()->cart->calculate_totals();
        }

Hope this helps to point you in the right direction.

Cheers, Gabriel

About

Geeks Mental is a community that publishes articles and tutorials about Web, Android, Data Science, new techniques and Linux security.