Creating a Shipping Module

Bart Delvaux

February 2014

(For more resources related to this topic, see here.)

Shipping ordered products to customers is one of the key parts of the e-commerce flow. In most cases, a shop owner has a contract with a shipping handler where everyone has their own business rules.

In a standard Magento, the following shipping handlers are supported:

  • DHL
  • FedEx
  • UPS
  • USPS

If your handler is not on the list, have a look if there is a module available at Magento Connect. If not, you can configure a standard shipping method or you can create your own, which we will do in this article.

Initializing module configurations

In this recipe, we will create the necessary files for a shipping module, which we will extend with more features using the recipes of this article.

Getting ready

Open your code editor with the Magento project. Also, get access to the backend where we will check some things.

How to do it...

The following steps describe how we can create the configuration for a shipping module:

  1. Create the following folders:

    • app/code/local/Packt/
    • app/code/local/Packt/Shipme/
    • app/code/local/Packt/Shipme/etc/
    • app/code/local/Packt/Shipme/Model/
    • app/code/local/Packt/Shipme/Model/Carrier
  2. Create the module file named Packt_Shipme.xml in the folder app/etc/modules with the following content:

    <?xml version="1.0"?> <config> <modules> <Packt_Shipme> <active>true</active> <codePool>local</codePool> <depends> <Mage_Shipping /> </depends> </Packt_Shipme> </modules> </config>

  3. Create a config.xml file in the folder app/code/local/Packt/Shipme/etc/ with the following content:

    <?xml version="1.0" encoding="UTF-8"?> <config> <modules> <Packt_Shipme> <version>0.0.1</version> </Packt_Shipme> </modules> <global> <models> <shipme> <class>Packt_Shipme_Model</class> </shipme> </models> </global> <default> <carriers> <shipme> <active>1</active> <model>shipme/carrier_shipme</model> <title>Shipme shipping</title> <express_enabled>1</express_enabled> <express_title>Express delivery</express_title> <express_price>4</express_price> <business_enabled>1</business_enabled> <business_title>Business delivery</business_title> <business_price>5</business_price> </shipme> </carriers> </default> </config>

  4. Clear the cache and navigate in the backend to System | Configuration | Advanced Disable Modules Output. Observe that the Packt_Shipme module is on the list.

  5. At this point, the module is initialized and working. Now, we have to create a system.xml file where we will put the configuration parameters for our shipping module. Create the file app/code/local/Packt/Shipme/etc/system.xml.
  6. In this file, we will create the configuration parameters for our shipping module. When you paste the following code in the file, you will create an extra group in the shipping method's configuration. In this group, we can set the settings for the new shipping method:

    <?xml version="1.0" encoding="UTF-8"?> <config> <sections> <carriers> <groups> <shipme translate="label" module="shipping"> <label>Shipme</label> <sort_order>15</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> <fields> <!-- Define configuration fields below --> <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>1</show_in_website> <show_in_store>1</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>1</show_in_website> <show_in_store>1</show_in_store> </title> </fields> </shipme> </groups> </carriers> </sections> </config>

  7. Clear the cache and navigate in the backend to the shipping method configuration page. To do that, navigate to System | Configuration | Sales | Shipping methods. You will see that an extra group is added as shown in the following screenshot:

  8. You will see that there is a new shipping method called Shipme. We will extend this configuration with some values. Add the following code under the <fields> tag of the module:

    <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>1</show_in_website> <show_in_store>1</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>1</show_in_website> <show_in_store>1</show_in_store> </title> <express_enabled translate="label"> <label>Enable express</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_ model> <sort_order>30</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </express_enabled> <express_title translate="label"> <label>Title express</label> <frontend_type>text</frontend_type> <sort_order>40</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </express_title> <express_price translate="label"> <label>Price express</label> <frontend_type>text</frontend_type> <sort_order>50</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </express_price> <business_enabled translate="label"> <label>Enable business</label> <frontend_type>select</frontend_type> <source_model>adminhtml/system_config_source_yesno</source_ model> <sort_order>60</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </business_enabled> <business_title translate="label"> <label>Title business</label> <frontend_type>text</frontend_type> <sort_order>70</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </business_title> <business_price translate="label"> <label>Price business</label> <frontend_type>text</frontend_type> <sort_order>80</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </business_price>

  9. Clear the cache and reload the backend. You will now see the other configurations under the Shipme – Express shipping method as shown in the following screenshot:

