Current module:

  • Existing user - if they do not click the login button in the pane form, nothing happens - ie no authentication check of the password, no login, and order is not converted to an authenticated user order

Proposed changes:

  • Existing users
    • Require login of existing users - If enabled, the password field is required to proceed to the next checkout page. The customer will be logged in and the order converted to an authenticated user order
  • New users
    • Automatically create a user account for new customers - If enabled, a new user will be created based on the order's email address. The user is created on submit of the checkout page. This is similar to Commerce's default rule "on checkout complete" to create the user.
    • Automatically login the new user - If enabled, the new user will be logged in and the order converted to an authenticated user order.

With these changes, the order is associated with a user account on the initial checkout page. This solves many issues where the user account is created after payment processing has taken place.

Comments

recrit’s picture

The attached patch
* adds the settings described above to the account checkout pane's settings form
* adds code to force login for existing users
* adds code to create and login new users

recrit’s picture

Status: Active » Needs review
kcaporaso’s picture

Line 181 of this patch:
$username = $order_wrapper->mail_username->value();
Is returning bool(false) for the $username

Seems the call to the entity_wrapper on line 178 is not having the desired results:
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);

Perhaps I'm missing some other required piece?

---
Upon further review the real issue is when I'm dealing with a non-shippable product in the shopping cart -- essentially Drupal validation is looking for shipping details and is throwing an error which is why the order entity_metadata_wrapper is coming up short. I'm brand new to Drupal so I'm trying to figure out how to turn off the shipping validation even when I'm disabling the shipping pane (e.g. $checkout_panes['customer_profile_shipping']['enabled'] = FALSE;). Something else is triggering the validation -- any ideas?

Thanks!

recrit’s picture

Looking at that section of the patch I saw some room for improvement. I re-ran the patch with loading the order object fresh and ensure that $order->mail is set. Please re-test and report back.

The shipping validation error - not sure on that one. The customer_profile_shipping pane and order field just capture the address. The shipping module has the shipping services that might be complaining about it.

recrit’s picture

perhaps I should add that patch that I mentioned ..

recrit’s picture

added missing check to only alter the account checkout pane settings

recrit’s picture

added a check in the new user submit to check if user exists, ie got created already.

recrit’s picture

revised #7 to still fall through to convert the cart order and login user

recrit’s picture

added some conditions around converting the order if there is already a uid associated with the order.

haggins’s picture

Hey recrit,

thanks for this patch. Looks very good so far. However, I would additonally need the option for in checkout registration incl. password fields (optionally).

I will try to alter your patch in this direction if it's ok?

haggins’s picture

Here's the patch, based on recrits previous work.

Improvements:

  • Show login form also when you move back from the next checkout step
  • Focus confirmation e-mail field after ajax request (if field exists)
  • Hide confirmation e-mail field when a user with the given mail address already exists
  • Added a new setting "Allow new customers to create a new account" to panes setting form

Bevhavior of that new option:

  • Wins the race condition against "Automatically create a user account for new customers" when both options are selected. That prevents the checkout process to create multiple accounts and doing weird stuff
  • Shows a username field with respect to USERNAME_MAX_LENGTH
  • Username gets validated by user_validate_name()
  • Shows two password fields if "E-Mail verification" is turned off in either core user module or Logintoboggan
  • If Logintoboggan is enabled, the password is validated with its rules (min-length, allowed characters)

Todo:

  • Send e-mail with activation link if user is not allowed to set its own password
  • Think about how to process when autologin after registration is disabled.
    Since the anonymous user was able to reach the checkout form, he also can proceed the checkout process without clicking the activation link in the activation e-mail. Then the order is still associated with an anonymous user instead the new one. That could lead to bad UX when this customer activates its account later and can't find his first order in his order history.
    However, if you assign the order to the not yet activated user, this could make trouble if the customer never activates his account and the account may be deleted due his inactivity by any "clean up" process.
haggins’s picture

Fixing a bug introduced by unsetting the mail confirmation field. Now, in the case of required login of a known mail address, it gets prepopulated with the address and hidden by a wrapper with display: none;

JurgenR’s picture

