1

in the default onepage checkout, an existing customer can choose to login within the checkout process. this fires the usual observers. my module is observing the event sales_quote_merge_before to check if a persistent cart quote is being merged into the current quote. if so, the customer should be redirected to the /checkout/cart page.

this works fine for non-checkout pages. but setting the setBeforeAuthUrl and/or setAfterAuthUrl on the \Magento\Customer\Model\Session object does not seem to work for logins within the checkout process.

here's my (simplified) observer that works for non-checkout logins, that I now need to make work with the checkout login as well:

namespace My\Module\Observer;

class SalesQuoteMergeBefore implements \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Magento\Customer\Model\Session
     */
    protected $_customerSession;

    /**
     * @var \Magento\Framework\View\Element\Context
     */
    protected $_context;

    /**
     * SalesQuoteMergeBefore constructor.
     * @param \Magento\Customer\Model\Session $customerSession
     * @param \Magento\Framework\View\Element\Context $context
     */
    public function __construct(
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Framework\View\Element\Context $context
    )
    {
        $this->_customerSession = $customerSession;
        $this->_context = $context;
    }

    /**
     * redirect to cart when quote was merged
     *
     * @see \Magento\Quote\Model\Quote::merge()
     * @param \Magento\Framework\Event\Observer $observer
     * @return $this
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Quote\Model\Quote $target */
        $target = $observer->getData('source');
        if ($target && $target->hasItems())
        {
            $url = $this->_context->getUrlBuilder()->getUrl('checkout/cart');

            // setting just the after_auth_url does not seem to be enough...
            $this->_customerSession->setBeforeAuthUrl($url);
            $this->_customerSession->setAfterAuthUrl($url);
        }

        return $this;
    }
}

my understanding is that I somehow need to signal the javascript app a redirect should happen, but I failed to find any way to do this.

1

the \Magento\Customer\Controller\Ajax\Login::execute() function checks for a login_redirect cookie. if there's such a cookie, its value will be returned as the json attribute redirectUrl, which in turn Magento_Customer/js/action/login.js uses as a redirect target after the successful login.

so faking the cookie is a simple way to control where the user should be redirected when logged in through the checkout ajax login. the relevant updated part of the observer in the question:

$request = $this->_context->getRequest();
if ($request instanceof \Magento\Framework\App\Request\Http && $request->isAjax()) {
    // fake redirect cookie
    /** @see \Magento\Customer\Controller\Ajax\Login::execute() */
    $_COOKIE[\Magento\Customer\Model\Account\Redirect::LOGIN_REDIRECT_URL] = $url;
} else {
    // setting just the after_auth_url does not seem to be enough...
    $this->_customerSession->setBeforeAuthUrl($url);
    $this->_customerSession->setAfterAuthUrl($url);
}

one could also get the instance of \Magento\Customer\Model\Account\Redirect and use setRedirectCookie($url), but I did not want to actually set a cookie in the response as the login at this point was already completed successfully.

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.