In this article I will demonstrate how to write custom shipping method in Magento commerce.
First we need to write our shipping method, it’s a class in folder app/code/core/Mage/Shipping/Model/Carrier/.
I called it Inchoocustom.php and it’s based on Flat rate shipping method but you can developed your own class.
< ?php
class Mage_Shipping_Model_Carrier_Inchoocustom
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
protected $_code = 'inchoocustom';
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$freeBoxes = 0;
if ($request->getAllItems()) {
foreach ($request->getAllItems() as $item) {
if ($item->getFreeShipping() && !$item->getProduct()->isVirtual()) {
$freeBoxes+=$item->getQty();
}
}
}
$this->setFreeBoxes($freeBoxes);
$result = Mage::getModel('shipping/rate_result');
if ($this->getConfigData('type') == 'O') { // per order
$shippingPrice = $this->getConfigData('price');
} elseif ($this->getConfigData('type') == 'I') { // per item
$shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price'));
} else {
$shippingPrice = false;
}
$shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice);
if ($shippingPrice !== false) {
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('inchoocustom');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('inchoocustom');
$method->setMethodTitle($this->getConfigData('name'));
if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) {
$shippingPrice = '0.00';
}
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
$result->append($method);
}
return $result;
}
public function getAllowedMethods()
{
return array('inchoocustom'=>$this->getConfigData('name'));
}
}
Pay attention on following lines:
$method->setCarrier('inchoocustom');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('inchoocustom');
$method->setMethodTitle($this->getConfigData('name'));
They determine how we will set up our method. Keyword is ‘inchoocustom’.
In folder app/code/core/Mage/Shipping/etc/ we need to edit
system.xml and config.xml in order to enable our new shipping method.
system.xml:
<inchoocustom translate="label">
<label>Inchoo Custom Shipping Method</label>
<frontend_type>text</frontend_type>
<sort_order>2</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</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>1</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</active>
<name translate="label">
<label>Method name</label>
<frontend_type>text</frontend_type>
<sort_order>3</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</name>
<price translate="label">
<label>Price</label>
<frontend_type>text</frontend_type>
<sort_order>5</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</price>
<handling_type translate="label">
<label>Calculate Handling Fee</label>
<frontend_type>select</frontend_type>
<source_model>shipping/source_handlingType</source_model>
<sort_order>7</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</handling_type>
<handling_fee translate="label">
<label>Handling Fee</label>
<frontend_type>text</frontend_type>
<sort_order>8</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</handling_fee>
<sort_order translate="label">
<label>Sort order</label>
<frontend_type>text</frontend_type>
</sort_order><sort_order>100</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
<title translate="label">
<label>Title</label>
<frontend_type>text</frontend_type>
<sort_order>2</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>1</show_in_store>
</title>
<type translate="label">
<label>Type</label>
<frontend_type>select</frontend_type>
<source_model>adminhtml/system_config_source_shipping_flatrate</source_model>
<sort_order>4</sort_order>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</type>
<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>91</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>
</specificcountry>
<showmethod translate="label">
<label>Show method if not applicable</label>
<frontend_type>select</frontend_type>
<sort_order>92</sort_order>
<source_model>adminhtml/system_config_source_yesno</source_model>
<show_in_default>1</show_in_default>
<show_in_website>1</show_in_website>
<show_in_store>0</show_in_store>
</showmethod>
<specificerrmsg translate="label">
<label>Displayed Error Message</label>
<frontend_type>textarea</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>
</specificerrmsg>
</fields>
</inchoocustom>
config.xml:
<inchoocustom>
<active>0</active>
<sallowspecific>0</sallowspecific>
<model>shipping/carrier_inchoocustom</model>
<name>Inchoo Custom Shipping Method</name>
<price>5.00</price>
<title>Inchoo Custom Shipping Method</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>
</inchoocustom>
Now we need to enable our new shipping method in admin panel (System->Configuration->Shipping Methods)
And we have our custom shipping method.
Enjoy coding.