When well aware of the todo's, patch #12 does as described in patch #11.
Maybe you can become a (co-)maintainer of this project?

haggins’s picture

Further improvement:

  • Validate e-mail confirmation field with ajax for immediate feedback
  • Show registration form only when both e-mails match

@13: There already was an attempt by an experienced maintainer to get (co-)maintership here.
See #1830100: Request to be maintainer/co-maintainer.

JMOmandown’s picture

I don't have time to do it myself tonight but may tomorrow. With that said, a few minor issues:

1) We refocus on the mail_confirm input after an ajax call but do not do so when loading the register new user form (if enabled). The focus should be restored on account[login][register][name] once the register form is loaded.

2) If a new account is registered in this manner, emails normally sent to the new user by the system are skipped. At a minimum the user welcome email or commerce account created email (if enabled) should be forced programmatically.

Awesome job by the way.

haggins’s picture

Included your 2nd suggestion with a configuration to enable/disable the welcome e-mail.

However, since the creation of a new account is optional and since the registration form is not visible until you leave focus of the mail confirmation field, I think it would be bad practice to hijack the users focus and set it to an optional field.

Are there other thoughts on this point?

JMOmandown’s picture

Yeah Because of the way the registration form will render on the page after the ajax call (generally under the previous), the users screen will be staring the registration form in the face. The natural inclination is to tab through this, at least that's what a customer we walked through your patch felt.

"Although not a deal breaker, when I pushed tab after entering my email for a second time, a new box appeared but above the box my cursor tabbed to. I was annoyed that I had to scroll back up to fill out my information and create a new account. It would have been quicker to tab through the section after reading what it was than to stop and scroll up to see it was optional then scroll back down."

Not a big deal to me, but figured I would pass it along. That was quite fast by the way haggins

BrianLP’s picture

Works well on my installation.

