Службы доставки битрикс. Создание собственных автоматизированных обработчиков служб доставки. Выбор автоматизированных служб

  • Tutorial

В предыдущей статье мы рассмотрели процесс установки нового компонента оформления заказов. Он несколько дней обкатался на проекте, и пришла пора воспользоваться теми возможностями, ради которых стоило переходить на новую платформу «1С-Битрикс».

Автоматическая подстановка города по умолчанию

Этот пример будет полезен как небольшим региональным магазинам, так и крупным проектам.

Регион доставки - это первый из главных элементов процесса оформления заказа. Допустим, нам нужно использовать автоматическую подстановку названия «Калининград» для увеличения конверсии и уменьшении проблем с оформлением заказов.

Сейчас при первом входе это выглядит вот так:

Клиенты, конечно, могут щелкнуть по кнопке «Калининград», после чего поле заполнится, но многие просто пропускают этот шаг, в результате получая ошибку:

Данную проблему выявил «Вебвизор Метрики». Конечно, после этого клиент уже заполняет всё правильно, но осадок остается, несмотря на то, что во многих магазинах важным критерием является самовывоз (до 80% заказов), а в этом случае правильность заполнения названия города не критична.

Давайте проставим город по умолчанию и посмотрим, сработает ли подстановка. Зайдем в административный раздел магазина, и далее в настройки свойств:

И настраиваем местоположение по умолчанию:

Теперь для проверки оформим заказ:

Отлично, местоположение заполнено и клиенту достаточно нажать «Далее». Теперь заказ будет оформляться с минимальными неудобствами для клиента, а мы максимально увеличим конверсию. Что касается крупных магазинов, то они могут собрать статистику по частоте заказов из тех или иных городов, и сделать кнопки быстрого выбора, как на скриншоте: «Калининград», «Зеленоградск», «Светлогорск».

Можно установить самый популярный город по умолчанию, ведь всегда проще изменить его или уточнить по телефону, чем потерять клиента.

Дополнительные ограничения в оплате

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

Введем ограничение с привязкой к определенным службам доставки и максимальной сумме чека. Для этого идем в административный интерфейс на вкладку «Ограничения», для конкретного способа оплаты:

В данном случае нужно будет сделать две системы оплаты наличными:

  • в одной ограничим использование для точки самовывоза, но без ограничений по цене,
  • а во второй будем ограничиваться курьерскими службами, и добавим ограничение по сумме.
Сначала установим ограничение по цене:

Теперь ограничения по доставкам:

В итоге у нас получается следующее:

Проверим оформление заказа с товарами на сумму менее 10 000 рублей и доставкой курьером:

Всё отлично, требуемая оплата есть, заказ можно оформить.

Проверим с товаром более 10 000 рублей:

Замечательно, наличная оплата отсутствует, можно оформить заказ с оплатой другими способами, не рискуя курьерами и деньгами.

При введении ограничений клиенты не видят «запрещенные» способы оплаты и поэтому не будут ругаться с операторами, которым в противном случае пришлось бы постоянно объяснять, почему ваша компания не повезет оформленный заказ.

Дополнительные услуги в доставках

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

Идем в настройки доставок:

В интерфейсе появилась отдельная вкладка с дополнительными услугами, которые будут отображаться в блоке доставок. Поддерживаются услуги трех видов:


Давайте посмотрим, как настраиваются подобные правила:

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

  • Менеджер - услуга будет отображаться в административном интерфейсе.
  • Клиент - услуга будет отображаться во время оформления заказа в публичной части сайта.
Вот так выглядит добавление услуги в административном интерфейсе, при создании заказа или внесении правок:

Динамический «Ввод личных данных»

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

Новый компонент оформления заказа умеет запрашивать различные наборы полей. Чаще всего владельцы магазинов уменьшают количество информации, которую нужно ввести при самовывозе. Пожалуй, в этом случае нам будет достаточно знать:

  • Телефон.
  • E-mail. Этот пункт тоже можно убрать, но иногда хочется «баловать» клиента рассылками о новинках.
Перейдем в административный раздел «Свойства заказа» -> «Список свойств», и выберем для изменения свойство адрес:

Привяжем только те «Службы доставки», у которых должно отображаться данное поле. Затем идем в публичный раздел и пробуем оформить заказ. Выбираем самовывоз и видим, что магазин не спрашивает у нас адрес доставки.

Это полезная и долгожданная функциональность. Ведь согласитесь, что не слишком приятно отвечать на вопросы клиентов: «А зачем вам мой адрес, если я собираюсь забрать заказ самостоятельно?». Теперь этого делать не требуется.

