Magento – Magento 2 Restore Quote/Cart after order is cancelled/Failed

magento-2.1magento2ordersquote

I am Trying to Restore Quote/Cart after order is cancelled/Failed in custom payment gateway (CCAvenue) but the problem it the quantity of item restored is doubled.

protected function _cancelPayment($errorMsg = '')
    {
        $errorMsg = trim(strip_tags($errorMsg));

        $gotoSection = false;
        $this->_checkoutHelper->cancelCurrentOrder($errorMsg);
        if ($this->_checkoutSession->restoreQuote()) {
            //Redirect to payment step
            $gotoSection = 'paymentMethod';
        }

        return $gotoSection;
    }

in above code $this->_checkoutHelper->cancelCurrentOrder($errorMsg); is use to cancel last real order and $this->_checkoutSession->restoreQuote() is use to restore the cart but the problem is both the statements increase quantity of product.

Eg.

  • suppose I have Product XYZ with stock quantity: 1

  • When I add product to cart and Checkout The order is placed and stock is reduced to 0.

  • but when I click cancel on Payment gateway I return Back to my site and the above method is called.
  • And now the stock increase to 2 because $this->_checkoutHelper->cancelCurrentOrder($errorMsg); and $this->_checkoutSession->restoreQuote() increase the quantity of the product.

Is there any way to do both cancel order and restore quote while restore stock only once.

Edit: Complete Controller File.

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Ccavenuepay\Controller;
use Magento\Ccavenuepay\Helper\Data;
/**
 * Payflow Checkout Controller
 */
abstract class Ccavenuepay extends \Magento\Framework\App\Action\Action
{
    /**
     * @var \Magento\Checkout\Model\Session
     */
    protected $_checkoutSession;

    /**
     * @var \Magento\Sales\Model\OrderFactory
     */
    protected $_orderFactory;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $_logger;
    protected $logger;

    /**
     * @var \Magento\Ccavenuepay\Model\Ccavenuepay
     */
    protected $_ccavenuepay;

    /**
     * @var \Magento\Ccavenuepay\Helper\Checkout
     */
    protected $_checkoutHelper;

    /**
     * @var \Magento\Ccavenuepay\Helper\data
     */
    protected $_ccavenuepayHelper;

    /**
     * Redirect block name
     * @var string
     */
    protected $_redirectBlockName = 'ccavenuepay.iframe';

    /**
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Sales\Model\OrderFactory $orderFactory
     * @param \Magento\Ccavenuepay\Model\PayflowlinkFactory $ccavenuepay
     * @param \Magento\Ccavenuepay\Helper\Checkout $checkoutHelper
     * @param \Psr\Log\LoggerInterface $logger
     */



    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Checkout\Model\Session $checkoutSession,
        \Magento\Sales\Model\OrderFactory $orderFactory,
        \Magento\Ccavenuepay\Model\Ccavenuepay $ccavenuepay,
        \Magento\Ccavenuepay\Helper\Checkout $checkoutHelper,
        \Psr\Log\LoggerInterface $logger
    ) {

        $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/test.log');
        $this->logger = new \Zend\Log\Logger();
        $this->logger->addWriter($writer);
        $this->logger->info("__construct=====Ccavenuepay extends \Magento\Framework\App\Action\Action");


        $this->_checkoutSession = $checkoutSession;
        $this->_orderFactory = $orderFactory;
        $this->_logger = $logger;
        $this->_ccavenuepay = $ccavenuepay;
        $this->_checkoutHelper = $checkoutHelper;
        //$this->_ccavenuepayHelper = $this->_ccavenuepay;
        parent::__construct($context);
    }




    /**
     * Cancel order, return quote to customer
     *
     * @param string $errorMsg
     * @return false|string
     */
    protected function _cancelPayment($errorMsg = '')
    {
        $errorMsg = trim(strip_tags($errorMsg));

        $gotoSection = false;
        $this->_checkoutHelper->cancelCurrentOrder($errorMsg);
        if ($this->_checkoutSession->restoreQuote()) {
            //Redirect to payment step
            $gotoSection = 'paymentMethod';
        }

        return $gotoSection;
    }

    public function errorAction()
    {
        $this->_redirect('checkout/onepage/');
    }

    //check_module_upload
    //newmoduleupdate_now
    /**
     * Check if email is registered at Moneybookers
     */



    protected function _getCheckout()
    {
        return $this->_objectManager->get('Magento\Checkout\Model\Session');
    }
    /**
     * Get session model
     *
     * @return \Magento\Ccavenuepay\Model\Ccavenuepay\Session
     */
    protected function _getCcavenuepayPostSession()
    {
        return $this->_objectManager->get('Magento\Ccavenuepay\Model\Ccavenuepay\Session');
    }
    protected function _getHelper()
    {
        return $this->_ccavenuepay->getHelper();
    }
}

Best Answer

Below is the solution for Magento 2.3.5

Please override Failure.php and change public function as below,

public function execute()
{
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $_checkoutSession = $objectManager->create('\Magento\Checkout\Model\Session');
    $_quoteFactory = $objectManager->create('\Magento\Quote\Model\QuoteFactory');
    
    $order = $_checkoutSession->getLastRealOrder();
    $quote = $_quoteFactory->create()->loadByIdWithoutStore($order->getQuoteId());
    if ($quote->getId()) {
        $quote->setIsActive(1)->setReservedOrderId(null)->save();
        $_checkoutSession->replaceQuote($quote);
        $resultRedirect = $this->resultRedirectFactory->create();
        $resultRedirect->setPath('checkout/cart');
        //$this->messageManager->addWarningMessage('Payment Failed.');
        return $resultRedirect;
    }
}
Related Topic