generate system setting
app/code/Firstflight/Firstship/etc/adminhtml/system.xml
<?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="firstship" translate="label" type="text" sortOrder="900" showInDefault="1" showInWebsite="1" showInStore="1">
<label>First flight</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="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Title</label>
</field>
<field id="name" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Method Name</label>
</field>
<field id="account_no" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Account number</label>
</field>
<field id="live_api_username" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Live API username</label>
</field>
<field id="live_api_password" translate="label" type="obscure" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Live API password</label>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
</field>
<field id="sendbox_mode" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sendbox mode</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<frontend_class>is-sendbox-mode</frontend_class>
</field>
<field id="sendbox_api_username" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sendbox API username</label>
<depends>
<field id="sendbox_mode">1</field>
</depends>
</field>
<field id="sendbox_api_password" translate="label" type="obscure" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sendbox API password</label>
<backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model>
<depends>
<field id="sendbox_mode">1</field>
</depends>
</field>
<field id="sallowspecific" translate="label" type="select" sortOrder="10" 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="select" sortOrder="10" 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="10" 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="service_type" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Service type</label>
<source_model>Firstflight\Firstship\Model\Config\Source\ServiceType</source_model>
<frontend_class>service-type</frontend_class>
</field>
<field id="shipping_type" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Shipping type</label>
<source_model>Firstflight\Firstship\Model\Config\Source\ShippingType</source_model>
<frontend_class>shipping-type</frontend_class>
</field>
<field id="sort_order" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sort Order</label>
</field>
</group>
</section>
</system>
</config>
app/code/Firstflight/Firstship/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>
<firstship>
<active>0</active>
<title>First Flight</title>
<name>First Flight Shipping</name>
<sallowspecific>0</sallowspecific>
<sort_order>15</sort_order>
<sendbox_api_password backend_model="Magento\Config\Model\Config\Backend\Encrypted" />
<live_api_password backend_model="Magento\Config\Model\Config\Backend\Encrypted" />
<model>Firstflight\Firstship\Model\Carrier</model>
</firstship>
</carriers>
</default>
</config>
Carrier code
app/code/Firstflight/Firstship/Model/Carrier.php
<?php
namespace Firstflight\Firstship\Model;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
/**
* Custom shipping model
*/
class Carrier extends AbstractCarrier implements CarrierInterface
{
/** @var string */
protected $_methodCode = 'firstflight';
/** @var string */
protected $_carrierCode = 'firstship';
/** @var string */
protected $_code = 'firstship';
/** @var bool */
protected $_isFixed = true;
/** @var \Magento\Shipping\Model\Rate\ResultFactory */
private $rateResultFactory;
/** @var \Magento\Framework\UrlInterface */
private $urlBuilder;
/** @var \Magento\Framework\Url\EncoderInterface */
protected $urlEncoder;
/** @var \Firstflight\Firstship\Helper\Data */
private $dataHelper;
/** @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory */
private $rateMethodFactory;
/**
* construct
*
* @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 \Firstflight\Firstship\Helper\Data $dataHelper
* @param \Magento\Framework\Url\EncoderInterface $urlEncoder
* @param \Magento\Framework\UrlInterface $urlBuilder
* @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,
\Firstflight\Firstship\Helper\Data $dataHelper,
\Magento\Framework\Url\EncoderInterface $urlEncoder,
\Magento\Framework\UrlInterface $urlBuilder,
array $data = []
) {
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
$this->rateResultFactory = $rateResultFactory;
$this->rateMethodFactory = $rateMethodFactory;
$this->dataHelper = $dataHelper;
$this->urlEncoder = $urlEncoder;
$this->urlBuilder = $urlBuilder;
}
/**
* 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->_carrierCode);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($this->_methodCode);
$method->setMethodTitle($this->getConfigData('name'));
$data = [
'dest_country_id' => $request->getDestCountryId(),
'package_weight' => $request->getPackageWeight(),
'country_id' => $request->getCountryId()
];
$rate = $this->dataHelper->getRateFinder($data);
$shippingCost = (float)$rate['NetAmount'];
$method->setPrice($shippingCost);
$method->setCost($shippingCost);
$result->append($method);
return $result;
}
/**
* @return array
*/
public function getAllowedMethods()
{
return [$this->_methodCode => $this->getConfigData('name')];
}
/**
* get tracking info object
*
* @param int $trackingNumber
* @return \Magento\Framework\DataObject
*/
public function getTrackingInfo($trackingNumber)
{
$tracking = new \Magento\Framework\DataObject();
$tracking->setData([
'carrier' => $this->_code,
'carrier_title' => $this->getConfigData('title'),
'tracking' => $trackingNumber,
'url' => $this->_getTrackingUrl($trackingNumber)
]);
return $tracking;
}
/**
* get tracking url
*
* @param string $trackingNumber
* @return string
*/
protected function _getTrackingUrl($trackingNumber)
{
$params = [
'_nosid' => true,
'_direct' => 'firstflight/tracking/info',
'_query' => ['hash' => $this->urlEncoder->encode($trackingNumber)]
];
return $this->urlBuilder->getUrl('', $params);
}
}
Thanks.