Пункт выдачи заказа

Напоследок хочется рассказать об изменениях в блоке выбора «Пунктов выдачи заказа». В предыдущей версии основные нарекания были на проблемы с отображением большого количества точек самовывоза, мелкую карту, отсутствие автоматического выбора пункта самовывоза (если он был один, например).

В новой версии компонента появилась настройка способа отображения пункта выдачи заказов. Если он единственный в каком-либо городе, то сразу показываем свернутый блок и выводим все его данные с картинкой, или показываем блок развернутым. В первом случае, для отображения карты вам нужно будет войти в блок, а во втором - карта будет сразу отображена.

Давайте реализуем первый вариант:

Если же отображать блок развернутым, то клиент увидит следующую картину:

На этом мы заканчиваем наш небольшой туториал. Мы будем продолжать знакомить вас с особенностями новых версий наших продуктов, следите за нашим блогом.

Мы рассмотрели процесс установки нового компонента оформления заказов. Он несколько дней обкатался на проекте, и пришла пора воспользоваться теми возможностями, ради которых стоило переходить на новую платформу «1С-Битрикс».

Автоматическая подстановка города по умолчанию

Этот пример будет полезен как небольшим региональным магазинам, так и крупным проектам.

Регион доставки - это первый из главных элементов процесса оформления заказа. Допустим, нам нужно использовать автоматическую подстановку названия «Калининград» для увеличения конверсии и уменьшении проблем с оформлением заказов.

Сейчас при первом входе это выглядит вот так:

Клиенты, конечно, могут щелкнуть по кнопке «Калининград», после чего поле заполнится, но многие просто пропускают этот шаг, в результате получая ошибку:

Данную проблему выявил «Вебвизор Метрики». Конечно, после этого клиент уже заполняет всё правильно, но осадок остается, несмотря на то, что во многих магазинах важным критерием является самовывоз (до 80% заказов), а в этом случае правильность заполнения названия города не критична.

Давайте проставим город по умолчанию и посмотрим, сработает ли подстановка. Зайдем в административный раздел магазина, и далее в настройки свойств:

И настраиваем местоположение по умолчанию:

Теперь для проверки оформим заказ:

Отлично, местоположение заполнено и клиенту достаточно нажать «Далее». Теперь заказ будет оформляться с минимальными неудобствами для клиента, а мы максимально увеличим конверсию. Что касается крупных магазинов, то они могут собрать статистику по частоте заказов из тех или иных городов, и сделать кнопки быстрого выбора, как на скриншоте: «Калининград», «Зеленоградск», «Светлогорск».

Можно установить самый популярный город по умолчанию, ведь всегда проще изменить его или уточнить по телефону, чем потерять клиента.

Дополнительные ограничения в оплате

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

Введем ограничение с привязкой к определенным службам доставки и максимальной сумме чека. Для этого идем в административный интерфейс на вкладку «Ограничения», для конкретного способа оплаты:

В данном случае нужно будет сделать две системы оплаты наличными:

  • в одной ограничим использование для точки самовывоза, но без ограничений по цене,
  • а во второй будем ограничиваться курьерскими службами, и добавим ограничение по сумме.
Сначала установим ограничение по цене:

Теперь ограничения по доставкам:

В итоге у нас получается следующее:

Проверим оформление заказа с товарами на сумму менее 10 000 рублей и доставкой курьером:

Всё отлично, требуемая оплата есть, заказ можно оформить.

Проверим с товаром более 10 000 рублей:

Замечательно, наличная оплата отсутствует, можно оформить заказ с оплатой другими способами, не рискуя курьерами и деньгами.

При введении ограничений клиенты не видят «запрещенные» способы оплаты и поэтому не будут ругаться с операторами, которым в противном случае пришлось бы постоянно объяснять, почему ваша компания не повезет оформленный заказ.

Дополнительные услуги в доставках

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

Идем в настройки доставок:

В интерфейсе появилась отдельная вкладка с дополнительными услугами, которые будут отображаться в блоке доставок. Поддерживаются услуги трех видов:

  • Список услуг. Клиенту предлагается выбрать какой-то пункт из списка услуг. По умолчанию выбирается первый пункт, поэтому, если вам не требуется увеличения цены, то первая услуга в списке должна быть с нулевой ценой.

Количественная услуга. Создается услуга с ценой за единицу, а клиент может указать, какое количество ему требуется.

