Skip to content

Commit

Permalink
Added tutorial on creating a custom shipping carrier (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikolalardev authored Oct 9, 2024
1 parent aebd1b9 commit 513846e
Show file tree
Hide file tree
Showing 2 changed files with 236 additions and 0 deletions.
235 changes: 235 additions & 0 deletions add-custom-shipping-carrier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
# Add custom shipping carrier

[TOC]

Mage-OS allows the creation of custom shipping carriers to handle various shipping methods for

Check failure on line 5 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:5:81 MD013/line-length Line length [Expected: 80; Actual: 94] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
different carriers or logistics providers. A custom shipping carrier can be added by creating a

Check failure on line 6 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:6:81 MD013/line-length Line length [Expected: 80; Actual: 95] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
Mage-OS module and configuring the required fields to handle shipping calculations,
carrier configurations, and frontend integration.

## Module Setup

The first step in adding a custom shipping carrier is creating the necessary directory structure

Check failure on line 12 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:12:81 MD013/line-length Line length [Expected: 80; Actual: 96] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
for the Mage-OS module:

```bash
app/code/MageOS/ShippingCarrier/
├── registration.php
├── composer.json
├── etc
│ ├── module.xml
│ ├── config.xml
│ ├── adminhtml
└── system.xml
├── Model
│ └── Carrier
│ └── CustomCarrier.php
```

Create register module file `app/code/MageOS/ShippingCarrier/registration.php`

```php
<?php
use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Vendor_ShippingCarrier',
__DIR__
);
```

Next, you need to declare your module in `app/code/MageOS/ShippingCarrier/etc/module.xml`:

```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="MageOS_ShippingCarrier"/>
</config>
```

## Shipping Carrier Configuration

In the `config.xml` file, define the shipping carrier's core settings, such as its active state,

Check failure on line 53 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:53:81 MD013/line-length Line length [Expected: 80; Actual: 96] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
title, and allowed countries. Create `app/code/MageOS/ShippingCarrier/etc/config.xml`:

```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Shipping/etc/config.xsd">
<default>
<carriers>
<customcarrier>
<active>1</active>
<title>Custom Shipping Carrier</title>
<name>Custom Shipping Method Name</name>
<shipping_cost>10</shipping_cost>
<sallowspecific>0</sallowspecific>
<sort_order>15</sort_order>
<model>MageOS\ShippingCarrier\Model\Carrier\CustomCarrier</model>
</customcarrier>
</carriers>
</default>
</config>
```

Explanation:

- active: Enables or disables the custom carrier.
- title: The name displayed in the checkout.
- name: Internal name of the carrier.
- model: The path to the custom shipping carrier model.
- shipping_cost: The amount of the handling fee.

## Admin Configuration for Carrier

To allow store administrators to configure the shipping method, we define settings in

Check failure on line 85 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:85:81 MD013/line-length Line length [Expected: 80; Actual: 85] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
`app/code/MageOS/ShippingCarrier/etc/adminhtml/system.xml`:

```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">
<group id="customcarrier" translate="label" type="text" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1">

Check failure on line 94 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:94:81 MD013/line-length Line length [Expected: 80; Actual: 134] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
<label>Custom Shipping Module</label>
<field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">

Check failure on line 96 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:96:81 MD013/line-length Line length [Expected: 80; Actual: 149] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
<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="1" canRestore="1">

Check failure on line 100 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:100:81 MD013/line-length Line length [Expected: 80; Actual: 146] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
<label>Title</label>
</field>
<field id="name" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">

Check failure on line 103 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:103:81 MD013/line-length Line length [Expected: 80; Actual: 145] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
<label>Method Name</label>
</field>
<field id="shipping_cost" translate="label" type="text" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">

Check failure on line 106 in add-custom-shipping-carrier.md

View workflow job for this annotation

GitHub Actions / lint

Line length

add-custom-shipping-carrier.md:106:81 MD013/line-length Line length [Expected: 80; Actual: 154] https://github.com/DavidAnson/markdownlint/blob/v0.31.1/doc/md013.md
<label>Shipping Cost</label>
<validate>validate-number validate-zero-or-greater</validate>
</field>
<field id="sallowspecific" translate="label" type="select" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1" 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="60" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<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="70" showInDefault="1" showInWebsite="1" showInStore="1">
<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="80" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Sort Order</label>
</field>
</group>
</section>
</system>
</config>
```

This configuration allows administrators to enable the carrier, set a title, and configure a handling
fee through the Mage-OS admin panel.

## Shipping Carrier Model

The core logic for the custom shipping carrier is in the CustomCarrier.php model.
This class extends Mage-OS's abstract shipping carrier class and implements the shipping calculation and rates.

```php
<?php
declare(strict_types=1);

namespace MageOS\ShippingCarrier\Model\Carrier;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Quote\Model\Quote\Address\RateResult\Method;
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\Result;
use Magento\Shipping\Model\Rate\ResultFactory;
use Psr\Log\LoggerInterface;

class CustomCarrier extends AbstractCarrier implements CarrierInterface
{
protected $_code = 'customcarrier';

protected $_isFixed = true;

private ResultFactory $rateResultFactory;

private MethodFactory $rateMethodFactory;

public function __construct(
ScopeConfigInterface $scopeConfig,
ErrorFactory $rateErrorFactory,
LoggerInterface $logger,
ResultFactory $rateResultFactory,
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 Method $method */
$method = $this->rateMethodFactory->create();

$method->setCarrier($this->_code);
$method->setCarrierTitle($this->getConfigData('title'));

$method->setMethod($this->_code);
$method->setMethodTitle($this->getConfigData('name'));

$shippingPrice = (float)$this->getConfigData('shipping_cost');
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
$method->setDataUsingMethod('cost', $shippingPrice);

/** @var Result $result */
$result = $this->rateResultFactory->create();
$result->append($method);

return $result;
}

public function getAllowedMethods(): array
{
return [$this->_code => $this->getConfigData('name')];
}
}
```

Explanation:

- collectRates(): Calculates shipping rates based on the quote request and returns them.
Here, a fixed rate of 10.00 is used.
- getAllowedMethods(): Returns the allowed shipping methods for this carrier.

## Frontend Integration

Once the backend logic is in place, the custom shipping carrier will automatically appear in the Mage-OS checkout
if it's enabled and configured properly. The title and price will be displayed as defined in the carrier configuration.

## Conclusion
This guide walks through the basic setup of a custom shipping carrier in Mage-OS. The carrier integrates with Mage-OS’s shipping framework, allowing you to customize the shipping calculation and display it during the checkout process. You can extend this basic structure to integrate with third-party APIs, offer dynamic shipping rates, or introduce more complex shipping logic based on cart contents or customer information.
1 change: 1 addition & 0 deletions documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
- ## Tutorials & Examples
- [Collection of real-world examples, and step-by-step tutorials](/docs/{{version}}/collection-of-real-world-examples-and-step-by-step-tutorials)
- [Case studies of problem-solving in Magento 2](/docs/{{version}}/case-studies-of-problem-solving-in-magento-2)
- [Add custom shipping carrier](/docs/{{version}}/add-custom-shipping-carrier)
- ## Community & Support
- [Get help and support](/docs/{{version}}/how-to-get-help-and-support)
- [Community Contribution](/docs/{{version}}/how-to-contribute-to-the-magento-2-community)
Expand Down

0 comments on commit 513846e

Please sign in to comment.