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 нужно присылать номер заказа в системе Партнёра.

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

При появлении нового заказа от клиента на сайте Ютеки, делается запрос на подготовленный 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.

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

{
  "partnerOrderId": "textAndNumbers12345",
  "utekaOrderId": "99"
}

Проверка статуса

Периодически Ютека опрашивает АПИ партнера о текущем статусе заказа. Ютека делает запрос вида:

{
    "orderIds": [
      {"partnerOrderId": "4567", "utekaOrderId": "123"},
      {"partnerOrderId": "xxxx", "utekaOrderId": "4568"},
      {"partnerOrderId": "4569", "utekaOrderId": "2"}
    ]
}

и ожидает в ответ JSON массив из текущих статусов заказов.

[
    {
      "utekaOrderId": "4567",
      "partnerOrderId": "xxx",
      "status": "cancelled"
     },
    {
      "utekaOrderId": "4568",
      "partnerOrderId": "xxxx",
      "status": "approved"
     },
    {
      "utekaOrderId": "4569",
      "partnerOrderId": "xxxxx",
      "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_by_pharmacy, а когда клиент отменяет заказ, то Ютека посылает статус cancelled.

В ответ на отмену заказа сервер должен ответить текущим статусом заказа (так как мы отменяем заказ, в ответе всегда должно быть cancelled):

    {
      "utekaOrderId": "4569",
      "partnerOrderId": "xxxxx",
      "status": "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"}
comment String Да, если "status": "cancelled_by_pharmacy" Причина отмены заказа со стороны аптеки. {"comment": ""}
cart Array Список элементов корзины в которых есть несовпадение {"cart": [{"productId": "12345", "quantity": 2, "price": 123.45}, {"productId": "12345", "quantity": 1, "price": 12}]}
cart.productId String Да Идентификатор товара Партнёра {"productId": "12345"}
cart.quantity Number (целочисленный) Да Количество товаров. Дробные числа не поддерживаются. {"quantity": 10}
cart.price Number Да Цена товара в рублях. Может содержать дробную часть - копейки. {"price": 500.12}

Примеры:

Тестовое окружение Ютеки

Тестовое АПИ расположено по адресу https://example.com/srv/ordersrv/api/.

Для того, что бы вызвать конкретный метод, нужно добавить его название к АПИ URL.

Например, если название метода orders/status, а адрес АПИ https://example.com/srv/ordersrv/api/, то запрос нужно будет делать по адресу https://example.com/srv/ordersrv/api/orders/status.

История изменений

[1.0.1] - 17.09.2020

Добавлено

  • Пример ответа и комментарий в методе отмены заказа

[1.0.0] - 10.09.2020

Изменено

  • В объекте создания заказа поле orderId переименовано в utekaOrderId, поле pharmacy переименовано в pharmacyId.
  • Во всех методах, где участвует номер заказа, теперь вместо строки с номером нужно посылать объект с полями utekaOrderId, partnerOrderId: {"utekaOrderId":"1", "partnerOrderId:"xxx"}