Рассмотрим пример создания модуля для вымышленного типа доставки CustomDeliveryType. Структура папок модуля рекомендуется следующая:
- customdeliverytype
- config
- file.inc.php
- handlers.inc.php
- module.xml
- model
Непосредственно функциональность модуля доставки реализована в классе DeliveryType. Класс DeliveryType должен быть унаследован от базового класса Shop::Model::DeliveryType::AbstractType.
Класс, описывающий тип доставки (deliverytype.inc.php)
Рассмотрим методы базового класса Shop::Model::DeliveryType::AbstractType, которые необходимо реализовать/унаследовать в нашем классе DeliveryType.
Основная информация о типе доставки
abstract public function getTitle();
abstract public function getDescription();
abstract public function getShortName();
Дополнительная форма для способа доставки
Форма отображается пользователью в окне редактирования способа доставки.
public function getFormObject()
{}
Пример готовой формы:
public function getFormObject()
{
$properties = new PropertyIterator([
'api_key' => (new Type\Integer())
->setDescription(t('API ключ')),
...
]);
$form_object = new FormObject($properties);
$form_object->setParentObject($this);
$form_object->setParentParamMethod('Form');
return $form_object;
}
Инициализация типа доставки
public function loadOptions(array $opt = null)
{
$this->opt = $opt;
}
Описание взаимодействия с адресом при оформлении заказа
public function getRequiredAddressFields(): array
{
$config = ConfigLoader::byModule('shop');
return $config->getRequiredAddressFields();
}
public function canCalculateCostByDeliveryAddress(Address $address): bool
{
return true;
}
Проверка ошибок
public function getSelectError(Order $order): string
{
return '';
}
public function getCheckoutError(Order $order): string
{
return '';
}
Калькуляция стоимости и сроков доставки
Необходимо реализовать метод getDeliveryCost, который должен возвращать стоимость доставки заказа $order по адресу $address с параметрами доставки $delivery.
ReadyScript предлагает дефолтную реализацию определения сроков, которая зависит от указанных в административной панели сроков у регионов доставки. Если ваш способ доставки позволяет автоматически получать срок доставки, то необходимо реализовать всю логику получения сроков доставки в методе calcDeliveryPeriod. Метод должен возвращать объект Shop::Model::DeliveryType::Helper::DeliveryPeriod или null (если срок не удалось определить)
Отрывок из абстрактного класса Shop::Model::DeliveryType::AbstractType
abstract public function getDeliveryCost(Order $order, Address $address = null, Delivery $delivery, $use_currency = true);
protected function calcDeliveryPeriod(Order $order, Address $address = null, Delivery $delivery = null)
{
if (!$delivery) {
$delivery = $order->getDelivery();
}
if (!empty($delivery['delivery_periods'])) {
$zone_api = new ShopZoneApi();
$zones = $zone_api->getZonesByRegionId($address['region_id'], $address['country_id'], $address['city_id']);
foreach ($delivery['delivery_periods'] as $delivery_period) {
if ($delivery_period['zone'] == 0 || in_array($delivery_period['zone'], $zones)) {
return new Helper\DeliveryPeriod(isset($delivery_period['days_min']) ? $delivery_period['days_min'] : null,
isset($delivery_period['days_max']) ? $delivery_period['days_max'] : null,
isset($delivery_period['text']) ? $delivery_period['text'] : null);
}
}
}
return null;
}
Пункты выдачи заказов
public function getSelectedPvz(Order $order): ?Pvz
{
if ($this->hasPvz()) {
$delivery_extra = $order->getExtraKeyPair(Order::EXTRAKEYPAIR_DELIVERY_EXTRA);
if (!empty($delivery_extra[self::EXTRA_KEY_PVZ_DATA])) {
$pvz_data = json_decode(htmlspecialchars_decode($delivery_extra[self::EXTRA_KEY_PVZ_DATA]), true);
if ($pvz_data) {
return Pvz::loadFromArray($pvz_data);
}
}
}
return null;
}
public function getPvzByAddress(Address $address)
{
return [];
}
public function hasPvz(): bool
{
return false;
}
Прочие методы
public function onOrderCreate(Order $order, Address $address = null)
{}
protected function getAdditionalHtml(Order $order): string
{
return '';
}
public function getAdminHTML(Order $order)
{
return "";
}
Регистрация нового типа доставки в системе
Для регистрации в системе нового типа доставки, необходимо обработать событие delivery.gettypes. Согласно формату моделей в ReadyScript, регистрация обработчика событий производится в файле /config/handlers.inc.php.
Пример регистрации нового типа доставки CustomDeliveryType.
<?php
namespace CustomDeliveryType\Config;
{
function init()
{
$this->bind('delivery.gettypes');
}
public static function deliveryGetTypes($list)
{
$list[] = new \CustomDeliveryType\Model\DeliveryType\DeliveryType();
return $list;
}
}
Интерфейс работы с заказами на доставку
Чтобы тип доставки поддерживал взаимодействие с заказами на доставку на стороне внешнего сервиса доставки, он должен имплементировать интерфейс Shop::Model::DeliveryType::InterfaceDeliveryOrder и использовать трейт Shop::Model::DeliveryType::TraitInterfaceDeliveryOrder. Трейт создан для упрощения разработки, в нем уже реализованы некоторые методы интерфейса, но при необходимости вы сможете их перегрузить в вашем классе платежной системы.
Основные методы интерфейса
Данные методы обеспечивают базовый функционал интерфейса, их реализация обязательна:
public function createDeliveryOrder(Order $order): DeliveryOrder;
public function deleteDeliveryOrder(DeliveryOrder $delivery_order): void;
public function refreshDeliveryOrder(DeliveryOrder $delivery_order): void;
public function getDeliveryOrderDataLines(DeliveryOrder $delivery_order): array;
Для сохранения заказа на доставку в системе RS следует использовать класс Shop::Model::Orm::DeliveryOrder. Ниже приведён список полей объекта Shop::Model::Orm::DeliveryOrder, которые необходимо заполнить перед сохранением:
external_id - (string) Внешний идентификатор заказа на доставку (используется для внешних запросов)
order_id - (int) id заказа на стороне RS
delivery_type - (string) Расчётный класс доставки (получается при помощи вызова метода getShortName() у типа доставки)
number - (string) Номер заказа на доставку
data - (array) Сохранённые произвольные данные
address - (string) Адрес, на который создан заказ на доставку
Дополнительные методы интерфейса
Данные методы могут быть унаследованы для реализации специфических функций, применяемых к созданному заказу на доставку:
public function getDeliveryOrderActions(DeliveryOrder $delivery_order): array;
public function executeInterfaceDeliveryOrderAction(HttpRequest $http_request, Order $order, string $action): array;