Creating custom shipping methods in Magento 2 is fairly simple you just have to follow following steps.
Module I’m using have the name space of Gm_Module make sure to replace it with your custom module name.
1-Register Your Module
Make sure to create registration.php and module.xml file in their respective folder.
2-Create System.xml
Custom shipping methods mainly appear in configuration that is why we have to create a system.xml file where we will define our custom shipping method . we will use fedex as our example for our custom shipping method. create system.xml and paste the give code in it.
Magento 2 Create Custom Payment Methods
<?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" sortOrder="1000" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <group id="fedex" sortOrder="10" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>FedEx</label> <field id="active" type="select" sortOrder="10" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="name" type="text" sortOrder="20" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Method Name</label> </field> <field id="price" type="text" sortOrder="30" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Price</label> <validate>validate-number validate-zero-or-greater</validate> </field> <field id="sort_order" type="text" sortOrder="40" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Sort Order</label> </field> <field id="title" type="text" sortOrder="50" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Title</label> </field> <field id="sallowspecific" type="select" sortOrder="60" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <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" type="multiselect" sortOrder="70" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Ship to Specific Countries</label> <can_be_empty>1</can_be_empty> <source_model>Magento\Directory\Model\Config\Source\Country</source_model> </field> <field id="specificerrmsg" type="textarea" sortOrder="80" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Displayed Error Message</label> </field> </group> </section> </system> </config>
3- Create Config.xml
Once you have created system.xml we will create config.xml for our default value i.e if you want to charge custom price or give it a custom name by default.
etc/config.xml
<?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> <fedex> <model>Gm\Module\Model\Carrier\FedEx</model> <active>0</active> <title>FedEx</title> <name>FedEx</name> <price>0.00</price> <specificerrmsg>This shipping method is not available. To use this shipping method, please contact us.</specificerrmsg> <sallowspecific>0</sallowspecific> </fedex> </carriers> </default> </config>
4- Create Carrier File
Next create carrier file that will contain your logic for custom payment method.
Model/Carrier/FedEx.php
<?php
/**
* Copyright © All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);
namespace Gm\Module\Model\Carrier;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Rate\Result;
class FedEx extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements
\Magento\Shipping\Model\Carrier\CarrierInterface
{
protected $_code = 'fedex';
protected $_isFixed = true;
protected $_rateResultFactory;
protected $_rateMethodFactory;
/**
* Constructor
*
* @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 = []
) {
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
/**
* {@inheritdoc}
*/
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$shippingPrice = $this->getConfigData('price');
$result = $this->_rateResultFactory->create();
if ($shippingPrice !== false) {
$method = $this->_rateMethodFactory->create();
$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($this->_code);
$method->setMethodTitle($this->getConfigData('name'));
if ($request->getFreeShipping() === true) {
$shippingPrice = '0.00';
}
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
$result->append($method);
}
return $result;
}
/**
* getAllowedMethods
*
* @return array
*/
public function getAllowedMethods()
{
return [$this->_code => $this->getConfigData('name')];
}
}
Once you have created all the mentioned files make sure to run cache:flush and setup:di:compile commands . after that it will be visible on your shipping methods on checkout page.
