Найти в Дзене
Ellefra

Подробное описание интеграции АПИ Яндекс.Доставки

Оглавление

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

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

Работа с Яндекс.Доставкой
Работа с Яндекс.Доставкой

Создание заявки

Получение вариантов доставки (офферов) для переданного заказа.

b2b.taxi.tst.yandex.net/api/b2b/platform/offers/create

Исходником стал xlsx-файл, который подходит также и для загрузки в Озон.Доставку. С одним отличием: В случае доставки до ПВЗ Яндексу требуется напрямую указать "Идентификатор станции в Логистической платформе (например, склад отгрузки или ПВЗ)". Это поле destination.platform_station.platform_id. С определением, откуда же его можно взять, пришлось немало повозиться, потому что ни по работе с Яндекс.Маркетом, ни в реестре ПВЗ, который предоставил Яндекс, такого кода не обнаружилось. Выглядит он как уникальный 1С-ный код, например, "5ee634be-60d0-43c8-9076-4ddf23de551h". Надо отдать должное, ребята быстро справились с предоставлением такой информации заказчику. Позже они появились и в АПИ: Получение списка точек самопривоза и ПВЗ, HTTP-запрос POST b2b.taxi.tst.yandex.net/api/b2b/platform/pickup-points/list

Так это выглядит в программе Postman
Так это выглядит в программе Postman

Очень важно все числовые значения приводить к числовому виду, строковые - к строковому. Многомерные массивы должны быть именно массивами, даже если там всего 1 элемент (items и places).

Размеры указываются в см, объем в см3, а вес - в граммах.

По каждому заказу в php создаем массив с такими элементами:

billing_info.delivery_cost - Сумма которую нужно взять с получателя за доставку. Так описывает Яндекс это поле, но больше нигде не было найдено поля, в котором бы указывалась сумма, которую должен клиент заплатить в случае наложенного платежа. Здесь же, полную стоимость заказа указывать не стоит. Если не было предоплаты, сумму, которую надо взять с получателя, Яндекс рассчитывает по стоимости товаров. Возможность частичной оплаты подключается при заключении договора. Но можно обойтись и без этого, если стоимость товара указать за вычетом суммы предоплаты.

billing_info.payment_method - метод оплаты "cash_on_receipt" - наличными при получении.

Если была предоплата, то мы delivery_cost не указываем, а payment_method будет "already_paid". Конечно, в случае наличия других вариантов, можно указывать и другие значения.

destination - формируем адрес доставки

destination.type* - Тип целевой точки. Для доставки до двери он равен 2, для доставки до ПВЗ - 1.

Для доставки до двери добавляем такие элементы:

destination.custom_location - Информация о произвольной точке. Точка может быть задана либо своими координатами - пара (latitude, longitude), либо адресом.

destination.custom_location.details.comment - Комментарий, если нужен.

Если адрес, то:

destination.custom_location.details.full_address - Полный адрес. Учтите, что во избежание ошибок из этого поля требуется убрать индекс, а номер квартиры писать отдельно в поле:

destination.custom_location.details.room - Номер квартиры или офиса

Если координаты, то:

destination.custom_location.latitude - Широта.

destination.custom_location.longitude - Долгота.

Для доставки до ПВЗ добавляется тот самый дополнительный код:

destination.platform_station.platform_id - Идентификатор станции в Логистической платформе (например, склад отгрузки или ПВЗ).

Далее добавляем общий элемент "интервал доставки", он рассчитывается от момента создания заявки до момента доставки клиенту. Интервал необходимо передавать либо в UTC, либо в UNIX timestamp.

Здесь также есть небольшие подводные камни. На тестовом сайте для бронирования подходили любые варианты интервалов. А в боевом режиме возникли проблемы с ошибкой "cannot build user request". Все дело оказалось в том, что при любых вариантах заказов интервал не может составлять более 5 дней. Правда, есть и исключения, в зависимости от условий заказа. Поэтому, мы отказались от указания интервалов и получаем просто ближайшие возможные варианты.

Если UNIX timestamp, то:

destination.interval - При доставке до пункта выдачи, необходимо указывать только дату.

destination.interval.from - UNIX timestamp для нижней границы интервала

destination.interval.to - UNIX timetamp для верхней границы интервала

Если UTC timestamp, то:

destination.interval_utc - Интервал необходимо передавать либо в UTC, либо в UNIX timestamp. При доставке до пункта выдачи, необходимо указывать только дату

destination.interval_utc.from - UTC timestamp для нижней границы интервала

destination.interval_utc.to - UTC timetamp для верхней границы интервала

Самый важный обязательный элемент - информация о заказе info *:

info.comment - Опциональный комментарий.

info.operator_request_id * - Идентификатор заказа у отправителя.

Информация о предметах в заказе, items[].

Здесь необходимо обратить внимание на то, как вы упаковываете свои товары. Возможно, несколько одинаковых товаров, или несколько разных товаров упакуете в одну коробку. Тогда для них должен быть один элемент places и элементы items для каждого наименования с нужным количеством. И четко укажите штрихкод коробки.

items[].article * - Артикул

items[].billing_details.assessed_unit_price * - Оценная цена за единицу товара (передается в копейках)

items[].billing_details.nds - Код НДС. Дефолтное значение 20%.

items[].billing_details.unit_price * - Цена за единицу товара (передается в копейках)

items[].count * - Количество

items[].name * - Название

items[].place_barcode * - Штрихкод коробки, к которой относится товар.

items[].physical_dims - Указываются либо габариты (dx, dy, dz), либо Объем в см3 (predefined_volume).

Наш клиент предпочел для каждой единицы товара делать отдельную коробку. В таком случае к стандартному штрихкоду добавляем последовательную нумерацию "-1", "-2" и т.д. Получается, что если в заказе 2 наименования товара по 2 штуки, то сформируем 4 элемента items и 4 элемента places.

Здесь возникла одна из проблем при тестировании. При отправке такого заказа из 4 позиций на тестовый сервер, получали ответ "service unavailable", сервис недоступен. Хотя одиночные заказы отправлялись. После обращения в поддержку проблема была исправлена.

Информация о местах в заказе places[] *

places[].barcode * - Штрихкод коробки. Именно его указываем в items[].place_barcode. Формирует его заказчик так, как ему удобно. Например, префикс, номер заказа и номер отправления, если их несколько.

places[].physical_dims * - Указываются либо габариты (dx, dy, dz), либо Объем в см3 (predefined_volume).

places[].physical_dims.weight_gross * - Вес брутто, граммы. Обратите внимание, что вес указывается только у конечного места, отдельно у товаров не нужно.

Информация о заказчике recipient_info *

recipient_info.first_name * - Имя. У меня из всей информации было только одно поле с именем и фамилией, и телефон. Поэтому я указывала только обязательные поля.

recipient_info.phone * - Номер телефона

Источник source *

source.platform_station.platform_id - Идентификатор станции в Логистической платформе (например, склад отгрузки или ПВЗ). Это и есть тот код, который мы ждали, чтобы получить. Яндекс довольно быстро прислал реестр своих точек с этим кодом, его надо было загрузить в лк Я.Доставки. Планировалось, что когда в 1С приходит новый ПВЗ, в этот момент бухгалтерия его сохраняет к себе и может отправлять нам вместе с заказом для доставки.

Полученный массив кодируем в json с помощью функции json_encode().

Далее с помощью curl отправляем его на указанный выше тестовый адрес методом POST. Не забываем в заголовке указать правильную авторизацию с токеном.

В следующей статье напишу, что будем делать дальше.