Cancelling Order Placement Before Order Object Creation from Quote

ce-1.8.1.0checkoutevent-observerordersquote

I would like to hook up to an event that fires when a customer clicks on the button "Place Order", do some validations and then decide whether to proceed with checkout (and payment) or not. If not, I'd like to cancel the order placement, but keep the items in the cart (quote hasn't been converted to order yet) and throw a message like "Your order could not be processed".

I hooked to the checkout_submit_all_after event, which fires when I click on the button. I raised an exception and just got a browser alert "undefined" and remained in the page. I checked my account and the order was placed. So I added this:

$order->cancel()->save();

This cancels the order so that it is not placed, but the cart is emptied and I get no feed back on what went wrong during checkout. Instead I'm redirected to the cart page with the message "No items in your cart".

tldr: I want to be able to validate an order before saving it, so that it can be cancelled displaying a message similar to the one that appears when the payment method fails ("Your order could not be processed").

Best Answer

Just hookup your observer to the sales_order_place_before

app/code/local/my/module/etc/config.xml

<frontend>
    <events>
        <sales_order_place_before>
            <observers>
                <securityChecks>
                    <class>my_module/observer</class>
                    <method>placeOrder</method>
                </securityChecks>
            </observers>
        </sales_order_place_before>
    </events>
</frontend>

Perform your checks and raise an exception. Magento will return an error in json format to your checkout page and Magento's checkout will redirect you back to your cart; the order will not be processed and the cart (quote) will not be emptied.

app/code/local/my/Module/Model/Observer.php

class My_Module_Model_Observer
{
    public function placeOrder(Varien_Event_Observer $observer)
    {
        $order = $observer->getEvent()->getOrder();

        //perform checks

        if(!$passed)
        {
            Mage::throwException("An error ocurred");
        }

    }

}
Related Topic