Единичная услуга. Самостоятельная услуга, отображается как чек-бокс. По умолчанию не применяется, клиент должен самостоятельно выбрать нужную.

Давайте посмотрим, как настраиваются подобные правила:

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

  • Менеджер - услуга будет отображаться в административном интерфейсе.
  • Клиент - услуга будет отображаться во время оформления заказа в публичной части сайта.
Вот так выглядит добавление услуги в административном интерфейсе, при создании заказа или внесении правок:

Динамический «Ввод личных данных»

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

Новый компонент оформления заказа умеет запрашивать различные наборы полей. Чаще всего владельцы магазинов уменьшают количество информации, которую нужно ввести при самовывозе. Пожалуй, в этом случае нам будет достаточно знать:

  • Телефон.
  • E-mail. Этот пункт тоже можно убрать, но иногда хочется «баловать» клиента рассылками о новинках.
Перейдем в административный раздел «Свойства заказа» -> «Список свойств», и выберем для изменения свойство адрес:

Привяжем только те «Службы доставки», у которых должно отображаться данное поле. Затем идем в публичный раздел и пробуем оформить заказ. Выбираем самовывоз и видим, что магазин не спрашивает у нас адрес доставки.

Это полезная и долгожданная функциональность. Ведь согласитесь, что не слишком приятно отвечать на вопросы клиентов: «А зачем вам мой адрес, если я собираюсь забрать заказ самостоятельно?». Теперь этого делать не требуется.

Пункт выдачи заказа

Напоследок хочется рассказать об изменениях в блоке выбора «Пунктов выдачи заказа». В предыдущей версии основные нарекания были на проблемы с отображением большого количества точек самовывоза, мелкую карту, отсутствие автоматического выбора пункта самовывоза (если он был один, например).

В новой версии компонента появилась настройка способа отображения пункта выдачи заказов. Если он единственный в каком-либо городе, то сразу показываем свернутый блок и выводим все его данные с картинкой, или показываем блок развернутым. В первом случае, для отображения карты вам нужно будет войти в блок, а во втором - карта будет сразу отображена.

Автоматизированные обработчики служб доставки позволяют программным образом реализовать произвольную логику расчёта стоимости доставки на основе параметров заказа и собственных настроек. Алгоритмы расчёта могут быть произвольными - фиксированная стоимость, запросы к удаленным web-сервисам, расчёт на основе собственных таблиц данных и т.д.

Обработчик представляет собой класс или набор функций следующей структуры:

Метод Описание
Описание обработчика Функция, возвращающая описание обработчика, названия методов, список профилей обработчика и пр.
Настройки обработчика Функция, возвращающая массив настроек обработчика
Обработка настроек Набор функций, отвечающий за подготовку настроек к занесению в БД и обратное преобразование.
Проверка совместимости Метод, осуществляющий проверку совместимости профилей данного обработчика с заказом.
Функция расчёта Метод, осуществляющий расчёт стоимости доставки на основе настроек обработчика и параметров заказа.

Поскольку работать с набором отдельных функций неудобно, рекомендуется объединить их в класс (пространство имен). Исходя из этой рекомендации будет идти дальнейшее описание, а также, реализован приводимый пример. В примере обработчик "Курьерская доставки" реализован в виде класса CDeliveryMySimple .

Описание обработчика

Описание обработчика представляет собой метод, возвращающий ассоциативный массив следующей структуры:

Параметр Описание
SID Уникальный строковой идентификатор обработчика.
NAME Название обработчика.
DESCRIPTION Текстовое описание обработчика
DESCRIPTION_INNER Внутреннее описание обработчика, отображаемое при конфигурации обработчика в Панели Управления.
BASE_CURRENCY Идентификатор базовой валюты обработчика
HANDLER Путь к файлу обработчика. Нужен для корректного автоматического копирования обработчика (ещё не реализовано). В подавляющем большинстве случаев достаточно значения __FILE__
GETCONFIG Название метода, возвращающего массив настроек валидатора. В случае реализации обработчика в виде класса, значение представляет собой массив ("имя_класса", "имя_метода").
DBSETSETINGS Название метода, отвечающего за проверку настроек обработчика и преобразование массива настроек в строку для сохранения. В случае реализации обработчика в виде класса, значение представляет собой массив ("имя_класса", "имя_метода"). В случае отсутствия этого метода массив настроек будет сохранен в базу в сериализованном виде.
DBGETSETTINGS Название метода, отвечающего за обратное преобразование строки настроек обработчика в массив. В случае реализации обработчика в виде класса, значение представляет собой массив ("имя_класса", "имя_метода").
COMPABILITY Название метода, отвечающего за дополнительную проверку совместимости профилей обработки с параметрами заказа. Если метод отсутствует, дополнительная проверка не будет проводиться. В случае реализации обработчика в виде класса, значение представляет собой массив ("имя_класса", "имя_метода").
CALCULATOR Название метода, осуществляющего расчёт стоимости доставки. В случае реализации обработчика в виде класса, значение представляет собой массив ("имя_класса", "имя_метода").
PROFILES Массив профилей обработки. Должен содержать хотя бы один профиль. Формат описания см. ниже.