How it works...

The first thing we have done is to create the necessary files to initialize the module. The following files are required to initialize a module:

app/etc/modules/Packt_Shipme.xml app/code/local/Packt/Shipme/etc/config.xml

In the first file, we will activate the module with the <active> tag. The <codePool> tag describes that the module is located in the local code pool, which represents the folder app/code/local/.

In this file, there is also the <depends> tag. First this will check if the Mage_Shipping module is installed or not. If not, Magento will throw an exception. If the module is available, the dependency will load this module after the Mage_Shipping module. This makes it possible to rewrite some values from the Mage_Shipping module.

In the second file, config.xml, we configured all the stuff that we will need in this module.

These are the following things:

  • The version number (0.0.1)
  • The models
  • Some default values for the configuration values

The last thing we did was create a system.xml file so that we can create a custom configuration for the shipping module.

The configuration in the system.xml file adds some extra values to the shipping method configuration, which is available in the backend under the menu System | Configuration | Sales | Shipping methods.

In this module, we created a new shipping handler called Shipme. Within this handler, you can configure two shipping options: express and business. In the system.xml file, we created the fields to configure the visibility, name, and price of the options.

See also

In this recipe, we used the system.xml file of the module to create the configuration values.

Writing an adapter model

A new shipping module is initialized in the previous recipe. What we did in the previous recipe was a preparation to continue with the business part we will see in this recipe. We will add a model with the business logic for the shipping method. The model is called an adapter class because Magento requires an adapter class for each shipping method. This class will extend the Mage_Shipping_Model_Carrier_Abstract class.

This class will be used for the following things:

  • Make the shipping method available
  • Calculate the shipping costs
  • Set the title in the frontend of the shipping methods

How to do it...

