Custom shipping method in Magento
17 Comments 26th JUL 2009 | Posted by Vedran Subotic in Magento

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.


















July 27th, 2009 at 15:23
Can this be made into a local module so as to not get overridden during upgrades?
July 27th, 2009 at 15:53
I keep getting an error on this
July 28th, 2009 at 7:26
@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?
July 28th, 2009 at 7:28
@Tobeyt23
“Can this be made into a local module so as to not get overridden during upgrades?” => Yes it can.
July 28th, 2009 at 14:34
@Branko Ajzele
I found the error:
Sort order
text
100
1
1
0
should be:
Sort order
text
100
1
1
0
July 28th, 2009 at 14:43
@Tobeyt23 Vedran is the author of this post
I guess this one goes to him.
July 28th, 2009 at 15:22
@ 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.
July 28th, 2009 at 23:20
Well done Tobeyt23,
ceep tracing Magento code!!
July 29th, 2009 at 0:25
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
July 29th, 2009 at 23:20
@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.
August 28th, 2009 at 12:28
Hi, you have shown how to add shipping module in Core/Mage. Is there any way I can add shipping module in Local/
November 6th, 2009 at 7:37
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
November 9th, 2009 at 3:12
I found the error:
Sort order
text
100
1
1
0
should be:
Sort order
text
100
1
1
0
November 9th, 2009 at 3:15
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.
November 9th, 2009 at 3:17
i found error at line 054
January 27th, 2010 at 16:53
Can you offer opensource EMS shipment model?
March 7th, 2010 at 15:30
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