Question

On a clean, vanilla install of Magento 1.9.2.4, patched with SUPEE-8788, SUPEE-9652 and SUPEE-9767, and with the new 'Enable Form Key Validation On Checkout' setting turned on, following a successful new customer registration checkout on the default One Page Checkout, no new customer is created and the customer is not logged in, although the order goes through fine.

Turning the 'Enable Form Key Validation On Checkout' setting off makes this work again. Has anybody else had this issue? It doesn't seem to matter which shipping/payment methods are used.

I've since tried this with a fresh, unaltered installation of Magento 1.9.3.3 and it seems to have the same issue. When registering a new customer through the one page checkout, no customer is created even through the order goes through fine, as long as the 'Enable Form Key Validation On Checkout' setting is switched on.

Was it helpful?

Solution

Ok here's the real bug fix I came up with.

Edit /skin/frontend/base/default/js/opcheckout.js and edit the setMethod() method by replacing:

setMethod: function(){
    if ($('login:guest') && $('login:guest').checked) {
        this.method = 'guest';
        new Ajax.Request(
            this.saveMethodUrl,
            {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'guest'}}
        );
        Element.hide('register-customer-password');
        this.gotoSection('billing', true);
    }
    else if($('login:register') && ($('login:register').checked || $('login:register').type == 'hidden')) {
        this.method = 'register';
        new Ajax.Request(
            this.saveMethodUrl,
            {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'register'}}
        );
        Element.show('register-customer-password');
        this.gotoSection('billing', true);
    }
    else{
        alert(Translator.translate('Please choose to register or to checkout as a guest').stripTags());
        return false;
    }
    document.body.fire('login:setMethod', {method : this.method});
},

With:

setMethod: function(){
    var formKey = $('checkout-step-login').select('[name=form_key]')[0].value;
    if ($('login:guest') && $('login:guest').checked) {
        this.method = 'guest';
        new Ajax.Request(
            this.saveMethodUrl,
            {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'guest', form_key:formKey}}
        );
        Element.hide('register-customer-password');
        this.gotoSection('billing', true);
    }
    else if($('login:register') && ($('login:register').checked || $('login:register').type == 'hidden')) {
        this.method = 'register';
        new Ajax.Request(
            this.saveMethodUrl,
            {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'register', form_key:formKey}}
        );
        Element.show('register-customer-password');
        this.gotoSection('billing', true);
    }
    else{
        alert(Translator.translate('Please choose to register or to checkout as a guest').stripTags());
        return false;
    }
    document.body.fire('login:setMethod', {method : this.method});
},

That'll do it while we're waiting for the v2 of the patch

OTHER TIPS

When you select register and continue, the JS script calls checkout.setMethod(), which is located in skin/frontend/base/default/js/opcheckout.js. From there we can see it makes an AJAX POST request to this.saveMethodUrl, but the only paramter it passes is method. If we look at Mage_Checkout_OnepageController::saveMethodAction, which is the target of that AJAX request, we can see that the patch added:

if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) {
        return;
}

Since _validateFormKey looks for a form_key parameter in the request, and since the JS setMethod request didn't send this when it made the AJAX request, it's simply returning early and doing nothing. Back to the setMethod function and we can see that since it doesn't attempt to do anything with a return value, nothing else happens and the JS continues. At this point the JS has set this.method = 'register' but the quote hasn't been updated, so checkout_method is the default 'guest'.

Since the JS knows the customer selected register, it displays the password fields, so on the face of it, it looks like you're registering. But as far as the PHP side is concerned, it's a guest checkout, so it doesn't create the customer when checkout is complete.

Edit: the simplest fix is to comment out those three lines from saveMethodAction. The more correct/complex solution is that setMethod should be grabbing the form_key from the page and sending it with the AJAX request.

Full credits go to Peter for the solution! I would like to point out step by step instruction what to change.

Go to app/code/core/Mage/Checkout/controllers/OnepageController.php

Locate:

 public function saveMethodAction()
{
    if ($this->_expireAjax()) {
        return;
    }

    if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) {
        return;
    }

Comment out the line with /* */ tags.

 public function saveMethodAction()
{
    if ($this->_expireAjax()) {
        return;
    }

    /*if ($this->isFormkeyValidationOnCheckoutEnabled() && !$this->_validateFormKey()) {
        return;
    }*/

A good point to start:

Security Patch SUPEE-9767 - Possible issues?

You need to update your template files. Please note there are only a few hours from the release of this patch and for the moment we have to deal with what is public. I am pretty sure in the next days things will get clarified.

EDIT: Thank you for down voting! I am sorry I cannot give a solution in 8 hours from releasing this patch.

Thanks for the patch @ Raphael at Digital Pianism.

For convenience, I created a diff so you can quickly apply the patch.

 skin/frontend/base/default/js/opcheckout.js | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/skin/frontend/base/default/js/opcheckout.js b/skin/frontend/base/default/js/opcheckout.js
index 8935793af..9ccbe61a9 100644
--- a/skin/frontend/base/default/js/opcheckout.js
+++ b/skin/frontend/base/default/js/opcheckout.js
@@ -165,20 +165,21 @@ Checkout.prototype = {
     },

     setMethod: function(){
+        var formKey = $('checkout-step-login').select('[name=form_key]')[0].value;
         if ($('login:guest') && $('login:guest').checked) {
             this.method = 'guest';
-            var request = new Ajax.Request(
+            new Ajax.Request(
                 this.saveMethodUrl,
-                {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'guest'}}
+                {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'guest', form_key:formKey}}
             );
             Element.hide('register-customer-password');
             this.gotoSection('billing', true);
         }
         else if($('login:register') && ($('login:register').checked || $('login:register').type == 'hidden')) {
             this.method = 'register';
-            var request = new Ajax.Request(
+            new Ajax.Request(
                 this.saveMethodUrl,
-                {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'register'}}
+                {method: 'post', onFailure: this.ajaxFailure.bind(this), parameters: {method:'register', form_key:formKey}}
             );
             Element.show('register-customer-password');
             this.gotoSection('billing', true);

Version 2 of the SUPEE-9767 patch was released earlier today, along with Magento CE 1.9.3.4. V2 fixes a number of issues, including this checkout registration bug.

You can upgrade to the latest version (1.9.3.4), or revert V1 and then apply V2 of the patch. Either option will resolve the issue.

The official change in V2 is effectively the same as Peter O'Callaghan described, removing the three lines added to Mage_Checkout_OnepageController::saveMethodAction.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top