Add a Custom Shipping Method in Magento

Magento provides us with in-built shipping methods to use. This article will show you how add a custom shipping method in Magento 1.

Let’s take a look at how Magento currently configures its shipping methods. The configuration belongs within the Mage_Shipping module’s config.xml file.

<config>
    ....
    <default>
        ....
        <carriers>
            <flatrate>
                <active>1</active>
                <sallowspecific>0</sallowspecific>
                <model>shipping/carrier_flatrate</model>
                <name>Fixed</name>
                <price>5.00</price>
                <title>Flat Rate</title>
                <type>I</type>
                <specificerrmsg>This shipping method is currently unavailable. If you would like to ship using this shipping method, please contact us.</specificerrmsg>
                <handling_type>F</handling_type>
            </flatrate>
            <freeshipping>
            .....
            </freeshipping>
        </carriers>
    </default>
</config>

As seen above, shipping methods are found under the carriers tags. The others that you’ll see that are saved in Magento (UPS, FedEx etc) are found in Mage/Usa/etc/config.xml.

This tells us that we we went to add our own Magento custom shipping method, we should create our own module and add our shipping method within a pair of carriers tags in our config.xml configuration file.

Let’s start off by adding our module’s declaration file.

<?xml version="1.0"?>
<config>
    <modules>
        <Custom_Shippingrate>
            <codePool>local</codePool>
            <active>true</active>
        </Custom_Shippingrate>
    </modules>
</config>

Next, we need to add our module’s config.xml file.

<?xml version="1.0"?>
<config>
    <default>
        <carriers>
            <custom_shippingrate>
                <active>1</active>
                <sallowspecific>0</sallowspecific>
                <model>shippingrate/carrier_custom</model>
                <name>Custom Shipping</name>
                <price>10.00</price>
                <title>Custom Shipping</title>
            </custom_shippingrate>
        </carriers>
    </default>
</config>

To summarise what we’ve defined in our config.xml so far.

  • active – Sets the default value of the Active dropdown in the admin to be either Yes (1) or No (0).
  • sallowspecific – Sets the default value of the Ship to Applicable Countries dropdown to either be All Allowed Countries (0) or Specific Countries (1).
  • model – Specify the custom shipping method’s model.
  • name – The name of the shipping method.
  • price – The price of the shipping method.
  • title – The title of the shipping method.

Note that these values are just default values and therefore these will be made editable when we add in our custom shipping method section in the admin in System -> Configuration -> Shipping Methods. So to do this, we’ll need to add our module’s system.xml file.

<?xml version="1.0"?>
<config>
    <sections>
        <carriers>
            <groups>
                <custom_shippingrate translate="label">
                    <label>Custom Shipping</label>
                    <sort_order>1</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>0</show_in_website>
                    <show_in_store>0</show_in_store>
                    <fields>
                        <active translate="label">
                            <label>Enabled</label>
                            <frontend_type>select</frontend_type>
                            <source_model>adminhtml/system_config_source_yesno</source_model>
                            <sort_order>10</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>0</show_in_website>
                            <show_in_store>0</show_in_store>
                        </active>
                        <title translate="label">
                            <label>Title</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>20</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>0</show_in_website>
                            <show_in_store>0</show_in_store>
                        </title>
                        <price translate="label">
                            <label>Price</label>
                            <frontend_type>text</frontend_type>
                            <validate>validate-number validate-zero-or-greater</validate>
                            <sort_order>30</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>0</show_in_store>
                        </price>
                        <name translate="label">
                            <label>Method Name</label>
                            <frontend_type>text</frontend_type>
                            <sort_order>40</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>0</show_in_website>
                            <show_in_store>0</show_in_store>
                        </name>
                        <sallowspecific translate="label">
                            <label>Ship to Applicable Countries</label>
                            <frontend_type>select</frontend_type>
                            <frontend_class>shipping-applicable-country</frontend_class>
                            <source_model>adminhtml/system_config_source_shipping_allspecificcountries</source_model>
                            <sort_order>50</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>0</show_in_website>
                            <show_in_store>0</show_in_store>
                        </sallowspecific>
                        <specificcountry translate="label">
                            <label>Ship to Specific Countries</label>
                            <frontend_type>multiselect</frontend_type>
                            <sort_order>60</sort_order>
                            <source_model>adminhtml/system_config_source_country</source_model>
                            <show_in_default>1</show_in_default>
                            <show_in_website>0</show_in_website>
                            <show_in_store>0</show_in_store>
                            <can_be_empty>1</can_be_empty>
                        </specificcountry>
                    </fields>
                </custom_shippingrate>
            </groups>
        </carriers>
    </sections>
</config>

There is quite a lot of xml to digest here, but the end result is the section under the Shipping Methods area in System -> Configuration that looks like this:

Add a Custom Shipping Method in Magento

We’re not quite finished yet. Remember the model we defined earlier for our shipping rate in config.xml.

<model>shippingrate/carrier_custom</model>

Let’s go ahead and add this model.

<?xml version="1.0"?>
<config>
    <global>
        <models>
            <shippingrate>
                <class>Custom_Shippingrate_Model</class>
            </shippingrate>
        </models>
    </global>
    <default>
        <carriers>
            <custom_shippingrate>
                <active>1</active>
                <sallowspecific>0</sallowspecific>
                <model>shippingrate/carrier_custom</model>
                <name>Custom Shipping</name>
                <price>10.00</price>
                <title>Custom Shipping</title>
            </custom_shippingrate>
        </carriers>
    </default>
</config>
&lt;?php
class Custom_Shippingrate_Model_Carrier_Custom
    extends Mage_Shipping_Model_Carrier_Abstract
    implements Mage_Shipping_Model_Carrier_Interface
{
}

We need to add in some data to the model to complete the setup. Firstly, a property that contains our shipping rate code should be set.

protected $_code = 'custom_shippingrate';

This code must match the tags that you used to first define the custom shipping method in config.xml:

<?xml version="1.0"?>
<config>
    <default>
        <carriers>
            <custom_shippingrate> <!-- This -->

Secondly, we need to add our method to the list of allowed shipping methods in the getAllowedMethods() method.

public function getAllowedMethods()
{
    return array(
        'custom_shippingrate' => $this->getConfigData('name'),
    );
}

And lastly, we need to add our custom method’s collectRates() method.

public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
    $result = Mage::getModel('shipping/rate_result');
    $method = Mage::getModel('shipping/rate_result_method');

    $method->setCarrier($this->_code);
    $method->setCarrierTitle($this->getConfigData('title'));
    $method->setMethod($this->_code);
    $method->setMethodTitle($this->getConfigData('name'));
    $method->setPrice($this->getConfigData('price'));
    $method->setCost(0);
    $result->append($method);

    return $result;
}

The end result? Our shipping method sitting pretty on the checkout page:

Add a Custom Shipping Method in Magento

Note: This article is based on Magento Community/Open Source version 1.9.