Como: Crear un Shipping Method en Magento 2
En esta página
Hace un tiempo necesitaba un método de envío personalizado con una tarifa que dependía de algunas de nuestras propias reglas de negocio. El flat rate nativo no era lo suficientemente flexible, así que construí un pequeño carrier personalizado. Es una de esas tareas que da miedo la primera vez pero que en realidad queda muy ordenada una vez que conoces las tres piezas involucradas.
app/code/Vendor/Shipping. Si necesitas saber cómo crear un nuevo módulo, te recomiendo que le eches un vistazo a Cómo crear un nuevo módulo para Magento 2.La configuración
Los valores por defecto viven en el config.xml. El nodo model es el que ata todo a nuestra clase carrier.
<?xml version="1.0"?>
<!-- app/code/Vendor/Shipping/etc/config.xml -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<carriers>
<vendorcustom>
<active>1</active>
<model>Vendor\Shipping\Model\Carrier\Custom</model>
<title>My Custom Shipping</title>
<name>Fixed rate</name>
<price>10.00</price>
<sallowspecific>0</sallowspecific>
<specificerrmsg>This shipping method is currently unavailable.</specificerrmsg>
</vendorcustom>
</carriers>
</default>
</config>Y los campos de admin en el system.xml bajo Stores > Configuration > Sales > Shipping Methods.
<?xml version="1.0"?>
<!-- app/code/Vendor/Shipping/etc/adminhtml/system.xml -->
<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">
<group id="vendorcustom" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<label>My Custom Shipping</label>
<field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1">
<label>Enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="price" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1">
<label>Price</label>
</field>
<field id="title" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Title</label>
</field>
</group>
</section>
</system>
</config>El Carrier
Aquí es donde pasa lo interesante. El carrier extiende AbstractCarrier e implementa CarrierInterface. El método
que importa es collectRates(), ahí es donde decides el precio. No olvides getAllowedMethods(), Magento lo
necesita.
<?php
/** app/code/Vendor/Shipping/Model/Carrier/Custom.php */
namespace Vendor\Shipping\Model\Carrier;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Rate\ResultFactory;
class Custom extends AbstractCarrier implements CarrierInterface
{
/**
* @var string
*/
protected $_code = 'vendorcustom';
/**
* @var ResultFactory
*/
private $rateResultFactory;
/**
* @var MethodFactory
*/
private $rateMethodFactory;
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
ResultFactory $rateResultFactory,
MethodFactory $rateMethodFactory,
array $data = []
) {
$this->rateResultFactory = $rateResultFactory;
$this->rateMethodFactory = $rateMethodFactory;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
/**
* @param RateRequest $request
* @return \Magento\Shipping\Model\Rate\Result|bool
*/
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$result = $this->rateResultFactory->create();
$method = $this->rateMethodFactory->create();
$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod($this->_code);
$method->setMethodTitle($this->getConfigData('name'));
$price = (float) $this->getConfigData('price');
$method->setPrice($price);
$method->setCost($price);
$result->append($method);
return $result;
}
/**
* @return array
*/
public function getAllowedMethods()
{
return [$this->_code => $this->getConfigData('name')];
}
}Borra la caché, agrega algo al carrito, y el nuevo método debería aparecer en el estimado del checkout.
Espero que esto ayude.
Si tienes alguna pregunta o conoces una mejor manera de lograr esto, siéntete libre de compartir en los comentarios a continuación.