This blog contains full steps with example code snippets to create a custom shipping carrier on Magento 2 stores. By default, Magento supports a few shipping carriers. However, when you want to integrate with other 3rd parties logistics, you need to create a new shipping carrier.
With this simple guide, you can follow step by step to create a new shipping carrier in Magento 2
Step 1: Create a new module
In this blog, we are going to create a new shipping carrier: Magenest_CustomShipping
. First of all, we need at least 2 files registration.php and module.xml.
Registration.php
<?php use Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register( ComponentRegistrar::MODULE, 'Magenest_CustomShipping', __DIR__ );
Module.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Magenest_CustomShipping" > <sequence> <module name="Magento_Store"/> <module name="Magento_Sales"/> <module name="Magento_Quote"/> <module name="Magento_SalesRule"/> </sequence> </module> </config>
Step 2: Create the configuration
File system.xml: The system.xml source code declares 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
<?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="900" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Magenest Custom Shipping Module</label> <field id="active" translate="label" type="select" sortOrder="10" 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="20" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Title</label> </field> <field id="name" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Method Name</label> </field> <field id="shipping_cost" translate="label" type="text" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="0" > <label>Shipping Cost</label> <validate>validate-number validate-zero-or-greater</validate> </field> <field id="sallowspecific" translate="label" type="select" sortOrder="60" 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="70" 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="80" 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="sort_order" translate="label" type="text" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Sort Order</label> </field> </group> </section> </system> </config>
File config.xml: File specifies default values for custom shipping module options and the shipping module model.
<?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>0</active> <title>Magenest Shipping Title</title> <name>Magenest Shipping Method Name</name> <shipping_cost>10</shipping_cost> <sallowspecific>0</sallowspecific> <sort_order>15</sort_order> <model>Magenest\CustomShipping\Model\Carrier\Customshipping</model> </customshipping> </carriers> </default> </config>
Step 3: Create the carrier model
app/code/Magenest/CustomShipping/Model/Carrier/Customshipping.php
<?php namespace Magenest\CustomShipping\Model\Carrier; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Shipping\Model\Carrier\AbstractCarrier; use Magento\Shipping\Model\Carrier\CarrierInterface; /** * Custom shipping model */ class Customshipping extends AbstractCarrier implements CarrierInterface { /** * @var string */ protected $_code = 'customshipping'; /** * @var bool */ protected $_isFixed = true; /** * @var \Magento\Shipping\Model\Rate\ResultFactory */ private $rateResultFactory; /** * @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory */ private $rateMethodFactory; /** * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory * @param array $data */ 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 = [] ) { parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data); $this->rateResultFactory = $rateResultFactory; $this->rateMethodFactory = $rateMethodFactory; } /** * Custom Shipping Rates Collector * * @param RateRequest $request * @return \Magento\Shipping\Model\Rate\Result|bool */ 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')); $shippingCost = (float)$this->getConfigData('shipping_cost'); $method->setPrice($shippingCost); $method->setCost($shippingCost); $result->append($method); return $result; } /** * @return array */ public function getAllowedMethods() { return [$this->_code => $this->getConfigData('name')]; } }
Step 4: Enable the module
Run this command to activate the new module:
Php bin/magento setup:upgrade
The new shipping carrier will appear on the checkout page:
READ MORE. How to set up free shipping in Magento - Magenest Blog
With these 4 steps, we hope you can create a new shipping carrier in Magento 2 successfully. Thank you for reading!