Magento – “Please specify a shipping method” when programmatically creating an order

adminhtmlmagento-1.7ordersshipping-methods

I'm creating an order programmatically with code I wrote a while ago which functions correctly, when using the free shipping method (i.e freeshipping_freeshipping)

However, I'm now trying to place the order using a shipping method (which is from a module by WebShopApps).

$shipping_address->setCollectShippingRates(true)->collectShippingRates()
        ->setShippingMethod($delivery)
        ->setPaymentMethod($payment);

Where $delivery is the shipping method code. When I place the order, I get given an error

a:5:{i:0;s:33:"Please specify a shipping method.";i:1;s:1554:"#0 /chroot/home/site/site/html/app/code/core/Mage/Sales/Model/Service/Quote.php(303): Mage::throwException('Please specify ...')

When navigating to this file (Quote.php) on line 303:

protected function _validate()
{
    if (!$this->getQuote()->isVirtual()) {
        $address = $this->getQuote()->getShippingAddress();
        $addressValidation = $address->validate();
        if ($addressValidation !== true) {
            Mage::throwException(
                Mage::helper('sales')->__('Please check shipping address information. %s', implode(' ', $addressValidation))
            );
        }
        $method= $address->getShippingMethod();
        $rate  = $address->getShippingRateByCode($method);
        if (!$this->getQuote()->isVirtual() && (!$method || !$rate)) {
            Mage::throwException(Mage::helper('sales')->__('Please specify a shipping method.')); //this is line 303
        }
    }
    ....

To try and solve this, I went the route of creating an order via Adminhtml, and modifying Quote.php for testing purposes, to:

echo ($method . " and " . $rate);die();

I'm then given a blank page with the method Magento is expecting as well as the rate (which is blank), yet the order still gets created fine.
The method Magento prints out is also the exact same value that my $delivery variable had set.

What am I doing wrong?

Best Answer

You should add $quote->getShippingAddress()->collectTotals(); before your above code. It will work :

/* Important*/
 $quote->getShippingAddress()->collectTotals();// if not will show Please specify shipping methods.
 /* Important*/

$shipping_address->setCollectShippingRates(true)->collectShippingRates()
        ->setShippingMethod($delivery)
        ->setPaymentMethod($payment);
Related Topic