Perform the following steps to create the adapter class for the shipping method:

  1. Create the folder app/code/local/Packt/Shipme/Model/Carrier if it doesn't already exist.
  2. In this folder, create a file named Shipme.php and add the following content to it:

    <?php class Packt_Shipme_Model_Carrier_Shipme extends Mage_Shipping_Model_Carrier_Abstract implements Mage_Shipping_Model_Carrier_Interface { protected $_code = 'shipme'; public function collectRates (Mage_Shipping_Model_Rate_Request $request) { $result = Mage::getModel('shipping/rate_result'); //Check if express method is enabled if ($this->getConfigData('express_enabled')) { $method = Mage::getModel ('shipping/rate_result_method'); $method->setCarrier($this->_code); $method->setCarrierTitle ($this->getConfigData('title')); $method->setMethod('express'); $method->setMethodTitle ($this->getConfigData('express_title')); $method->setCost ($this->getConfigData('express_price')); $method->setPrice ($this->getConfigData('express_price')); $result->append($method); } //Check if business method is enabled if ($this->getConfigData('business_enabled')) { $method = Mage::getModel ('shipping/rate_result_method'); $method->setCarrier($this->_code); $method->setCarrierTitle ($this->getConfigData('title')); $method->setMethod('business'); $method->setMethodTitle ($this->getConfigData('business_title')); $method->setCost ($this->getConfigData('business_price')); $method->setPrice ($this->getConfigData('business_price')); $result->append($method); } return $result; } public function isActive() { $active = $this->getConfigData('active'); return $active==1 || $active=='true'; } public function getAllowedMethods() { return array('shipme'=>$this->getConfigData('name')); } }

  3. Save the file and clear the cache; your adapter model has now created.

How it works...

The previously created class handles all the business logic that is needed for the shipping method. Because this adapter class is an extension of the Mage_Shipping_Model_Carrier_Abstract class, we can overwrite some methods to customize the business logic of the standard.

The first method we overwrite is the isAvailable() function. In this function, we have to return true or false to say that the module is active. In our code, we will activate the module based on the system configuration field active.

The second method is the collectRates() function. This function is used to set the right parameters for every shipping method. For every shipping method, we can set the title and price.

The class implements the interface Mage_Shipping_Model_Carrier_Interface.

In this interface, two functions are declared: the isTrackingAvailable() and getAllowedMethods() functions.

We created the function getAllowedMethods() in the adapter class. The isTrackingAvailable() function is declared in the parent class Mage_Shipping_Model_Carrier_Abstract.

We configured two options under the Shipme shipping method. These options are called Express delivery and Business delivery. We will check if they are enabled in the configuration and set the configured title and price for each option.

The last thing to do is return the right values. We have to return an instance of the class Mage_Shipping_Model_Rate_Result. We created an empty instance of the class, where we will append the methods to when they are available.

To add a method, we have to use the function append($method). This function requires an instance of the class Mage_Shipping_Model_Rate_Result_Method that we created in the two if statements.

Extending the shipping method features

When all the files are installed, we can add more features to the shipping method. In this recipe, we will add a country configuration and we will enable tracking codes for the shipping method.

How to do it...

Perform the following steps to tracking codes and country-specific shipping:

  1. Open the adapter file app/code/local/Packt/Shipme/Model/Carrier/Shipme.php.
  2. Add the following function in this file to enable tracking codes:

    public function isTrackingAvailable() { return true; }

    Tracking codes are now enabled for the Shipme shipping methods.

  3. To enable country-specific shipping, we have to add some configuration fields in the system.xml file of the module. Add the following code as the child of the <fields> tag:

    <sallowspecific translate="label"> <label>Ship to Applicable Countries</label> <frontend_type>select</frontend_type> <sort_order>90</sort_order> <frontend_class>shipping-applicable-country</frontend_class> <source_model>adminhtml/system_config_source_shipping _allspecificcountries</source_model> <show_in_default>1</show_in_default> <show_in_website>1</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>100</sort_order> <source_model>adminhtml/system_config_source_country </source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> <can_be_empty>1</can_be_empty> </specificcountry>

  4. Clear the cache and open the configuration page of the shipping method. You will see that there are two new configuration options. When you change Ship to Applicable Countries to Specific Countries, you can select multiple countries as seen in the following screenshot:

How it works...

The first thing we did was enable the possibility to create tracking codes for the Shipme shipping method. We overwrote the isTrackingAvailable() function, which returns the standard false. By returning true, we enable the tracking codes.

The second thing we did was enable country-specific shipping. We configured two fields with a standard naming convention. When we enable the configuration in the backend, we can only use the shipping method when the shipping address is in one of the selected countries.

Adding the module in the frontend

In this recipe, we will test that the shipping method appears in the frontend. We prepared the code and configuration in the previous recipes to make this possible.

How to do it...

In this recipe, we will check the configuration and place a test order with the new shipping method:

  1. Log in to the admin panel.
  2. Navigate to the shipping methods page by going to System | Configuration | Sales | Shipping methods.
  3. Check that all the values are correct for the Shipme – Express method. Also make sure it is enabled.
  4. Save the configuration.
  5. Go to the frontend, add a product to the shopping cart, and checkout.
  6. Fill in the right data for the billing and shipping steps.
  7. In the shipping method step, new methods will appear as shown in the following screenshot:

  8. Select a method from the list and click on the Continue button.
  9. In the payment method step, choose the Check Money Order method.

    If you don't see the Check Money Order payment method, you have to enable it in the system configuration.

  10. Click Continue and place the order. You will see the success page.
  11. In the backend, go to Sales | Orders and click on the latest order.
  12. To complete the order, we have to create an invoice for it to confirm that the order is paid. When you click on the Invoice button, you will be redirected to the invoice form where you can submit your invoice.
  13. When the invoice is saved, you will see that the status of the order has changed to Processing. When the status is Processing, you can click on the Ship button to create the shipment. You will see the following screen:

  14. When you click on the Add Tracking Number button, choose the Shipme shipping option from the drop-down and add a tracking code such as 1234567890:

  15. When you click on the Submit Shipment button, your shipment is processed and the status of the order will change to Complete.

How it works...

In this recipe, we tested the shipping method that we created in this article. We placed an order with the new shipping method to check that everything works the way we wanted it to.


This article shows you how to create a custom module with the configurations required for a new shipping method.

Resources for Article:

Further resources on this subject:

You've been reading an excerpt of:

Magento 1.8 Development Cookbook

Explore Title