Расширение расчета стоимости доставки

Ранее мы писали, что настройки бесплатной версии позволяют настраивать лишь фиксированную стоимость доставки. Однако, плагин имеет достаточно хорошую архитектуру для расширения логики расчета под ваши конкретные нужды. Для этого вам понадобятся небольшие знания в PHP и Wordpress. Все остальное мы постарались упростить для вас при разработке архитектуры.

В данном руководстве будет описана архитектура, отвечающая за калькуляцию стоимости, а также показан классический пример расчета стоимости в зависимости от суммы корзины. Обладая этими знаниями вы сможете реализовать практически любую логику расчета доставки.

Архитектура системы расчета стоимости

В основе архитектуры заложены модульность кода и абстракции над стандартными сущностями WooCommerce. Большая часть кода оперирует данными абстракциями не обращаясь напрямую к стандартным функциям Woo. Это дает нам возможность менять реализацию под динамические требования к продукту, стандартизируя общие контракты между внутренними модулями плагина. Если вы не являетесь разработчиком, возможно это звучит сложно, однако понимание логики работы плагина просто необходимо, если вы хотите расширять его под свои задачи. Ниже приведена визуальная диаграмма классов, описывающая взаимодействие компонентов, которые отвечают за расчет доставки и создание заказов. Как можно заметить, PRO и Free версия плагинов имеют одинаковую архитектуру, но отличаются разным количеством функционала.

Сервис расчета стоимости (CalculationService на диаграмме) принимает в качестве параметра реализацию интерфейса OrderDataInterface. В него плагин собирает все данные о заказе и доставке для конкретного состояния магазина (когда нужно расчитать стоимость, создать или изменить заказ). Этими данными мы и будем оперировать, когда будем писать свою логику расчета. OrderDataInterface имеет следующие методы:

public function getSubTotal();
// Возвращает сумму заказа без учета скидок, налогов, надбавок и т.д.
// Тип возвращаемых данных: float

public function getDiscountTotal();
// Возвращает сумму всех скидок заказа.
// Тип возвращаемых данных: float

public function getTotal();
// Возвращает итоговую сумму заказа (после всех расчетов).
// Тип возвращаемых данных: float

public function getCalculatedTotal();
// Возвращает сумму заказа после расчетов скидок и надбавок, но без стоимости доставки.
// Тип возвращаемых данных: float

public function getShippingAddress();
// Возвращает информацию про данные доставки.
// Тип возвращаемых данных: AddressInterface (будет описан ниже)

public function isAddressShipping();
// Проверяет, является ли доставка адресной.
// Тип возвращаемых данных: bool

public function getPaymentMethod();
// Возвращает код выбранного метода оплаты (cod, bacs, liqpay и т.д.)
// Тип возвращаемых данных: string

public function isShipToDifferentAddress();
// Проверяет, выбрана ли галочка "Доставка по другому адресу"
// Тип возвращаемых данных: bool

В свою очередь AddressInterface, возвращаемый методом getShippingAddress(), содержит следующие методы:

public function getAreaRef();
// Идентификатор выбранной области доставки
// Тип возвращаемых данных: string

public function getCityRef();
// Идентификатор выбранного города
// Тип возвращаемых данных: string

public function getWarehouseRef();
// Идентификатор выбранного отделения
// Тип возвращаемых данных: string

public function getCustomAddress();
// Пользовательский адрес (если указана адресная доставка).
// Тип возвращаемых данных: string

public function isAddressShipping();
// Проверяет, является ли доставка адресной.
// Тип возвращаемых данных: bool

Пример: расчет стоимости в зависимости от суммы корзины

Для примера, реализуем такую логику расчета:

  • если сумма корзины (sub total) < 1000 грн., то установить стоимость доставки в 60 грн.
  • если сумма корзины >= 1000 грн., то сделать доставку бесплатной

Для начала, установим текущую стоимость доставки в 50 грн. и убедимся, что плагин корректно выводит фиксированную стоимость. Перейдем на страницу чекаута, чтобы это проверить.

Теперь открываем файл functions.php вашей темы и пишем следующий код:

add_filter('wcus_calculate_shipping_cost', function ($cost, $orderData) {
    return $orderData->getSubTotal() >= 1000 ? 0 : 60;
}, 10, 2);

Сохраняем файл и переходим на сайт. Добавляем товары в корзину на сумму < 1000 грн. и проверяем стоимость доставки.

Теперь добавляем товаров на сумму больше 1000 грн. и проверяем результат.