Change shipping rate based on shipping address in Magento



In this tutorial I will show you how to change shipping rate based on shipping address in Magento.  I have created a custom module to set the shipping rate based on shipping address country.

I have added an observer on save shipping address after. I have added an event in config.xml of checkout.

<events>
	<checkout_controller_onepage_save_shipping_address_after>
		<observers>
			<getShippingMethods>
				<class>checkout/observer</class>
				<method>getShippingMethods</method>
			</getShippingMethods>
		</observers>
	</checkout_controller_onepage_save_shipping_address_after>
</events>

Below is the code of the observer of the event. Here you can set the shipping rate on your shipping method based on the customer shipping address country.

public function getShippingMethods($observer)
{
	$session = Mage::getSingleton('checkout/session');
	$quote=Mage::getSingleton('checkout/session')->getQuote();
	$quoteid=$quote->getId(); 
	if($quoteid) {                   
		try{
			$address=$quote->getShippingAddress();
			if($address->getAddressType()=='shipping'){
				$countryId = $address->getCountry();
				$price = 30; // get the shipping rate based on the country
				
				// Find if our shipping has been included.
				$rates = $address->collectShippingRates()
						 ->getGroupedAllShippingRates();
				
				foreach ($rates as $carrier) {
					foreach ($carrier as $rate) {
						// Check with your custom shipping method code
						if($rate->getCode() == 'your_shippingmethod'){
							$rate->setPrice($price);
							$rate->save();
						}
					}
				}
				$this->collectTotals($quote, $price);
			}            
			$quote->collectTotals();
		} catch (Exception $e) {            
			Mage::logException($e);
			$response['error'] = $e->getMessage();
		}
	}
}   

public function collectTotals($quote, $price){
	$quoteid=$quote->getId(); 
	$shippingcode='freeshipping_freeshipping';
	if($quoteid) {
		try{
			$quote->setSubtotal(0);
			$quote->setBaseSubtotal(0);
			$quote->setSubtotalWithDiscount(0);
			$quote->setBaseSubtotalWithDiscount(0);
			$quote->setGrandTotal(0);
			$quote->setBaseGrandTotal(0);

			$quote->getShippingAddress()->setShippingMethod($shippingcode)->save();
			$quote->save();
			foreach ($quote->getAllAddresses() as $address) {
				$address->setSubtotal(0);
				$address->setBaseSubtotal(0);

				$address->setGrandTotal(0);
				$address->setBaseGrandTotal(0);

				$address->collectTotals();

				$quote->setSubtotal((float) $quote->getSubtotal() + $address->getSubtotal());
				$quote->setBaseSubtotal((float) $quote->getBaseSubtotal() + $address->getBaseSubtotal());

				$quote->setSubtotalWithDiscount(
					(float) $quote->getSubtotalWithDiscount() + $address->getSubtotalWithDiscount()
				);
				$quote->setBaseSubtotalWithDiscount(
					(float) $quote->getBaseSubtotalWithDiscount() + $address->getBaseSubtotalWithDiscount()
				);

				$quote->setGrandTotal((float) $quote->getGrandTotal() + $address->getGrandTotal());
				$quote->setBaseGrandTotal((float) $quote->getBaseGrandTotal() + $address->getBaseGrandTotal());

				$address->setShippingAmount($price);
				$address->setBaseShippingAmount($price);
				$address->save();
			}

			$response['message'] = 'Succcess';
		} catch (Exception $e) {            
			Mage::logException($e);
			$response['error'] = $e->getMessage();
		}
	}
}

Now dispatch the event in saveShipping method of OnepageController like below:

Mage::dispatchEvent('checkout_controller_onepage_save_shipping_address_after', array('page' => $model, 'request' => $this->getRequest()));

Hope this will help you to change shipping rate based on shipping address in magento.