Feature request from leoquijano, posted on GitHub May 24, 2016
Hi,
I've been debugging some checkout issues. I noticed that several of them were fixed in Magento 2.0.7, so I went in to test our payment process using that version.
As I tested my integration with Autorize.NET DPM gateway, my checkout page froze in the "loading" stage. The order was successfully received and Authorize.NET debug log showed the information. However, something was happening after the response came back.
Sometimes I would get a window saying "Cannot place order". Sometimes it would just get stuck. However, at no point I would get more detailed information, as a developer, to what's going on.
I traced down the issue to the vendor/magento/module-authorizenet/Controller/Directpost/Payment/Place.php
file (I'm using a Composer based install). The following method would be executed:
protected function placeCheckoutOrder()
{
$result = new DataObject();
$response = $this->getResponse();
try {
$this->cartManagement->placeOrder($this->_getCheckout()->getQuote()->getId());
$result->setData('success', true);
$this->eventManager->dispatch(
'checkout_directpost_placeOrder',
[
'result' => $result,
'action' => $this
]
);
} catch (\Exception $exception) {
$result->setData('error', true);
$result->setData('error_messages', __('Cannot place order.'));
}
if ($response instanceof Http) {
$response->representJson($this->jsonHelper->jsonEncode($result));
}
}
Since I got the error message 'Cannot place order' a couple of times, I entered some logging statements, and got this in my log:
2016-05-24T23:08:42+00:00 INFO (6): Error placing order: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '000000010-1' for key 'SALES_ORDER_INCREMENT_ID_STORE_ID', query was: INSERT INTO `sales_order` (`state`, `status`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_grand_total`, `base_shipping_amount`, `base_shipping_tax_amount`, `base_subtotal`, `base_tax_amount`, `base_to_global_rate`, `base_to_order_rate`, `discount_amount`, `grand_total`, `shipping_amount`, `shipping_tax_amount`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `tax_amount`, `total_qty_ordered`, `customer_is_guest`, `customer_note_notify`, `customer_group_id`, `quote_id`, `base_shipping_discount_amount`, `base_total_due`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `increment_id`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `global_currency_code`, `order_currency_code`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `total_item_count`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `gift_message_id`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
So it is clearly an inconsistent database state. I deleted the contents from the sales_order
table and the checkout now works fine.
However, it would be a good idea to provide feedback for developers when an order placement fails. Something like this:
protected function placeCheckoutOrder()
{
$result = new DataObject();
$response = $this->getResponse();
try {
$this->cartManagement->placeOrder($this->_getCheckout()->getQuote()->getId());
$result->setData('success', true);
$this->eventManager->dispatch(
'checkout_directpost_placeOrder',
[
'result' => $result,
'action' => $this
]
);
} catch (\Exception $exception) {
$this->_logger->info("Error placing order: ".$exception->getMessage());
$result->setData('error', true);
$result->setData('error_messages', __('Cannot place order.'));
}
if ($response instanceof Http) {
$response->representJson($this->jsonHelper->jsonEncode($result));
}
}
... where $this->_logger
is an appropriately configured logger (via DI). This would provide something to the developer to work with, and prevent exception swallowing.