FTP catalog + REST API
FTP Catalog
Раздел технического описания механизма работы процесса загрузки и синхронизации каталога через протокол FTP, посредством загрузки определенных файлов в директории на ftp сервере. У Ютеки есть ftp сервер, но так же можем использовать сервер партнера.
Технические детали перед началом
Мы можем обрабатывать следующие форматы файлов: CSV
(приоритетнее), JSON
, XML
.
Файлы должны быть в кодировке UTF-8 (промышленный стандарт) или, в крайнем случае, windows-1251.
Если вы рассматриваете формат CSV, просим обратить внимание на его корректное формирование для выгрузок аптек и товаров.
А в частности, на формирование строк содержащих спецсимволы: '
"
;
,
.
Особенно это актуально для наименований товаров, адресов и названий аптек, так как они могут содержать эти символы.
Правильные варианты смотри в примерах к файлам.
Аптеки
В корень ftp выгружается файл pharmacies.<формат>
, где расширение соответствует формату выгрузки.
Ютека загружает аптеки раз в 3 часа. Партнеру рекомендуется выгружать с такой же периодичностью.
Новые файлы выгружаются поверх старых, перезаписывая их.
Поле | Обязательное | Описание | Комментарий |
---|---|---|---|
pharmacyId |
уникальный идентификатор аптеки | По нему будет отправляться заказ в аптеку | |
title |
Название аптеки | ||
region |
ID Региона аптеки | Не обязателен, если аптеки Партнера представлены только в одном регионе | |
address |
Адрес | С точностью до дома. Если возможно, без дополнительных комментариев, вида пом.75843б, за магазином канцтоваров |
|
phone |
Телефон | В международном формате (+71234567890 ). Если это городской номер телефона, то с кодом города (например для Новосибирска это +7(383)000‒00‒00 ) |
|
workingHours |
Часы работы в формате | ||
location |
GPS координаты Latitude,Longitude |
Например, 59.939032,30.315826 . При подстановке в гугл/яндекс/другие карты должна показываться точка на аптеку. По координатам проверяется адрес, если он не точен |
|
email |
Email аптеки для связи | Мы можем присылать email оповещения в аптеку при поступлении новых или отмене заказов |
Товары
В корень ftp выгружается файл products.<формат>
, где расширение соответствует формату выгрузки.
Ютека загружает товары раз в 3 часа. Партнеру рекомендуется выгружать с такой же периодичностью.
Новые файлы выгружаются поверх старых, перезаписывая их.
Поле | Обязательное | Описание |
---|---|---|
productId |
уникальный идентификатор товара в аптечной сети. | |
barcode |
Штрихкод | |
title |
Название | |
vendor |
Производитель | |
country |
Страна | |
egk |
ЕГК код товара, если такой известен | |
rls |
RLS код товара, если такой известен | |
katren |
Katren код товара, если такой известен |
Остатки
Ютека загружает остатки раз в 15 минут. Партнеру рекомендуется выгружать с такой же периодичностью.
Остатки выгружаются по-аптечно в директорию /stocks
в файлы с именем stocks_<аптека>.<формат>
, где суффикс названия соответствует ID аптеки.
Ожидаемые поля в файлах остатков:
Поле | Обязательное | Описание |
---|---|---|
productId |
ID товара из выгрузки Товаров | |
pharmacyId |
ID аптеки из выгрузки Аптек | |
price |
Цена | |
quantity |
Остаток | |
partNumber |
Партия | |
expirationDate |
Срок годности в формате ДД.ММ.ГГГГ (например 31.12.2020) |
REST API заказов
Этот раздел описывает процесс интеграции Ютеки и Партнера через реализацию на стороне Партнера HTTP REST интерфейса для обработки заказов.
Хоть и реализация интерфейса кладется на плечи Партнера, взаимодействие является двусторонним: Ютека отправляет новые заказы и отмены заказов Партнеру, а Партнер отправляет Ютеке информацию об изменении статуса.
Список используемых методов
Интерфейс Партнёра:
Интерфейс Ютеки:
АПИ и механики работы
В этом разделе описаны технические моменты реализации АПИ и механики работы.
Формат работы АПИ - JSON
. HTTP методы, используемые в запросах: POST
.
Авторизация
Во время начала интегрирования, Ютека и Партнёр договариваются о способе авторизации и аутентификации друг друга. Это нужно, что бы исключить возможность третьих лиц делать ложные заказы или присылать неправильные статусы. Поэтому Партнёр, при реализации АПИ должен добавить проверку запросов на ключ авторизации.
Пусть, далее в документации, ключ доступа будет hee7vaisahchu4O
(случайная строка, не пытайтесь делать с ней запросы).
Ютека может авторизировать запросы способами:
- Basic Auth авторизация.
Партнёр закрывает HTTP endpoint при помощи Basic Auth, а Ютека добавляет к запросам логин и пароль доступа. Authorization
заголовок.
Ютека и Партнёр добавляют к своим запросам заголовок с секретным токеном. В HTTP запросе будет заголовок видаAuthorization: hee7vaisahchu4O
- JSON поле в теле запроса.
Ютека и Партнёр добавляют к телу запроса полеtoken
. Тогда, минимальное тело запроса будет{"token": "hee7vaisahchu4O"}
Работа с ошибками
За успешность выполнения запроса отвечает HTTP Status Code ответа. При успешном выполнении запроса, АПИ должно возвращать код 200 OK.
Если по какой-либо причине запрос выполнился неудачно, АПИ не должно возвращать 200 ОК.
В теле отведа должно быть описание ошибки в поле error
:
{
"error": "Ошибка установки соединения с базой данных"
}
А код ответа должен быть одиним из:
- 403 - Ошибка авторизации, токен или пара логин/пароль не совпали.
- 400 - В запросе неверные данные. Например, неправильный JSON формат тела запроса.
- 500 - Остальные ошибки. Недоступность сервера, отказ базы данных и др.
Номера заказов
При начале интеграции Партнёр и Ютека договариваются, чей номер заказа показывать клиенту на сайте Ютеки и по этому же номеру клиент будет забирать заказ в аптеке.
В случае, если Партнёр хочет использовать свои номера заказов,
то в ответе метода Создания заказа,
в поле partnerOrderId
нужно присылать номер заказа в системе Партнёра.
Во всех методах (кроме создания заказа) Ютека посылает оба номера utekaOrderId
и partnerOrderId
и гарантирует, что они соответствуют друг другу.
Поля partnerOrderId
и utekaOrderId
всегда должны быть JSON String.
Создание заказа
При появлении нового заказа от клиента на сайте Ютеки, делается запрос на подготовленный URL Партнёра в котором будет данные по заказу и контакты клиента.
{
"utekaOrderId": "123",
"pharmacyId": "1234",
"items":[
{
"productId": "60001090",
"quantity": 2,
"price": 880
},
{
"productId": "60001040",
"quantity": 1,
"price": 73000
}
],
"amount": 74760,
"name": "Кирилл",
"phone": "9997651151"
}
Параметр | JSON Тип | Описание |
---|---|---|
utekaOrderId |
String | Номер заказа в сервисе Ютеки. (*) |
pharmacyId |
String | ID аптеки Партнера |
items |
Array | Список позиций заказа. Каждый элемент имеет уникальный productId (т.е. позиции не повторяются) |
items .productId |
String | Идентификатор товара Партнёра |
items .quantity |
Number (целочисленный) | Количество позиции товара в заказе. Дробные числа не поддерживаются. |
items .price |
Number | Цена товара в рублях. Может содержать дробную часть - копейки. |
amount |
Number | Общая сумма заказа. Может содержать дробную часть - копейки. |
name |
String | Имя/Фамилия/Псевдоним пользователя под которым он будет забирать заказ. |
phone |
String | Номер телефона клиента в формате 9001112233 (без +7 или 8) |
(*) Используется как ключ идемпотентности.
При успешном получении нового заказа, Партнёр ответить на HTTP запрос статусом 200.
В ответе АПИ должно вернуть оба ID заказа: и Партнера, и Ютеки.
{
"partnerOrderId": "textAndNumbers12345",
"utekaOrderId": "99"
}
Это используется для доп. валидации, что заказ принят.
Если Партнер, по каким-то причинам, не может присылать свой идентификатор, он может вернуть в partnerOrderId
номер заказа Ютеки.
Переотправка заказов (повторные запросы)
Ютека может послать запросы с одним и тем же utekaOrderId
.
В случае, если на стороне партнера уже есть заказ с этим номером Ютеки, то не нужно создавать новый,
а нужно вернуть данные уже созданного заказа.
Повторный запрос может быть, например отправлен в случае переотправки заказа из-за технических проблем и для избавления от дублирования.
Проверка статуса
Периодически Ютека опрашивает АПИ партнера о текущем статусе заказа. Ютека делает запрос вида:
{
"orderIds": [
{"partnerOrderId": "4567", "utekaOrderId": "123"},
{"partnerOrderId": "xxxx", "utekaOrderId": "4568"},
{"partnerOrderId": "4569", "utekaOrderId": "2"}
]
}
и ожидает в ответ JSON массив из текущих статусов заказов.
[
{
"utekaOrderId": "4567",
"partnerOrderId": "utk-123",
"status": "cancelled"
},
{
"utekaOrderId": "4568",
"partnerOrderId": "utk-17",
"status": "approved"
},
{
"utekaOrderId": "4569",
"partnerOrderId": "utk-utk",
"status": "ready"
}
]
Возможные статусы заказа
approved
- подтвержден. Новый заказ был обработан системой и/или заказ собирается.ready
- готов к выдаче. Заказ укомплектован и клиент может идти забирать его из аптеки.cancelled_by_pharmacy
- отменен аптекой. В случае, когда аптека не может выполнить этот заказ. Например, неактуальные остатки или разница в цене в аптеке и в заказе.completed
- выполнен. Клиент успешно забрал/выкупил заказ.cancelled
- отменен клиентом. Ютека присылает этот статус в методе отмены заказа.
Все другие возможные внутренние статусы (например, Отгружено, Аннулирован, Требуется подтверждение аптекой или любые другие) Партнер должен максимально точно сконвертировать в один статусов выше. Диаграмма ниже описывает общий флоу заказов.
graph LR approved[Подтвержден approved] ready[Готов к выдаче ready] cancelled_by_pharmacy[Отменен аптекой cancelled_by_pharmacy] completed[Выполнен completed] cancelled[Отменен клиентом cancelled] endst((Конечный статус)) newOrder((Новый заказ)) clientCancel((Клиент отменяет заказ)) uteka(Ютека) uteka1(Ютека) newOrder-->uteka uteka-->approved approved--Все позиции заказа собраны-->ready approved--Невозможно собрать заказ-->cancelled_by_pharmacy ready--Клиент не забрал заказ-->cancelled_by_pharmacy ready--Клиент выкупил заказ-->completed clientCancel-->uteka1 uteka1-->cancelled cancelled_by_pharmacy-->endst completed-->endst cancelled-->endst style uteka fill:#68e472,stroke:#008012 style uteka1 fill:#68e472,stroke:#008012
Отмена заказа клиентом
Когда клиент отменяет заказ на сайте Ютеки, Партнёру отправляется запрос с телом
{
"utekaOrderId": "4567",
"partnerOrderId": "xxx",
"status": "cancelled"
}
И ожидается ответ с текущим статусом заказа (должен быть cancelled
если отмена прошла успешно), как при запросе статуса:
{
"utekaOrderId": "4567",
"partnerOrderId": "xxx",
"status": "cancelled"
}
Обратите внимание, что при отмене заказа Партнёром (в том числе и на стороне аптеки), Партнёр посылает статус cancelled_by_pharmacy
,
а когда клиент отменяет заказ, то Ютека посылает статус cancelled
.
Обновление статуса заказа
URL: https://example.com/srv/ordersrv/api/orders/status
Партнер посылает следующий запрос, когда изменяется статус заказа.
Параметры запроса:
Параметр | JSON Тип | Обязательное | Описание | Пример |
---|---|---|---|---|
utekaOrderId |
String (и содержит целочисленное число) | Да | Номер заказа в сервисе Ютеки. Передается в запросе создания заказа, в ответе на запрос создания заказа | {"utekaOrderId": "333591"} |
partnerOrderId |
String | Да | Номер заказа в сервисе Партнера. Передается в ответе на запрос создания заказа | {"partnerOrderId": "000-5323.ff12"} |
status |
String | Да | Должен принимать одно из возможных значений. См. Возможные статусы заказа | {"status": "ready"} |