Can this be made into a local module so as to not get overridden during upgrades?
I keep getting an error on this
@Tobeyt23
Not much info provided on your side!
What is the error you are getting? Check the SmallCaps cases in config.xmlf files. Our color syntax app has the tendency to lowercase attribute names in XML files so you might be getting some config errors?
@Tobeyt23
“Can this be made into a local module so as to not get overridden during upgrades?” => Yes it can.
@Branko Ajzele
I found the error:
Sort order
text
100
1
1
0
should be:
Sort order
text
100
1
1
0
@Tobeyt23 Vedran is the author of this post
I guess this one goes to him.
@ Branko Ajzele
Woops didn’t see that the code got messed up. In the system.xml on line 54 the sortorder is closed before it should be once I fixed that it worked.
Well done Tobeyt23,
ceep tracing Magento code!!
It does not work in the newest version of Magento … it is visible in System->Configuration->Shipping Methods, but if it is active shopping chart drops errors, and the checkout does not let to pass to shipping methods. or did I missed something in
Pay attention on following lines:
1. $method->setCarrier(‘inchoocustom’);
2.$method->setCarrierTitle($this->getConfigData(‘title’));
3.
4.$method->setMethod(‘inchoocustom’);
5.$method->setMethodTitle($this->getConfigData(‘name’));
gimme more info to what should I pay attention to
thanx best wishes
Jozef
@Jozef
I’m sorry, I should highlight that the code above is tested in Magento version 1.3.2.1.
But if you followed the instructions (not just copy-paste) and tried to make your own shipping method with new magento version I belive that you would achieve your goal.
Hi, you have shown how to add shipping module in Core/Mage. Is there any way I can add shipping module in Local/
try this one, hopefully working.
Inchoo Custom Shipping Method
text
5
1
1
1
Enabled
select
adminhtml/system_config_source_yesno
1
1
1
0
Method name
text
3
1
1
1
Price
text
5
1
1
0
Calculate Handling Fee
select
shipping/source_handlingType
7
1
1
0
Handling Fee
text
8
1
1
0
Sort order
text
100
1
1
0
Title
text
2
1
1
1
Type
select
adminhtml/system_config_source_shipping_flatrate
4
1
1
0
Ship to applicable countries
select
90
shipping-applicable-country
adminhtml/system_config_source_shipping_allspecificcountries
1
1
0
Ship to Specific countries
multiselect
91
adminhtml/system_config_source_country
1
1
0
Show method if not applicable
select
92
adminhtml/system_config_source_yesno
1
1
0
Displayed Error Message
textarea
80
1
1
1
I found the error:
Sort order
text
100
1
1
0
should be:
Sort order
text
100
1
1
0
i found error:
052. Sort order
053. text
054. 100
055. 1
056. 1
057. 0
should be:
052. Sort order
053. text
054. 100
055. 1
056. 1
057. 0
058.
i found error at line 054
Can you offer opensource EMS shipment model?
Great! Our store is based in one currency and displays in another ($). That works fine. The problem is with shipping. You see we want to have a flat fixed shipping rate in $ – but it gets converted from our base currency. Any ideas?
Thanks
Hey please correct the section
Sort order
text
100
1
1
0
Instead of blindly copy paste this in system.xml:
Sort order
text
100
1
1
0
Error was in line: 54
Xml tag wasn’t properly closed.
Please check the link provided:
fixed solution
Point was that You spend some time to trace the error so you can get that feeling how is like to be Magento developer.
Great tutorial! You should be namespacing this code into /local, especially if it is a tutorial, and you are telling others best practices in Magento programming.
How can I add a minimum shipping amount to the flat rate %. For example:
I want to charge $6.50 or 8% depending on which is greater.
Thanks!
Hello… I have made it local, but I saw thay the model class is never called. the system insists in calle Mage_Shipping model class.
My module is called Newshipping, and the carrier is regionfreeshipping. Can you show me how to configure system.xml and config.xml files?
Thanks
Jaime
HI,
I tried to make the following fields dynamic so that it’s data come from some table.
for example
foreach($multiple_methods as $method){ ... $method->setMethod($method['code']); $method->setMethodTitle($method[''name]); .. }But in the frontend i get the methods but with ‘US’ title and all divs ids were same.
Can anybody has some idea
Pay attention on shipping/carrier_inchoocustom without correct model you we unable to see custom shipping in the frontend list
While this module works quite fine.. when I go to Sales>Orders and click on Invoice, it throws up an error.
Do you have any fix for that?
Using Magento 1.1.4
Hello,
Due to the errors being thrown up, I disabled your module (meaning: retraced the methods you mentioned to install this module)
But now when I click on Sales>orders>view and click on Invoice or Ship, I get the error message: Invalid model for shipping method: inchoocustom
How do i fix this?
Sorry for the spam… but it’s kind of frustrating.. When I do use the module, then when creating promotions and New Rule action is set to Shipping Method, it throws up a bunch of errors again.
getConfigFlag('active')) { return false; } $freeBoxes = 0; if ($request->getAllItems()) { foreach ($request->getAllItems() as $item) { if ($item->getFreeShipping() && !$item->getProduct()->isVirtual()) { $freeBoxes+=$item->getQty(); } } } $this->setFreeBoxes($freeBoxes); $result = Mage::getModel('shipping/rate_result'); if ($this->getConfigData('type') == 'O') { // per order $shippingPrice = $this->getConfigData('price'); } elseif ($this->getConfigData('type') == 'I') { // per item $shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price')); } else { $shippingPrice = false; } $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice); if ($shippingPrice !== false) { $method = Mage::getModel('shipping/rate_result_method'); $method->setCarrier('inchoocustom'); $method->setCarrierTitle($this->getConfigData('title')); $method->setMethod('inchoocustom'); $method->setMethodTitle($this->getConfigData('name')); if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) { $shippingPrice = '0.00'; } $method->setPrice($shippingPrice); $method->setCost($shippingPrice); $result->append($method); } return $result; } public function getAllowedMethods() { return array('inchoocustom'=>$this->getConfigData('name')); } } Fatal error: Call to a member function setId() on a non-object in /public_html/app/code/core/Mage/Shipping/Model/Config.php on line 118Hi,
It’s me again (for the last time). I figured out the errors.. even after disabling this module, when clicking on invoices, the error throws up. This is because of the path in core_config_data
Each of the records have to be deleted and it works fine.
Perhaps you might want to mention this and others might find it useful.
@John
This example is more than 1 year old.
Install new Magento, follow step by step and code it from scratch.
Thanks for reply
I can get the above to work on Magento 1.5 but when I try to create a shopping cart price rule using something like if shipping method is Custom Method, it just throws me back to the dashboard
I assume we need to add the custom method to the database or mage somewhere else in the program?
Any thoughts?
Its work fine for me but i want to know is it proper way to use, what if a new version of magento comes and somebody runs upgrade over system everything will be vanished then, is it possible to override this system.xml and config.xml, i can override shipping model but confused with the xml files.
i had use this code it is correct and complete thanks for that.but now i want to need shipping charge based on total which is manage from admin.shipping charge will be 2% of total and if total>400 then shipping charge will be free so please help me for that i m new in magento.
thanks in advance.
informations in this site are very very useful for everyone in the world.
My suggestion is to please change coding background color in your site. because now it very dark.
site take some high loading time. reduce it if possible.
informations in this site are very valuable.
how may i add region in shipping method?
http://stackoverflow.com/questions/6355409/magento-get-region-list-for-country-in-admin-shipping-module
i flow this ling but it is not working when i select country and then region what can i do?
Hello
i have to develop a new shipping method for MaltaPost in magento. Please let me know whether it is possible
I need some example to make shipping module in Magento 1.5, anybody can help me?
Thanks.
can I set up multiple prices for rates
ex
10.00
5.00
15.00
?
in the config.xml
Thanx, very nice and almost working example(using magento 1.5.1).
You have forgotten to end the
tag:
<sort_order translate="label"> <label>Sort Order</label> <frontend_type>text</frontend_type> <sort_order>100</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> </sort_order> <- This is missing in the above code, but easy to spot and fix.Besides that it works great and shows up in the store as well.
DO NOTE!! You can not use special chars like åäö in the xml. Use the html equivalent instead. If you do use it the admin page will not display any of the shipping modules instead.
EDIT:
The code example is a complete working version, I just noticed that the original code did include the end tag but that it is placed wrong.
Please John, you said “This is because of the path in core_config_data. Each of the records have to be deleted and it works fine” I would be very grateful you tell what you realy mean because i am having the problem. In this core_config_data table, there are many paths, which one do i delete? Please please, i need your help. Keep all good work alive.
Hey man, is there a way I could use this tutorial to create a shipping mode that applies only to certain categories of products?
This works fine in Magento CE 1.5 except that after a customer has used the method I created there is no reorder button on the customers dashboard under that specific order, all other shipping methods allow for reorder.
Only thing I did different from the tutorial is that I based my shipping method on the Free Shipping default method included in Magento.
Anyone else have this issue or know why and how to fix it?
Cheers,
Chris
Hi I followed your example but i get this error.
getConfigFlag(‘active’)) { return false; } $freeBoxes = 0; if ($request->getAllItems()) { foreach ($request->getAllItems() as $item) { if ($item->getFreeShipping() && !$item->getProduct()->isVirtual()) { $freeBoxes+=$item->getQty(); } } } $this->setFreeBoxes($freeBoxes); $result = Mage::getModel(‘shipping/rate_result’); if ($this->getConfigData(‘type’) == ‘O’) { // per order $shippingPrice = $this->getConfigData(‘price’); } elseif ($this->getConfigData(‘type’) == ‘I’) { // per item $shippingPrice = ($request->getPackageQty() * $this->getConfigData(‘price’)) – ($this->getFreeBoxes() * $this->getConfigData(‘price’)); } else { $shippingPrice = false; } $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice); if ($shippingPrice !== false) { $method = Mage::getModel(‘shipping/rate_result_method’); $method->setCarrier(‘G4S’); $method->setCarrierTitle($this->getConfigData(‘title’)); $method->setMethod(‘G4S’); $method->setMethodTitle($this->getConfigData(‘name’)); if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) { $shippingPrice = ’0.00′; } $method->setPrice($shippingPrice); $method->setCost($shippingPrice); $result->append($method); } return $result; } public function getAllowedMethods() { return array(‘G4S’=>$this->getConfigData(‘name’)); } }
Fatal error: Call to a member function setStore() on a non-object in /home/covertas/public_html/supa/magento/app/code/core/Mage/Shipping/Model/Shipping.php on line 247
any help?
I am trying to create this, in magento 1.6.1 using LOCAL folder, and it never appears …
does anybody knows why? maybe magento is not checking my system.xml file?
Is there any way to apply a specific shipping costs for each category?
This is great! But I’m also wondering how to add my custom parcel tracking to this.
Can you demonstrate a simple case?
When the shipment is booked, the tracking URL should end up in the email to the customer.
when we apply the above code then the shipping method and shipping price are not see in admin->config. why