Magento – How to convert a quote to order

magento2payment-gatewaypayment-methodssales-order

To finish implementing a custom payment method I need to know how to convert the quote to the actual order.

From payment gateway, my custom controller is called.

Inside that controller, I can access Checkout Session object.

When I call getQuoteId on that object, I get the actual quote id, however, when I call getLastRealOrderId, nothing is returned, so I think I need to do a previous step first.

I have read https://mage2.pro/t/topic/732 and https://mage2.pro/t/topic/731 but those sites only shows code, with no explanation, so I need a little guide to use method calls shown there.

The order should be created in both when failure and success payment occured.

Furthermore, when success payment, the confirmation e-mail for customer should be sent automatically.

How can I do it?

EDIT:

This is a controller that is called using $.post jquery method:

class Store extends \Magento\Framework\App\Action\Action {

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

/**
 * @param \Magento\Framework\App\Action\Context $context
 * @param \Psr\Log\LoggerInterface $logger
 */
public function __construct(
        \Magento\Framework\App\Action\Context $context, 
        \Psr\Log\LoggerInterface $logger
) {
    $this->_logger = $logger;
    parent::__construct($context);
}

/**
 * Almacena los datos para posterior recuperacion
 *
 * @return void
 * @SuppressWarnings(PHPMD.ExitExpression)
 */
public function execute() {
    if (!$this->getRequest()->isPost()) {
        return;
    }

    try {
        $data = $this->getRequest()->getPostValue();
        ----
    }
    } catch (RemoteServiceUnavailableException $e) {
        $this->_logger->critical($e);
        $this->getResponse()->setStatusHeader(503, '1.1', 'Service Unavailable')->sendResponse();
        /** @todo eliminate usage of exit statement */
        exit;
    } catch (\Exception $e) {
        $this->_logger->critical($e);
        $this->getResponse()->setHttpResponseCode(500);
    }
}

Quote Id is received by POST method in execute() function. I need to be able to create the order from there. How can I define the constructor in the proper way? I am thinking that maybe constructor parameters are specified as @params comments, aren't they? I would found this to be strange, since those are comments in PHP, but maybe Magento uses that information to do such a definition.

Best Answer

I'm going to try to make it simple and understandable.

So to convert a quote to an order, you need to use the \Magento\Quote\Api\CartManagementInterface interface.

Use dependency injection in your constructor to have an accessible variable for this one:

protected $_quoteManagement;

public function __construct(\Magento\Framework\App\Action\Context $context,
    \Psr\Log\LoggerInterface $logger,
    \Magento\Quote\Api\CartManagementInterface $quoteManagement)
{
    $this->_logger = $logger;
    //$this->_quoteManagement = $quoteManagement;
    $this->quoteManagement = $quoteManagement;
    parent::__construct($context);
}

Then to convert a quote to an order you can do the following in your execute method:

$order = $this->quoteManagement->submit($quote);

Regarding the getLastRealOrderId it is not managed automatically by the order creation and thus you need to use your _checkoutSession object like this:

$this->_checkoutSession
    ->setLastOrderId($order->getId())
    ->setLastRealOrderId($order->getIncrementId());

If you need more details about quote conversion I reckon you should have a look at the saveOrder() method of \Magento\Checkout\Model\Type\Onepage.php

Related Topic