Описание профилей представляет собой массив следующего формата:

"строковой_идентификато_профиля " => array("TITLE" => "название_профиля ", "DESCRIPTION" => "описание_профиля ", // веса указываются в граммах "RESTRICTIONS_WEIGHT" => array(минимальный_вес , максимальный_вес ), // суммы указываются в базовой валюте обработчика "RESTRICTIONS_SUM" => array(минимальная_сумма_заказа , максимальная_сумма_заказа ));

Если массив RESTRICTIONS_WEIGHT или RESTRICTIONS_SUM содержит один элемент, то он считается минимальным значением. Если никаких ограничений не требуется, нужно указать array(0) .

Function Init() { return array(/* Basic description */ "SID" => "simple", "NAME" => "Доставка курьером", "DESCRIPTION" => "", "DESCRIPTION_INNER" =>
" .".", "BASE_CURRENCY" => COption::GetOptionString("sale", "default_currency", "RUB"), "HANDLER" => __FILE__, /* Handler methods */ "DBGETSETTINGS" => array("CDeliveryMySimple", "GetSettings"), "DBSETSETTINGS" => array("CDeliveryMySimple", "SetSettings"), "GETCONFIG" => array("CDeliveryMySimple", "GetConfig"), "COMPABILITY" => array("CDeliveryMySimple", "Compability"), "CALCULATOR" => array("CDeliveryMySimple", "Calculate"), /* List of delivery profiles */ "PROFILES" => array("simple" => array("TITLE" => "доставка", "DESCRIPTION" => "Срок доставки до 3 дней", "RESTRICTIONS_WEIGHT" => array(0), "RESTRICTIONS_SUM" => array(0),),)); }

Параметры валидатора

Метод, заданный элементом GETCONFIG , должен возвращать массив элементов вида:

Array("CONFIG_GROUPS" => array("идентификатор_группы1 " => "название_группы1 ", "идентификатор_группы2 " => "название_группы2 ", /* ...................... */), "CONFIG" => array("идентфикатор_параметра1 " => array("TITLE" = > "название_параметра1 ", "TYPE" => "тип_параметра1 ", "DEFAULT" => "значение_по_умолчанию_параметра1 ", "GROUP" => "идентфикатор_группы_параметра1 ", "VALUES" => array("значение1_параметра1 " => "наименование_значения1_параметра1 ", "значение2_параметра1 " => "наименование_значения2_параметра1 ", /* ....................... */)), /* ........................ */))

Группы параметров, описываемые в элементе массива с ключом " CONFIG_GROUPS " отображаются в виде отдельных вкладок в форме редактирования параметров обработчика, содержащих параметры, приписанные к этой группе. Элемент массива с ключом " CONFIG " задает список параметров. Тип параметра может принимать одно из следующих значений:

  • STRING - поле для ввода текста
  • PASSWORD - поле для ввода пароля
  • CHECKBOX - элемент типа "флажок" со значением "Y"
  • RADIO
  • DROPDOWN - набор вариантов в виде выпадающего списка
  • MULTISELECT - набор вариантов в виде списка со множественным выбором
  • RADIO - набор вариантов в виде радио-кнопок

Для типов параметра подразумевающий выбор из нескольких вариантов значений (DROPDOWN , MULTISELECT и RADIO ) список значений задается элементом описательного массива с ключом " VALUES ". Для остальных типов параметров этот элемент игнорируется.

Function GetConfig() { $arConfig = array("CONFIG_GROUPS" => array("all" => "Стоимость доставки",), "CONFIG" => array(),); // параметрами обработчика в данном случае являются значения стоимости доставки в различные группы местоположений. // для этого сформируем список параметров на основе списка групп $dbLocationGroups = CSaleLocationGroup::GetList(); while ($arLocationGroup = $dbLocationGroups->Fetch()) { $arConfig["CONFIG"]["price_".$arLocationGroup["ID"]] = array("TYPE" => "STRING", "DEFAULT" => "", "TITLE" => "Стоимость доставки в группу "\" " .$arLocationGroup["NAME"]."\" " .(".COption::GetOptionString("sale", "default_currency", "RUB").")", "GROUP" => "all",); } return $arConfig; }

Обработка параметров

Обработка параметров обработчика требует двух методов, задаваемых в описании параметрами DBSETSETTINGS и DBGETSETTINGS . Первый из них получает на вход массив значений параметров вида "идентфикатор_параметра " => "значение_параметра " и должен вернуть их строковое представление. Второй - совершить обратное преобразование. Оба метода могут также совершать произвольные манипуляции со значениями параметров.

Function SetSettings($arSettings) { // Проверим список значений стоимости. Пустые значения удалим из списка. foreach ($arSettings as $key => $value) { if (strlen($value) > 0) $arSettings[$key] = doubleval($value); else unset($arSettings[$key]); } // вернем значения в виде сериализованного массива. // в случае более простого списка настроек можно применить более простые методы сериализации. return serialize($arSettings); } function GetSettings($strSettings) { // вернем десериализованный массив настроек return unserialize($strSettings); }

Проверка совместимости

Проверка совместимости профилей обработчика с заказом осуществляется методом, задаваемым в описании параметром " COMPABILITY ". Этот метод принимает на вход 2 параметра - описательный массив заказа и массив настроек обработчика. В качестве ответа метода ожидается массив, содержащий идентификаторы подходящих для данного заказа профилей доставки. Проверка, задаваемая значениями " RESTRICTIONS_WEIGHT " и " RESTRICTIONS_SUM " в настройках профиля, производится вне обработчика и здесь не требуется. Формат принимаемых на вход данных следующий:

Первый параметр - информация о заказе - представляет собой массив со следующими ключами:

Второй параметр представляет собой значение массива, заданного элементом с ключом " CONFIG " в обработчика, к каждому элементу которого добавлено значение параметра с ключом " VALUE ".

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

// введем служебный метод, определяющий группу местоположения и возвращающий стоимость для этой группы. function __GetLocationPrice($LOCATION_ID, $arConfig) { // получим список групп для переданного местоположения $dbLocationGroups = CSaleLocationGroup::GetLocationList(array("LOCATION_ID" => $LOCATION_ID)); while ($arLocationGroup = $dbLocationGroups->Fetch()) { if (array_key_exists("price_".$arLocationGroup["LOCATION_GROUP_ID"], $arConfig) && strlen($arConfig["price_".$arLocationGroup["LOCATION_GROUP_ID"]]["VALUE"] > 0)) { // если есть непустая запись в массиве настроек для данной группы, вернем ее значение return $arConfig["price_".$arLocationGroup["LOCATION_GROUP_ID"]]["VALUE"]; } } // если не найдено подходящих записей, вернем false return false; } // метод проверки совместимости в данном случае практически аналогичен рассчету стоимости function Compability($arOrder, $arConfig) { // проверим наличие стоимости доставки $price = CDeliveryMySimple::__GetLocationPrice($arOrder["LOCATION_TO"], $arConfig); if ($price === false) return array(); // если стоимость не найдено, вернем пустой массив - не подходит ни один профиль else return array("simple"); // в противном случае вернем массив, содержащий идентфиикатор единственного профиля доставки }

Обработчик

Основной метод расчёта стоимости доставки получает на вход следующие параметры:

  • идентификатор профиля доставки;
  • массив настроек обработчика доставки;
  • описательный массив заказа;
  • текущий шаг расчёта;
  • временные данные, переданные с прошлого шага расчёта.

На выход обработчик должен дать стоимость доставки в валюте, задаваемой в параметрах, либо массив следующей структуры:

Ключ Описание
RESULT Идентификатор ответа. Возможные значения:
  • "OK " - стоимость доставки успешно рассчитана;
  • "ERROR " - в процессе расчёта произошла ошибка;
  • "NEXT_STEP " - необходимо перейти на следующий шаг для продолжения расчёта.
VALUE Значение стоимости доставки в валюте, задаваемой в параметрах. (RESULT = "OK")
TRANSIT Длительность доставки в днях (RESULT = "OK"). Если отсутствует, то длительность не выводится.
periodFrom Строки доставки автоматизированных служб доставок. От указанного количества дней. Необходим для передачи сроков доставки в Яндекс.маркет. Используется при разработке собственных служб доставок.
periodTo Строки доставки автоматизированных служб доставок. До указанного количества дней. Необходим для передачи сроков доставки в Яндекс.маркет. Используется при разработке собственных служб доставок.
TEXT Текст ошибки или текст, сопровождающий переход на следующий шаг (RESULT = {"ERROR"|"NEXT_STEP"}).
TEMP Строка, содержащая промежуточные данные, передаваемые следующему шагу (RESULT = "NEXT_STEP").

В описываемом нами примере многошаговый процесс не подразумевается, потому, расчёт осуществляется просто.

Function Calculate($profile, $arConfig, $arOrder, $STEP, $TEMP = false) { // служебный метод рассчета определён выше, нам достаточно переадресовать на выход возвращаемое им значение. return array("RESULT" => "OK", "VALUE" => CDeliveryMySimple::__GetLocationPrice($arOrder["LOCATION_TO"], $arConfig)); }

Интеграция обработчика

Путь к автоматически подключаемым файлам обработчиков устанавливается в настройках модуля "Интернет-магазин". Путь по умолчанию - /bitrix/php_interface/include/sale_delivery/ Такие файлы должны иметь префикс delivery_ , в противном случае, они будут проигнорированы. Если система обнаружит файл, имеющее то же название, что и системный, то он будет подключаться вместо системного. Подключение автоматизированной доставки в файле производится установкой описательного метода в качестве обработчика события onSaleDeliveryHandlersBuildList .

Пример

Подытожив все вышесказанное, сформируем обработчик простой доставки. Класс обработчика расположим в файле /bitrix/php_interface/include/sale_delivery/delivery_mysimple.php

"simple", "NAME" => "Доставка курьером", "DESCRIPTION" => "", "DESCRIPTION_INNER" => "Простой обработчик курьерской доставки. Для функционирования необходимо " ."наличие хотя бы одной группы местоположений. При настройке обработчика указывается " ."фиксированная стоимость доставки для каждой группы местоположений. Для того, чтобы " ."группа не участвовала в обработке, оставьте пустым поле стоимости для этой группы." ."
" ."" ."Редактировать группы местоположений" .".", "BASE_CURRENCY" => COption::GetOptionString("sale", "default_currency", "RUB"), "HANDLER" => __FILE__, /* Методы обработчика */ "DBGETSETTINGS" => array("CDeliveryMySimple", "GetSettings"), "DBSETSETTINGS" => array("CDeliveryMySimple", "SetSettings"), "GETCONFIG" => array("CDeliveryMySimple", "GetConfig"), "COMPABILITY" => array("CDeliveryMySimple", "Compability"), "CALCULATOR" => array("CDeliveryMySimple", "Calculate"), /* Список профилей доставки */ "PROFILES" => array("simple" => array("TITLE" => "доставка", "DESCRIPTION" => "Срок доставки до 3 дней", "RESTRICTIONS_WEIGHT" => array(0), // без ограничений "RESTRICTIONS_SUM" => array(0), // без ограничений),)); } // настройки обработчика function GetConfig() { $arConfig = array("CONFIG_GROUPS" => array("all" => "Стоимость доставки",), "CONFIG" => array(),); // настройками обработчика в данном случае являются значения стоимости доставки в различные группы местоположений. // для этого сформируем список настроек на основе списка групп $dbLocationGroups = CSaleLocationGroup::GetList(); while ($arLocationGroup = $dbLocationGroups->Fetch()) { $arConfig["CONFIG"]["price_".$arLocationGroup["ID"]] = array("TYPE" => "STRING", "DEFAULT" => "", "TITLE" => "Стоимость доставки в группу \"" .$arLocationGroup["NAME"]."\" " ."(".COption::GetOptionString("sale", "default_currency", "RUB").")", "GROUP" => "all",); } return $arConfig; } // подготовка настроек для занесения в базу данных function SetSettings($arSettings) { // Проверим список значений стоимости. Пустые значения удалим из списка. foreach ($arSettings as $key => $value) { if (strlen($value) > 0) $arSettings[$key] = doubleval($value); else unset($arSettings[$key]); } // вернем значения в виде сериализованного массива. // в случае более простого списка настроек можно применить более простые методы сериализации. return serialize($arSettings); } // подготовка настроек, полученных из базы данных function GetSettings($strSettings) { // вернем десериализованный массив настроек return unserialize($strSettings); } // введем служебный метод, определяющий группу местоположения и возвращающий стоимость для этой группы. function __GetLocationPrice($LOCATION_ID, $arConfig) { // получим список групп для переданного местоположения $dbLocationGroups = CSaleLocationGroup::GetLocationList(array("LOCATION_ID" => $LOCATION_ID)); while ($arLocationGroup = $dbLocationGroups->Fetch()) { if (array_key_exists("price_".$arLocationGroup["LOCATION_GROUP_ID"], $arConfig) && strlen($arConfig["price_".$arLocationGroup["LOCATION_GROUP_ID"]]["VALUE"] > 0)) { // если есть непустая запись в массиве настроек для данной группы, вернем ее значение return $arConfig["price_".$arLocationGroup["LOCATION_GROUP_ID"]]["VALUE"]; } } // если не найдено подходящих записей, вернем false return false; } // метод проверки совместимости в данном случае практически аналогичен рассчету стоимости function Compability($arOrder, $arConfig) { // проверим наличие стоимости доставки $price = CDeliveryMySimple::__GetLocationPrice($arOrder["LOCATION_TO"], $arConfig); if ($price === false) return array(); // если стоимость не найдено, вернем пустой массив - не подходит ни один профиль else return array("simple"); // в противном случае вернем массив, содержащий идентфиикатор единственного профиля доставки } // собственно, рассчет стоимости function Calculate($profile, $arConfig, $arOrder, $STEP, $TEMP = false) { // служебный метод рассчета определён выше, нам достаточно переадресовать на выход возвращаемое им значение. return array("RESULT" => "OK", "VALUE" => CDeliveryMySimple::__GetLocationPrice($arOrder["LOCATION_TO"], $arConfig)); } } // установим метод CDeliveryMySimple::Init в качестве обработчика события AddEventHandler("sale", "onSaleDeliveryHandlersBuildList", array("CDeliveryMySimple", "Init")); ?>

Post factum

Несколько советов в завершение:

  • Если Ваш обработчик использует какие-либо ресурсоемкие вычисления, обращения к базе данных, запросы к удаленным серверам и т.д., то категорически рекомендуется использовать тот или иной вариант кеширования результата, реализованный таким образом, чтобы запоминались результаты хотя бы для заказа с данными параметрами. Это необходимо из-за того, что в процессе оформления и обработки заказа запрос к обработчику на расчёт стоимости заказа может происходить несколько раз. В поставляемых обработчиках используется механизм управляемого кеширования, настроенный с учётом специфики алгоритма вычисления стоимости конкретной службой доставки.
  • Для кастомизации системного обработчика достаточно скопировать его файл (вместе с сопутствующими файлами, лежащими обычно в каталоге с тем же названием) в каталог /bitrix/php_interface/include/sale_deivery/ с сохранением имени. В этом случае он будет подключаться вместо системного.

Решаем проблему вывода автоматизированных служб доставки интернет-магазина Битрикс v14 при оформлении заказа на Яндекс.Маркете.

Речь пойдет вот об этом, оказывается не сделано, работают только настраиваемые службы, сегодня это исправим.
Тут я тестирую оформление заказа в панели Яндекс.Маркет, покупателю будет выводиться тоже самое, когда он будет оформлять заказ на Яндекс.Маркете.

Выбор автоматизированных служб

Сначала нам нужно добавить автоматизированные службы доставки в настройка модуля Интернет-магазина в разделе Покупки на маркете

Т.к. по умолчанию их там нет и модуль интернет-магазина обновлять мы уже не сможем, я редактирую прямо в модуле, т.к. в моем случае если обновить магазин, то у клиента все перестанет работать, что в вашем случае делать я не знаю, подумайте, в новом магазине Битрикс v16 возможно это тоже не будет работать.

Настройки задаются в административной странице в файле
/bitrix/modules/sale/admin/ymarket.php

Настраиваемые службы там есть до Самовывоз , а ниже это я вывел автоматизированные службы доставки, у всех значение например Почта , в моем случае была нужна только почта, если нужно что-то другое, будет несложно доработать, т.к. принцип будет ясен, где и что делать, но выводиться будут все автоматизированные службы, возможно и работать будут, просто я это не проверял.

Итак, находим где в файле формируется массив настраиваемых служб $arDeliveryList и добавляем к нему автоматизированные

$arDeliveryFilter = array(
"LID" => $arTab["SITE_ID"],
"ACTIVE" => "Y"
);

//STATIC DELIVERY
$dbDeliveryList = CSaleDelivery::GetList(
array("NAME" => "ASC"),
$arDeliveryFilter,
false,
false,
array("ID", "NAME")
);

$arDeliveryList=array();
while ($arDelivery = $dbDeliveryList->Fetch())
$arDeliveryList[$arDelivery["ID"]] = $arDelivery["NAME"];

//AUTOMATIC DELIVERY
$dbRes = CSaleDeliveryHandler::GetList(
array("NAME" => "ASC"),
$arDeliveryFilter
);
while($delivery = $dbRes->Fetch())
{
$deliveryId = ($delivery["ID"] ? $delivery["ID"] : $delivery["SID"]);
$arDeliveryList[ $deliveryId ] = $delivery["NAME"];
}


Далее находим блок вывода доставок и добавляем в список опцию для почты, в моем случае она была закомментирована, у вас скорее всего все тоже самое будет.

Вот так готовый селект выглядит, который выводит службы доставки в админке

$deliveryName):
$selected = isset($siteSetts["DELIVERIES"][$deliveryId]) ? $siteSetts["DELIVERIES"][$deliveryId] : "";
?>


С настройками все, осталось доработать скрипт на который приходят запросы с Яндекс.Маркета , он и говорит маркету, какие доставки показать покупателю при оформлении заказа на Яндекс.Маркете .

Запросы Яндекс.Маркет

Все запросы с Яндекс.Маркета в Битрикc приходят сначала в этот файл, в нем только подключение другого файла
/bitrix/services/ymarket/index.php

В том файле подключается само API Битрикс для взаимодействия Яндекс.Маркета с вашим интернет-магазином
/bitrix/modules/sale/services/ymarket/index.php

В этом файле интересует метод, который идет дальше, к нужному нам файлу для изменений, в этом ничего не меняем
$result = $YMHandler->processRequest($requestObject, $method, $postData);

А вот и наш файл, в котором вся логика взаимодействия Битрикса с Яндекс.Маркетом, работает с ним
/bitrix/modules/sale/general/ym_handler.php

Я ни сразу статью писал, какое-то время функционал тестировался и исправлялись ошибки, даже если что-то забыл сказать, файлы я прикрепил, можно разобраться.

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

Итак, какие были изменения в классе CSaleYMHandler
1) Добавлена переменная, в которой будет храниться полная информация о товарах в корзине для расчета доставки автоматизированными службами доставки.
protected $basketItems = array();

2) Изменен метод, который слушает корзину на маркете, получает информацию о товарах (корзине) и возвращает службы доставки и способы оплаты
protected function processCartRequest($arPostData)

