Currently, I am developing a plugin that can calculate shipping charges based on distance. On installation of the plugin, I want to add a custom shipping method to the backend.
What can I do to accomplish this?
Step 1: Verify if the Shipping Method Already Exists with the UUID you are using
To prevent duplicates, start by checking if the custom shipping method already exists. Search for the method using its ID.
$newShippingMethod = $this->shippingMethodRepository->search( (new Criteria([self::SHIPPING_METHOD_ID])), $salesChannelContext )->first();
We only create a new one if we haven't found anything.
Step 2: Get Availability Rule and Delivery Time IDs
We need to use the ruleRepository and deliveryTimeRepository to obtain the IDs for the availability rule and delivery time associated with the new shipping method.
//Fetching the availability rule
$this->avialabilityRuleId = $this->ruleRepository->search(
(new Criteria()),
$salesChannelContext
)->first()->getId();
//Fetching the delivery time
$this->deliveryTimeId = $this->deliveryTimeRepository->search(
(new Criteria()),
$salesChannelContext
)->first()->getId();
Step 3: Create the Shipping Method Entity
Let's create the shipping method with necessary details like name, description, availability rule. In this instance, we have kept a fixed price, but it's customizable based on your logic:
$shippingMethod = [ 'id' => self::SHIPPING_METHOD_ID,
'name' => self::SHIPPING_METHOD_NAME,
'description' => self::SHIPPING_METHOD_DESCRIPTION,
'active' => true,
'availabilityRuleId' => $this->availabilityRuleId,
"deliveryTimeId" => $this->deliveryTimeId,
];
Step 4: Add the Shipping Method to the Repository
Now, we add the newly created shipping method to the shipping method repository:
$this->shippingMethodRepository->create([$shippingMethod], $salesChannelContext);
Step 5: Create a shipping method price matrix
After that, we now need to add a price matrix to the shipping method. We're just going to use a fixed price for now to show you how it works, but don't worry, it can be adjusted to fit whatever you need.
$uuidString = self::SHIPPING_METHOD_ID;
$uuidBinary = Uuid::fromHexToBytes($uuidString);
$currencyPrice = '{"cb7d2554b0ce847cd82f3ac9bd1c0dfca":{"currencyId":"'.self::CURRENCY_ID.'","net":"0","gross":"0","linked":false}}';
if ($connection) {
$connection->executeStatement('INSERT INTO `shipping_method_price`
(`id`, `shipping_method_id`,`calculation`,`currency_price`, `quantity_start`,`quantity_end`,`created_at`)
VALUES
(?,?,1,?,0,null, NOW())', [Uuid::randomBytes(), $uuidBinary,$currencyPrice]);
}
Step 6: Assign the Shipping Method to Sales Channels
Before we can use the new shipping method for existing sales channels, we need to adjust the sales channel configuration. The first step is to get a list of all sales channels.
$criteria = new Criteria();
$criteria->addAssociation('shippingMethods');
$salesChannels = $this->salesChannelRepository->search($criteria, $context)->getEntities();
Next, we will update each sales channel with the new shipping method by preparing the necessary data.
$salesChannelData = [];
foreach ($salesChannels as $salesChannel) {
$shippingMethods = $salesChannel->getShippingMethods();
$shippingMethods->add($newShippingMethod);
$shippingMethodIds = [];
foreach ($shippingMethods as $shippingMethod) {
$shippingMethodIds[] = ["id" => $shippingMethod->getId()];
}
$salesChannelData[] = [
'id' => $salesChannel->getId(),
'shippingMethods' => $shippingMethodIds,
];
}
Finally, we update the sales channels with the new shipping method configuration.
$this->salesChannelRepository->update($salesChannelData, $context);