Context:
- How to cancel an order programmatically?
- How to cancel the last order on an unsuccessfull payment?
- How is
\Magento\Paypal\Helper\Checkout::cancelCurrentOrder()
implemented and used?
Implementation
981d1f/app/code/Magento/Sales/Model/Order.php#L1128-L1176
/**
* Prepare order totals to cancellation
*
* @param string $comment
* @param bool $graceful
* @return $this
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function registerCancellation($comment = '', $graceful = true)
{
if ($this->canCancel() || $this->isPaymentReview() || $this->isFraudDetected()) {
$state = self::STATE_CANCELED;
foreach ($this->getAllItems() as $item) {
if ($state != self::STATE_PROCESSING && $item->getQtyToRefund()) {
if ($item->getQtyToShip() > $item->getQtyToCancel()) {
$state = self::STATE_PROCESSING;
} else {
$state = self::STATE_COMPLETE;
}
}
$item->cancel();
}
$this->setSubtotalCanceled($this->getSubtotal() - $this->getSubtotalInvoiced());
$this->setBaseSubtotalCanceled($this->getBaseSubtotal() - $this->getBaseSubtotalInvoiced());
$this->setTaxCanceled($this->getTaxAmount() - $this->getTaxInvoiced());
$this->setBaseTaxCanceled($this->getBaseTaxAmount() - $this->getBaseTaxInvoiced());
$this->setShippingCanceled($this->getShippingAmount() - $this->getShippingInvoiced());
$this->setBaseShippingCanceled($this->getBaseShippingAmount() - $this->getBaseShippingInvoiced());
$this->setDiscountCanceled(abs($this->getDiscountAmount()) - $this->getDiscountInvoiced());
$this->setBaseDiscountCanceled(abs($this->getBaseDiscountAmount()) - $this->getBaseDiscountInvoiced());
$this->setTotalCanceled($this->getGrandTotal() - $this->getTotalPaid());
$this->setBaseTotalCanceled($this->getBaseGrandTotal() - $this->getBaseTotalPaid());
$this->setState($state)
->setStatus($this->getConfig()->getStateDefaultStatus($state));
if (!empty($comment)) {
$this->addStatusHistoryComment($comment, false);
}
} elseif (!$graceful) {
throw new \Magento\Framework\Exception\LocalizedException(__('We cannot cancel this order.'));
}
return $this;
}
Details:
- How is
\Magento\Sales\Model\Order::isPaymentReview()
implemented and used? - How is
\Magento\Sales\Model\Order::isFraudDetected()
implemented and used?
Usages
1. \Magento\Authorizenet\Controller\Adminhtml\Authorizenet\Directpost\Payment/Redirect::_returnQuote()
2. \Magento\Authorizenet\Controller\Directpost\Payment::_returnCustomerQuote()
981d1f/app/code/Magento/Authorizenet/Controller/Directpost/Payment.php#L118-L150
/**
* Return customer quote
*
* @param bool $cancelOrder
* @param string $errorMsg
* @return void
*/
protected function _returnCustomerQuote($cancelOrder = false, $errorMsg = '')
{
$incrementId = $this->_getDirectPostSession()->getLastOrderIncrementId();
if ($incrementId && $this->_getDirectPostSession()->isCheckoutOrderIncrementIdExist($incrementId)) {
/* @var $order \Magento\Sales\Model\Order */
$order = $this->_objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId($incrementId);
if ($order->getId()) {
try {
/** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
$quoteRepository = $this->_objectManager->create('Magento\Quote\Api\CartRepositoryInterface');
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $quoteRepository->get($order->getQuoteId());
$quote->setIsActive(1)->setReservedOrderId(null);
$quoteRepository->save($quote);
$this->_getCheckout()->replaceQuote($quote);
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
}
$this->_getDirectPostSession()->removeCheckoutOrderIncrementId($incrementId);
$this->_getDirectPostSession()->unsetData('quote_id');
if ($cancelOrder) {
$order->registerCancellation($errorMsg)->save();
}
}
}
}
3. \Magento\Authorizenet\Model\Directpost::declineOrder()
981d1f/app/code/Magento/Authorizenet/Model/Directpost.php#L793-L816
/**
* Register order cancellation. Return money to customer if needed.
*
* @param \Magento\Sales\Model\Order $order
* @param string $message
* @param bool $voidPayment
* @return void
*/
protected function declineOrder(\Magento\Sales\Model\Order $order, $message = '', $voidPayment = true)
{
try {
$response = $this->getResponse();
if (
$voidPayment && $response->getXTransId() && strtoupper($response->getXType())
== self::REQUEST_TYPE_AUTH_ONLY
) {
$order->getPayment()->setTransactionId(null)->setParentTransactionId($response->getXTransId())->void();
}
$order->registerCancellation($message)->save();
} catch (\Exception $e) {
//quiet decline
$this->getPsrLogger()->critical($e);
}
}
4. \Magento\Paypal\Helper\Checkout::cancelCurrentOrder()
Details: How is \Magento\Paypal\Helper\Checkout::cancelCurrentOrder()
implemented and used?
5. \Magento\Paypal\Model\Ipn::_registerPaymentFailure()
6. Magento/Paypal/Model/Payflowlink::_getOrderFromResponse()
7. \Magento\Sales\Model\Order::cancel()
Details: How is \Magento\Sales\Model\Order::cancel()
implemented and used?