4

I was originally drafting this to ask a question, but in the process I actually fixed the problem, so I'm posting this in hopes it helps someone else.

I have Magento CE 1.9.1.0 and I'm having a problem with account registration at checkout when the customer pays using PayPal. We use Templates Master's FireCheckout. Here's the scenario:

  1. Customer fills out checkout form, elects to create an account for later use, and picks PayPal as payment option
  2. Customer redirects to PP, logs in, confirms payment, is directed back to our site on the PayPal Express Review page
  3. Customer clicks final Place Order button, PayPal responds with an error (i.e. 10736 - city/state/zipcode mismatch)
  4. Customer doesn't know the issue, so clicks Place Order again.
  5. Magento session still has their account type as "register", but because of how the PayPal UK module handles PayPal Express for PayFlow customers, the customer account creation wasn't rolled back and the account was already created. So then, upon secondary submission, they are presented with the error "That customer email already exists".
  6. Customer tries and tries, sometimes eventually figuring it out, sometimes giving up.

This can easily be tested using the PP sandbox in Negative testing mode.

  1. Create an item that has free shipping and costs exactly $107.36, grand total
  2. Place an order with this item and pick PayPal as the checkout method.
  3. Follow through the entire process, you should get the 10736 error on the file submission.
  4. Try submitting again, you should get the "This customer email already exists" error

I have dug through some of the code and found that it is due in part to the Mage_Paypal_Model_Express_Checkout class in their _prepareNewCustomerQuote method. This creates and saves the customer record before the order is even placed. This is unlike the standard checkout, which creates a customer record and sets it on the quote but doesn't actually commit the customer record to the DB. It is then able to roll back the customer creation SQL call and not commit the changes, allowing the subsequent attempts to do it. But this rollback doesn't work in PP Express because it already committed the record.

I tried a few things to resolve this (see Mage_Paypal_Model_Express_Checkout around line 990):

  • I tried commenting out the $customer->save(); call in Mage_Paypal_Model_Express_Checkout. That resulted in successfully allowing the order once the error was fixed, but it never actually saved the customer record.
  • I then tried adding setCustomerId(true) when it sets the customer on the quote. I copied this from the standard checkout class: $quote->setCustomer($customer)->setCustomerId(true);. THIS FIXED IT! See answer below for details.
3

First, please follow all recommended practices and DO NOT EDIT CORE CODE!! You should create your own module and extend the PP class in question to fix this.

You need to overwrite the _prepareNewCustomerQuote method in Mage_Paypal_Model_Express_Checkout as follows (see the end of the method for the changes):

protected function _prepareNewCustomerQuote()
{
    $quote      = $this->_quote;
    $billing    = $quote->getBillingAddress();
    $shipping   = $quote->isVirtual() ? null : $quote->getShippingAddress();

    $customerId = $this->_lookupCustomerId();
    if ($customerId && !$this->_customerEmailExists($quote->getCustomerEmail())) {
        $this->getCustomerSession()->loginById($customerId);
        return $this->_prepareCustomerQuote();
    }

    $customer = $quote->getCustomer();
    /** @var $customer Mage_Customer_Model_Customer */
    $customerBilling = $billing->exportCustomerAddress();
    $customer->addAddress($customerBilling);
    $billing->setCustomerAddress($customerBilling);
    $customerBilling->setIsDefaultBilling(true);
    if ($shipping && !$shipping->getSameAsBilling()) {
        $customerShipping = $shipping->exportCustomerAddress();
        $customer->addAddress($customerShipping);
        $shipping->setCustomerAddress($customerShipping);
        $customerShipping->setIsDefaultShipping(true);
    } elseif ($shipping) {
        $customerBilling->setIsDefaultShipping(true);
    }
    /**
     * @todo integration with dynamica attributes customer_dob, customer_taxvat, customer_gender
     */
    if ($quote->getCustomerDob() && !$billing->getCustomerDob()) {
        $billing->setCustomerDob($quote->getCustomerDob());
    }

    if ($quote->getCustomerTaxvat() && !$billing->getCustomerTaxvat()) {
        $billing->setCustomerTaxvat($quote->getCustomerTaxvat());
    }

    if ($quote->getCustomerGender() && !$billing->getCustomerGender()) {
        $billing->setCustomerGender($quote->getCustomerGender());
    }

    Mage::helper('core')->copyFieldset('checkout_onepage_billing', 'to_customer', $billing, $customer);
    $customer->setEmail($quote->getCustomerEmail());
    $customer->setPrefix($quote->getCustomerPrefix());
    $customer->setFirstname($quote->getCustomerFirstname());
    $customer->setMiddlename($quote->getCustomerMiddlename());
    $customer->setLastname($quote->getCustomerLastname());
    $customer->setSuffix($quote->getCustomerSuffix());
    $customer->setPassword($customer->decryptPassword($quote->getPasswordHash()));
    $customer->setPasswordHash($customer->hashPassword($customer->getPassword()));
    //BEGIN CUSTOMIZATIONS
    //$customer->save();
    $quote->setCustomer($customer)
        ->setCustomerId(true);
    //END CUSTOMIZATIONS
    return $this;
}

After you get your customization in place, follow the steps above to duplicate the problem. Upon secondary attempt to place the order you should get the 10736 error again and NOT the This customer email already exists error. Then you can emulate the customer fixing the problem by changing your shipping method so that it no longer costs exactly $107.36. Once the order goes through you should be logged into the new customer account.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.