3) Изменен метод, который получает информацию о товарах в корзине на маркете (id, цена, количество, вес, габариты и т.д.)
protected function getItemCartInfo($arItem, $currency)

4) Изменен метод, который получает информацию о местоположении покупателя, доступные ему службы доставки по фильтру, считает доставку и показывает ее покупателю на маркете.
protected function getDeliveryOptions($delivery, $price, $weight = 0, $arBasketItems = array())

Вот в этом методе рассчитываются настраиваемые и автоматизированные службы доставки Битрикс .

Обратите здесь внимание!

В моем случае магазин находится в Москве и для Москвы все автоматизированные службы доставки отключены, для покупателя из Москвы они показываться не должны, там Самовывоз и курьерская доставка работает, в коде это условие (стр. 432):
if($locationTo == 2691) continue;

5) Изменен метод, который добавляет на вашем сайте заказ, говорит маркету "Все ок" и возвращает его номер Яндекс.Маркету
protected function processOrderAcceptRequest($arPostData)

Конкретно строка 911, в ней получаем Номер заказа , это либо ID заказа , либо Код заказа при включенной нумерации заказа по шаблону
$arResult["order"]["id"] = $this->getOrderNumber($orderID);

6) Добавлен метод, который вернет на Яндекс.Маркет номер заказа на вашем сайте (ID заказа или Код-заказа)
protected function getOrderNumber($orderId)

Дополнительно

Еще на сайте загружены местоположения 2.0 , делал я это в прошлом 2015 году, помню была проблема с Яндекс.Маркетом, неправильно Битрикс искал местоположения и Яндекс.Маркет сообщал об ошибке, вот где я это делал уже не помню, я добавил на всякий случай в архив файл ym_location.php если найдете, сообщите пожалуйста, я дополню статью этим моментом.

Заключение

При оформлении заказа на Яндекс.Маркете покупатель будет видеть список доставок в таком виде, их возвращает ваш магазин.

Файлы используемые в статье, все разложено по папочкам, где найти какой файл будет несложно.

Что еще почитать