However, our site doesn't use user names but only email addresses. In such a case, when creating a new user account and letting the user set his password, the user name field isn't needed (shouldn't be mandatory).

haggins’s picture

@JMOmandown
I understand your reasoning. Since I'm quite busy atm I'll wait for more feedback before changing it.

@papalapapp
How do you disable usernames for the default registration process? Is there any configuration option I didn't see so far?
In the meantime you should be able to modify the form with hook_form_alter() to change its behavior.

vasike’s picture

Status: Needs review » Reviewed & tested by the community

with the latest patch (#16) i think we can move this issue to "reviewed & tested by the community" as it does what it says.

- imho opinion this should definitely be commited
- maybe a good helper (description) text it's needed for the Account information E-mail address form element.
So the anonymous user will know what to expect there - but this is another (general) issue.

BrianLP’s picture

@haggins
I mixed it up a little. The user name is indeed mandatory in my installation. But users get their account created during their first order via the Immediate Login module which doesn't ask for a user name, it sets the email address in for that.

Since this shop doesn't have any functions like komments, messages, personal ratings etc, there is no usecase for separate user names and therefor left out. Just wanted to throw that in. Making it optional would be basically to fill it with the email address if it is left blank.

BrianLP’s picture

As for the feature "Create new user account for new customers":
When applying this patch, should the Commerce default rule for creating a new user be deactivated? Or is it still needed?

haggins’s picture

Issue summary: View changes

papalapapp, I suggest to disable Allow new customers to create a new account under admin/commerce/config/checkout/form/pane/account. With that disabled you shouldn't have any problems.

p4trizio’s picture

I found #16 working good for this module! Thank you @haggins

Poieo’s picture

I had some issues with Safari trying to autocomplete the email and password fields and causing errors. I added the following to resolve it at the end of function commerce_checkout_login_form_commerce_checkout_form_alter:

      $form['account']['login']['mail']['#attributes']['autocomplete'] = 'off';
      $form['account']['login']['password']['#attributes']['autocomplete'] = 'off';
mibfire’s picture

The following form_set_error code should be moved from "commerce_checkout_form_alter" to "commerce_checkout_login_checkout_form_refresh" cos if there is another ajax callback for the form like a postal code check in address field then i will be getting form error continuously cos email field is empty. This is why form set error is used in form alter that is called in every ajax request.

      if ($error = user_validate_mail($mail)) {
        form_set_error('account][login][mail', $error);
      }
mibfire’s picture

There was a little error what i fixed.

haggins’s picture

@mibfire
Thank you, looks legit!

@Poieo
What kind of errors did you get? I have no Mac available here and so can only test with Chrome - without having any autocompletion issues.

Poieo’s picture

My fix actually didn't work, and the issue is a result of using LoginToboggan to allow logging in with your user name or password. With that in place, Safari (and possibly others) stores your login info and tries to populate the email address field with your username (if you've logged in with your username in the past) after the ajax call, which then causes the form to fail because your email is gone and replaced by your username.

mibfire’s picture

Haggins np Dude! instead we have to say big thank you for making this great patch!!!

One thing we should change is that a registration form can be very complex(with lots of fields, like user profile) too so instead of showing username and password for registration on checkout page we should show a link to the registration page and after user submits the form he/she will be redirected back to the checkout page, or we should show the full registration form on checkout page.

harrrrrrr’s picture

This should definitely be commited

ac’s picture

Please commit this.

jrao’s picture

Suggest two changes to the patch in #27

1. Change

elseif (variable_get('commerce_checkout_login_new_user_create', FALSE)) {

to

if (variable_get('commerce_checkout_login_new_user_create', FALSE)) {

Seems to me there's no reason to disable commerce_checkout_login_new_user_create when commerce_checkout_login_allow_registration is enabled. They can work together, if user use ajax form to register that's fine, if they don't then this module should automatically create new user.

2. Change

$username = isset($values['account']['login']['register']['name']) ? $values['account']['login']['register']['name'] : $order_wrapper->mail_username->value();

to

$username = empty($values['account']['login']['register']['name']) ? $order_wrapper->mail_username->value() : $values['account']['login']['register']['name'] ;

isset returns true if variable is an empty string, so shouldn't use it here.

webdrips’s picture

Thanks for the patch in #27; it didn't apply cleanly, so perhaps a re-roll is in order?

Is there any simple way to disable the "Continue to next step" cart button if the "Create new account" form is displayed?

slavojzizek’s picture

Any updates on how to get the patch to apply? 2 out of 5 failed to update

haggins’s picture

Hi,
I'm still using #16 and unfortunately have no time to reroll the patch with all suggested changes.

@#34
I would write a custom javascript and attaching it via hook_form_alter().

legolasbo’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
18.71 KB

I've rerolled the patch from #27 and included the suggestions in #33.

legolasbo’s picture

FileSize
19.46 KB

In addition to the reroll I also made the welcome e-mail notification message optional.

legolasbo’s picture

Assigned: recrit » legolasbo
Status: Needs review » Needs work

The implementation in the current patch does not degrade gracefully. When javascript is disabled you are able to continue checkout using any existing e-mail address without logging in. Only when you go back to the checkout pane will you be asked for the password. I will work on a fix somewhere in the coming days.

legolasbo’s picture

Status: Needs work » Needs review
FileSize
22.68 KB

Reworked the patch quite a bit, but it now gracefully degrades and makes use of the actual validation and submission callback options provided by commerce in stead of attaching validation handlers to the submit buttons.

I've also removed the now redundant and possibly confusing login button. The customer can now just enter his/her details and continue checkout. The account pane will be validated along with the other panes on form submission using the continue button.

These changes should probably also be made to the the user register functionality. But I think it's best to leave that refactoring for a follow up issue.

haggins’s picture

Thanks legolasbo. The downside of removing the additional login button is, that already saved addresses from commerce_addressbook cannot be used as the user object won't be available at the first checkout page.

legolasbo’s picture

@haggins, I see how that could be a problem to landing this issue. I've already got some ideas on how to fix it. I'll have a go at it soon.

Do you have any other input besides the issue you mentioned?

haggins’s picture

No, I currently don't have time to review, sorry. Maybe an interdiff would make it less time consuming to find code which changed in comparison to prior patch versions?

legolasbo’s picture

It's basically a complete rewrite of the previous patch. An interdiff wouldn't make it much easier to review. I did find a small bug myself. Will post a new patch soon.

capfive’s picture

Any ideas what is happening with this? would be great to get it implemented :)

capfive’s picture

Just tested the patch and when i registered and was logged in, it then wouldn't let me checkout, it kept saying xxx is already a registered user, please put in the password to continue, for now I am using a sandbox project from https://www.drupal.org/sandbox/purushothaman.drupalgeeks/2115745

This seems to work and I really think it should be looked at as a complete solution to this issue.

Thanks for the hard work!

haggins’s picture

@capfive, can you please provide information about your config at admin/commerce/config/checkout/form/pane/account?
And: What did you see at the checkout page when you were previously logged in?

I've got the following:

[x] Enter email address two times
[x] Display the account information pane for authenticated users.

[x] Require login of existing users.
[ ] Automatically create a user account for new customers
[x] Allow new customers to create a new account
[x] Automatically login the new user.
[ ] Send welcome e-mail after creating a new user.

capfive’s picture

I'll have a check for you this morning but from memory is 1 page checkout :)

capfive’s picture

Sorry didn't read properly
[x] Enter email address two times (tried with it off)
[x] Display the account information pane for authenticated users.

[x] Require login of existing users.
[ ] Automatically create a user account for new customers
[x] Allow new customers to create a new account
[x] Automatically login the new user.
[x] Send welcome e-mail after creating a new user.

haggins’s picture

Do you have any rules activated which auto-register new users?

capfive’s picture

no, only the commerce one which comes with commerce checkout - "Create a new account for an anonymous order"

Could this be causing an issue?

I do have a VERY complex setup with commerce licence/licence billing, i will have to bench this and try it with the next commerce shop i set up to see if it might have been the way my current site was set up, it is too far past standard to be disabling modules and such now.

I appreciate the troubleshooting help though and hopefully I can test it soon.

legolasbo’s picture

@capfive please report back if (and how) you can reproduce the issue on a vanilla installation.

nyleve101’s picture

Hi @legolasbo,

I also experienced this problem on a vanilla drupal installation with Commerce Recurring 2.x. I entered a previously unregistered email address on Checkout and then clicked 'back' on the Review order page. When I returned to the checkout page I also experienced the issue @capfive mentioned of seeing " xxx is already a registered user, please put in the password to continue" despite there being no password field. This issue didn't occur with patch 27.

Hope that helps

rei’s picture

with patch #40:

For anonymous order , If Email is Found on the database:
===================================
Problem step:
- click 'Continue to next step',
- at the next page (review order page) click 'Go Back' button,
- click 'Continue to next step' again,
- Error Message appear:There is already an account registered to x@x.xxx. Please enter your password to continue checkout.
- user can't finish the checkout

OR

Login first, make order, and then checkout
error message appear: There is already an account registered to x@x.xxx. Please enter your password to continue checkout.

Patch #38 :
IF Email is found on the database, AND login button is Not presssed, but directly click 'Continue to next step',
then Error Message appear:

Notice: Undefined variable: order in commerce_checkout_login_checkout_form_new_user_submit() (line 371 of /home/quickstart/websites/store.dev/sites/all/modules/commerce_checkout_login/commerce_checkout_login.module).
Notice: Trying to get property of non-object in commerce_cart_order_convert() (line 1016 of /home/quickstart/websites/store.dev/sites/all/modules/commerce/modules/cart/commerce_cart.module).
Warning: Creating default object from empty value in commerce_cart_order_convert() (line 1019 of /home/quickstart/websites/store.dev/sites/all/modules/commerce/modules/cart/commerce_cart.module).
Notice: Undefined property: stdClass::$type in commerce_cart_order_convert() (line 1025 of /home/quickstart/websites/store.dev/sites/all/modules/commerce/modules/cart/commerce_cart.module).
EntityMalformedException: Missing bundle property on entity of type commerce_order. in entity_extract_ids() (line 7766 of /home/quickstart/websites/store.dev/includes/common.inc).

I think if login button is to be removed, then system should login the user automatically after entering valid password

haggins’s picture

@rei: have you disabled the rule to automatically create an anonymous user for orders?

legolasbo’s picture

Status: Needs review » Needs work

I have been able to reproduce the issue on vanilla Drupal. I'm planning on fixing the problem, but I'm currently not sure when I will have time to do so. Hopefully before/during Drupalcon Barcelona.

legolasbo’s picture

Status: Needs work » Needs review
FileSize
7.68 KB
22.15 KB

Attached patch should fix the issues mentioned in 46, 49, 53 and 54. It also cleans up and simplifies the code a bit.

rei’s picture

with patch 57 error message gone.

@legolasbo: can you automatically login the user after entering the valid password ? since there is no login button now. if you can, then the saved address can be shown to logged in user (saved address from commerce_single_address or commerce_addressbook)

btw, the rule "Create a new account for an anonymous order" should be disabled or not with this patch?

legolasbo’s picture

@rei,

With the patch, the module now does the following (default settings, no special actions needed):

Automatically Verify e-mail address after it has been entered using AJAX (if javascript is disabled, this verification will happen on form submit). If the address exists, add a password field to the form.

On form submit it will then do the following:
If a new address is entered,

  1. create user
  2. login user
  3. continue checkout

If an existing address is entered and the password is correct:

  1. Login user
  2. Continue checout

If an existing address is entered and the password is incorrect:

  1. Return to the form displaying a error message.
legolasbo’s picture

FileSize
19.23 KB
18.12 KB

Also fixed the additional options regarding username and/or password selection. This also greatly simplified the code.

When configuring the checkout_pane you can now allow the user to choose their own username and/or password.

rei’s picture

@legolasbo,

what I mean is:

If the email address exists, add a password field to the form.
If the password entered is correct,
THEN Immediately/Automatically Login the user, Don't wait user to submit the form

This way, user saved Address will be shown, No need to entering the address again.

legolasbo’s picture

If the email address exists, add a password field to the form.
If the password entered is correct,
THEN Immediately/Automatically Login the user, Don't wait user to submit the form

This way, user saved Address will be shown, No need to entering the address again.

This can causes an infinite loop, which is why I left it out. See #2494891: Safari Incorrect Stored Password Causes Endless AJAX Loop.

blasthaus’s picture

Glad to see this module getting some love. A few suggestions:

You can use the following to get a valid username and avoid a lot of lines:

<?php
$mail = commerce_order_get_properties($order, array(), 'mail_username');
?>

Then, for creating the actual account:

<?php 
$account = commerce_checkout_create_account($name, $mail, $pass, $status, $notify); 
?>

However, rather than allowing them to set a password, maybe set them up with something that needs to be changed and set a message AFTER the order complete with a link to /user/%uid/edit to set their password.

For security, the flood control should be implemented.

rei’s picture

@legolasbo,
so, this patch will kill the commerce_address_book and commerce_single_address functionality then ?
since user have to enter again and again the saved billing and shipping address.

legolasbo’s picture

@blasthaus,

You can use the following to get a valid username and avoid a lot of lines:

$mail = commerce_order_get_properties($order, array(), 'mail_username');

Then, for creating the actual account:

$account = commerce_checkout_create_account($name, $mail, $pass, $status, $notify); 

I will look into this suggestion.

However, rather than allowing them to set a password, maybe set them up with something that needs to be changed and set a message AFTER the order complete with a link to /user/%uid/edit to set their password.

Allowing them to choose a password is a feature. By default the user will have an automatically generated password. Setting a link to /user/%uid/edit to set the password will not work however, since they need to know their original password. The only way they can change the password is by clicking the link in the confirmation mail.

For security, the flood control should be implemented.

Great idea, thanks.

@rei,

I have had time to think about this and I think I've thought of a way to prevent the infinite loop. So I will work on automatically logging in the user.

blasthaus’s picture

@legolasbo

The only way they can change the password is by clicking the link in the confirmation mail.

For the choose password feature, you can generate and then pass a session token to avoid having to enter the original password as done in href="https://api.drupal.org/api/drupal/modules%21user%21user.pages.inc/functi..." target="_blank">user_pass_reset()

Something like this inside of an implementation of hook_commerce_checkout_complete($order)

<?php
  user_login_finalize();
  // Let the user's password be changed without the current password check.
  $token = drupal_random_key();
  $_SESSION['pass_reset_' . $user->uid] = $token;
  $reset_link  = l(t('Click here'), 'user/' . $user->uid . '/edit', array('query' => array('pass-reset-token' => $token)));
  drupal_set_message(t('An account has been created for you at @sitename. !reset_link to create your account password.', array('!reset_link' => $reset_link, '@sitename' => variable_get('site_name', 'this site'))));
?>

I would vote to not log in a new user in until they successfully complete the order. Your existing password code for a new user could also be put in a custom pane after the payment pane, so they can set their password and get logged in before the 'order complete' pane. However that might require a module like commerce_rules_extra to make a conditional rule to only show the pane for anonymous users.

legolasbo’s picture

@Blasthaus,

Thanks for pointing out how to allow a password change. I'll also work on changing that. I agree that not logging in the user until the order is completed successfully is a good idea. In fact, the user probably shouldn't be created until then.

cameronbprince’s picture

I'm also glad to see some progress with this module. I use it on nearly all the e-commerce sites I set up, warts and all.

I tested the #60 patch and it works well and does seem to resolve the loop Safari was getting into. Unfortunately, I had to roll it back due to new accounts being created prior to checkout completion. This is a confusion point for users as they see the site magically change from not logged in to logged in between checkout steps. It would also equate to additional required maintenance to clean up accounts created and not used when carts are abandoned. Finally, the normal welcome email is never sent, so the user has no way of knowing how to set their password.

legolasbo’s picture

Status: Needs review » Needs work
FileSize
17.64 KB
8.96 KB

Attached patch addresses the issues raised in #63. The option to choose a password has been removed again, but the link to /user/%/edit is still absent. I will work on that and the other comments when I have more time on my hands.

legolasbo’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Parent issue: » #2580227: [META] 2.0 release

I have become the maintainer of the module and have started work on a new branch where I've rewritten the basic functionality of the module and added tests. Most of what my previous patches have been doing is way out of scope for this issue. I am therefor not going to continue along that path and will refocus future effort on the initial feature request, which is to require a logged in user before being able to checkout. Any other features added in the previous patches are still on the table for 2.x but will each be in issues of their own.

legolasbo’s picture

Status: Needs work » Fixed

I've taken a look at the original issue.

Current module:

Existing user - if they do not click the login button in the pane form, nothing happens - ie no authentication check of the password, no login, and order is not converted to an authenticated user order

This is correct for 7.x-1.x-dev, but in 7.x-2.x-dev the password field is always required to place an order using an existing e-mail address. Also the login button has been removed and account verification now occurs upon continuation of the checkout process. This also ensures graceful degradation when javascript is disabled.

Proposed changes:

Existing users
Require login of existing users - If enabled, the password field is required to proceed to the next checkout page. The customer will be logged in and the order converted to an authenticated user order

As stated above, the password field is now always required.

New users
Automatically create a user account for new customers - If enabled, a new user will be created based on the order's email address. The user is created on submit of the checkout page. This is similar to Commerce's default rule "on checkout complete" to create the user.
Automatically login the new user - If enabled, the new user will be logged in and the order converted to an authenticated user order.
With these changes, the order is associated with a user account on the initial checkout page. This solves many issues where the user account is created after payment processing has taken place.

As stated in this quote, Commerce's default rule allows for user creation on order completion. Creating accounts before order completion will result in many new accounts being created without checkout being completed. That in turn will result in a lot of unused accounts and customer confusion as stated in #66 and #68. Besides that it would also block anonymous checkouts completely. Any changes to user creation are therefor out of scope and should in my opinion take place on a separate issue.

For the reasons mentioned above I believe that the original issue is fixed appropriately in 7.x-2.x-dev and this issue can be considered fixed.

memsis’s picture

As stated in this quote, Commerce's default rule allows for user creation on order completion.

But it doesn't allow the user to choose their password and won't log them in after the transaction.

I am looking for a way to allow user creation while going trough the checkout, instead of the checkout redirect option that add a step to the checkout. Having a panel that takes care of either making the user log in or creating their account would be a perfect match.

legolasbo’s picture

@memsis,

Work is underway in #1104226: Allow users to register during checkout to add account creation support.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.