How to Create Custom Shipping Method in Magento 2
Sometimes our clients want to add custom delivery to their Magento shop. So, in this article, we'll create a custom delivery method in Magento 2. For that, we'll create a custom module to add Custom Shipping Method.
Let's get started!!
To create a custom shipping method module you have to follow the simple step which is listed below.
Before we start, we need to create Devhooks folder as a Namespace at app/code/ and create a Module folder CustomShipping at app/code/Devhooks/ location.
Step 1: Create a module.xml file at app/code/Devhooks/CustomShipping/etc/ and paste the below code.
Note: Don't forgot to replace the Devhooks_CustomShipping with your Namespace and Module Name if it's different.
saveCopyzoom_out_map<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
<module name="Devhooks_CustomShipping" setup_version="1.0.0">
<sequence>
<module name="Magento_Store"/>
<module name="Magento_Sales"/>
<module name="Magento_Quote"/>
<module name="Magento_SalesRule"/>
</sequence>
</module>
</config>
Our module is depends on other modules. So, we've added it's dependencies under <module> tag in module.xml file. Check above code for your reference.
Step 2: Create registration file registration.php at app/code/Devhooks/CustomShipping/ and paste the below code.
saveCopyzoom_out_map<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Devhooks_CustomShipping', __DIR__ );
Step 3: Create a system.xml at app/code/Devhooks/CustomShipping/etc/adminhtml/ and paste the below code to add Custom Shipping Method configurations.
saveCopyzoom_out_map<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="carriers" translate="label" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1">
<group id="customshipping" translate="label" type="text" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Custom Shipping Method</label>
<field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Title</label>
</field>
<field id="name" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Method Name</label>
</field>
<field id="price" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Price</label>
<validate>validate-number validate-zero-or-greater</validate>
</field>
<field id="handling_type" translate="label" type="select" sortOrder="7" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Calculate Handling Fee</label>
<source_model>Magento\Shipping\Model\Source\HandlingType</source_model>
</field>
<field id="handling_fee" translate="label" type="text" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Handling Fee</label>
<validate>validate-number validate-zero-or-greater</validate>
</field>
<field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sort Order</label>
</field>
<field id="sallowspecific" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Ship to Applicable Countries</label>
<frontend_class>shipping-applicable-country</frontend_class>
<source_model>Magento\Shipping\Model\Config\Source\Allspecificcountries</source_model>
</field>
<field id="specificcountry" translate="label" type="multiselect" sortOrder="91" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Ship to Specific Countries</label>
<source_model>Magento\Directory\Model\Config\Source\Country</source_model>
<can_be_empty>1</can_be_empty>
</field>
<field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Show Method if Not Applicable</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<frontend_class>shipping-skip-hide</frontend_class>
</field>
<field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Displayed Error Message</label>
</field>
</group>
</section>
</system>
</config>
In Above code we've declared custom shipping module options
- Enabled
- Title
- Method Name
- Shipping Cost
- Ship to Applicable Countries
- Ship to Specific Countries
- Show Method if Not Applicable
- Sort Order
Now, to set default options we need to create config.xml file.
Step 4: Create a default configuration file config.xml at app/code/Devhooks/CustomShipping/etc/ location and paste the below code.
saveCopyzoom_out_map<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<carriers>
<customshipping>
<active>1</active>
<sallowspecific>0</sallowspecific>
<model>Devhooks\CustomShipping\Model\Carrier\CustomShipping</model>
<name>Custom Shipping Method</name>
<price>10.00</price>
<title>Custom Shipping Method</title>
<specificerrmsg>This shipping method is not available. To use this shipping method, please contact us.</specificerrmsg>
<handling_type>F</handling_type>
</customshipping>
</carriers>
</default>
</config>
You can change above default values as per your need.
Step 5: Create a model file CustomShipping.php at app/code/Devhooks/CustomShipping/Model/Carrier/ location and paste the below code.
saveCopyzoom_out_map<?php
namespace Devhooks\CustomShipping\Model\Carrier;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Rate\Result;
class CustomShipping extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
\Magento\Shipping\Model\Carrier\CarrierInterface
{
protected $_code = 'customshipping';
protected $_rateResultFactory;
protected $_rateMethodFactory;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
array $data = []
) {
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
public function getAllowedMethods()
{
return [$this->_code => $this->getConfigData('name')];
}
private function getShippingPrice()
{
$configPrice = $this->getConfigData('price');
$shippingPrice = $this->getFinalPriceWithHandlingFee($configPrice);
return $shippingPrice;
}
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
/** @var \Magento\Shipping\Model\Rate\Result $result */
$result = $this->_rateResultFactory->create();
/** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
$method = $this->_rateMethodFactory->create();
$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($this->_code);
$method->setMethodTitle($this->getConfigData('name'));
$amount = $this->getShippingPrice();
$method->setPrice($amount);
$method->setCost($amount);
$result->append($method);
return $result;
}
}
Step 6: Open Command line in folder root of magento and run the below commands.
saveCopyzoom_out_mapphp bin/magento setup:upgrade php bin/magento cache:clean
Bingo!! we are done all steps.
Now open admin and go to Stores > Configuration > Sales > Delivery Methods and You will see your Custom Shipping Method like the below screenshot.

You can change the settings as per your need. Now go to frontend, add product to shopping cart and go to checkout. You'll see your Custom Shipping Method like the below screenshot in checkout.

That's it!!
I hope this article helped you to find what you were looking for.
Bookmark it for your future reference. Do comment below if you have any other questions on that.
P.S. Do share this article with your team.
AI-Powered Recommended Articles
How to Create Custom Payment Method in Magento 2
Step-by-step guide to creating a custom payment method in Magento 2 for your e-commerce store.
How To Create a Magento 2 Module
Follow this guide to create a custom Magento 2 module from scratch for extended functionality.
How To Add Custom Field At Checkout Address Form – Magento 2
Learn how to add custom fields to the checkout address form in Magento 2 for enhanced customer data collection.
Magento 2 Create Auto Invoice for the COD Order
Learn how to automatically generate invoices for Cash on Delivery orders in Magento 2.
How to Add Custom Select/MultiSelect Options on Store Configuration in Magento 2
Learn how to add custom select and multiselect options to the store configuration in Magento 2.
How to Create a Custom Console Command in Magento 2
Learn how to create custom console commands in Magento 2 to extend the command line interface for your specific needs.