Документация

Документация

Архитектура системы

Используемые технологии
Php7.1
MariaDb
RabbitMQ + supervisord
Yii1 \ Yii2

Интеграция с поставщиками
Push - интеграция при помощи REST API zelenka. В этом случае поставщик реализует взаимодействие на своей стороне
Pull - в этом случае интеграция реализуется на стороне zelenka

Данные обмена
География
Точки продаж
Номенклатура
Остатки по каждой точки продаж
Создание заказа
Получение статусов заказа
Отмена заказа
Документация: https://zelenka.ru/page/api_docs

Технические замечания
RabbitMQ используется при обновлении цен и остатков для обеспечения равномерной нагрузки
Скорость обработки данных определяется оптимизацией алгоритма, оптимизацией работы с БД и количеством обработчиков
Отдельное требование по обновлению остатков: интервал обновления 20 минут

Средства разработки, платформы, СУБД:

PHP 7.1, Yii 1/2, MySQL
MariaDb
HTML5
javaScript (jQuery, Bootstrap)
Git workflow
RabbitMQ + supervisord
мобильная разработка (android, ios, hybrid)
 

Год внедрения в промышленную эксплуатацию 2019

 Собственная разработка ООО "ВиртуалСервис"



 

Документация для подключения к сервису https://zelenka.ru/page/api_docs

 

В системе реализован программный интерфейс для получения и добавления данных о Заказах. Данные выгружаются по http протоколу. Формат на выбор - xml или json.
 

Используемые статусы

200 OK — это ответ на успешные GET, PUT, PATCH или DELETE. Этот код также используется для POST, который не приводит к созданию.
201 Created — этот код состояния является ответом на POST, который приводит к созданию.
204 Нет содержимого. Это ответ на успешный запрос, который не будет возвращать тело (например, запрос DELETE)
400 Bad Request — этот код состояния указывает, что запрос искажен, например, если тело не может быть проанализировано либо ошибка в параметрах запроса.
401 Unauthorized — Если не указаны или недействительны данные аутентификации.
404 Not found — если запрашивается несуществующий ресурс

Отличия в работе тестового и рабочего серверов

Тестовый сервер возвращает ответы описанные в документации. Используя эти ответы можно понять что происходит, успешно ли обработан запрос и т.п.
Рабочий сервер возвращает пустой ответ с кодом 200, т.к. все данные он сразу передает серверу обработки очередей. Обработка производится в отложенном режиме, результаты могут быть присланы по почте, если это включено в настройках.

Адрес тестового окружения - http://api.prot.zelenka.ru

1.     Аутентификация

Аутентификация основана на протоколе OAuth 2.0.

Предварительным запросом получается access_token. Который необходимо потом передавать как BearerToken в заголовке последующих запросов.

Например, первичный запрос токена:

Производится по адресу https://api.zelenka.ru/auth/login методом POST

POST  api.zelenka.ru/auth/login
Content-Type: application/json
{
    "username": "user123",
    "apikey": "key123"
}

Ответ:

{
    "access_token": "6755a48baaf6ee374f4ef55e07bbd2a9",
    "token_type": "bearer",
    "expires_in": 86400,
    "refresh_token": "99afa0362e5c579ecaf4e2621bf1ef69"
}

В последующих запросах выданный access_token необходимо передавать в заголовке как BearerToken.
Срок жизни выданного токена составляет 86400 секунд - значение поля expires_in.

После истечения срока действия access_token, его нужно обновить. Обновление производится с помощью refresh_token, срок действия которого 1 месяц.

POST  api.zelenka.ru/auth/refresh
Content-Type: application/json
{
    "refresh_token": "a36763c8e8473004841ed9f691166de4"
}

Ответ:

{
    "access_token": "ab475c1471c2d6342f2f620d6fb59838",
    "token_type": "bearer",
    "expires_in": 86400
}

При использовании устаревшего refresh_token будет выдана ошибка 401 Refresh token not found or expired.

2.     Item - Товары

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

Пакетная загрузка цен

Данные для добавления передаются в теле POST запроса в формате JSON.
Регион необходимо указывать параметром location_id.

Пример запроса:

POST /item/batch-update?location_id=1
HTTP/1.1
HOST: api.zelenka.ru
[
    {"id": "ЦБ-001123311", "name": "Azitrol 50ml", "price": "82.11", "price_min": "78.1", "manufacturer_name": "ПерваяФабрика", "barcode": "5646233"},
    {"id": "ЦБ-001123314", "name": "Azitrol 50ml", "price": "85.11", "price_min": "78.4", "manufacturer_name": "ПерваяФабрика", "barcode": "56462333"},
    {"id": "ЦБ-001123315", "name": "Azitrol 50ml", "price": "", "price_min": "78.5", "manufacturer_name": "ПерваяФабрика", "barcode": "56462334"}
]

Ответ сервера

{
    "success": 5,
    "errors": []
}

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

Пример запроса на одиночное обновление данных

POST /item/update
HTTP/1.1
HOST: api.zelenka.ru
{
  id: 21,
  name: "Азитрол капс.50мг",
  barcode: 23426546,
  price: 224.12,
  price_min: 220.00
}

Параметры запроса

id - код товара

name - название товара

manufacturer_name Название производителя

barcode - ш/код производителя через запятую

price – цена продажи для сайта

price_min - минимальная цена продажи

Ответ сервера

При успешном добавлении ответ возвращается с кодом статуса 201.

{
    "id": "21",
    "name": "Азитрол капс.50мг",
    "manufacturer_name": "",
    "barcode": "23426546",
    "price": "224.12",
    "price_min": "220.00"
}

3. Warehouse - Точки продаж

Пример запроса на добавление данных

POST /warehouse/update
HTTP/1.1
HOST: api.zelenka.ru
{
    "id": "341",
    "name": "Аптека1",
    "brand": "Бренд1",
    "location_id": 78,
    "address": "г. Санкт-Петербург, ул.Маршала Казакова, д.11",
    "phone": "8 (812) 000-11-22",
    "worktime": "Пн-Пт 8:00-20:00; Сб-Вс 10:00-18:00",
    "notify_order_email": "email_for_notify@your_domain.ru",
    "flag24hours": 1,
    "organisation": {
        "inn": "123456",
        "name": "ООО Здоровья всем"
    },
    "on_request": 0,
    "is_deleted": 0
}

Параметры запроса

id - идентификатор. При запросе производится проверка есть ли уже точка у этого контрагента с данным идентификатором, если нет то создается, если есть то данные обновляются.
name - название точки продаж (должно быть уникально для контрагента)
brand - бренд, торговое название аптечной сети/аптеки (название на вывеске)
location_id - обязательный параметр - код города/региона (78 - Санкт-Петербург)
address - адрес точки продаж
phone - телефон точки продаж
worktime - время работы. Если время работы имеет много вариантов, то предпочтителен следующий формат:
"Пн-Пт 8:00-20:00; Сб 10:00-18:00; Вс 12:00-18:00". В местах с ограниченной шириной будет производиться перенос по знаку ";" точка с запятой.
notify_order_email - email для уведомлений, если заполнен то будут приходить письма-уведомления о заказах. Можно указать несколько email, разделите запятая или точка с запятой. Например email_for_notify@your_domain.ru; second_notify@your_domain.ru.
flag24hours - признак круглосуточной работы.
organisation - информация о юридическом лице. Для объекта organisation поля inn и name обязательны. Необязательно для заполнения. 
on_request - точка продаж работает под запрос с главного склада. Значение 1 = точка «под заказ» со склада включена, Значение 0 = точка «под заказ» со склада выключена.
is_deleted - флаг обозначающий что данная точка выключена для отображения на сайте. Значение = 1 точка выключена, по умолчанию или значение = 0 точка включена

Обязательные поля

id
location_id

Ответ сервера

При успешном добавлении ответ возвращается с кодом статуса 201, при обновлении 200.

В случае если передается точка продаж с флагом is_deleted и на стороне Зеленки ее нет, код ответа будет 208 Already Reported. Удаленные точки не создаются, но если точка существует, устанавливается флаг удаления.

В теле ответа массив параметров точки продаж.

{
    "id": 44,
    "name": "NewWarehouse",
    "location_id": 78,
    "address": "Невский, 1",
    "phone": "88123121212",
    "worktime": "8:00 - 22:00",
    "flag24hours": 1,
    "organisation": {
        "inn": "123456",
        "name": "ООО Здоровья всем"
    },
    "on_request": 0
}

 

Возможные коды ошибок

409: Duplicate entity with name: {name} (id: {id}) - в случае добавления точки продаж с дубликатом названия.

 

4. Onhand - Остатки

Пакетное добавление/обновление информации по остаткам

Пример запроса

POST /onhand/batch-update
HTTP/1.1
HOST: api.zelenka.ru
[
    {"id": "ЦБ-00004897", "warehouse_id": 341, "quantity": 8.1},
    {"id": "ЦБ-00004898", "warehouse_id": 341, "quantity": 12},
    {"id": "ЦБ-00004899", "warehouse_id": 3411, "quantity": 0.00}
]

Параметры запроса

Информация принимается в теле запроса в формате JSON. Ограничение на размер тела запроса 16 мегабайт.

Каждый элемент передаваемого массива должен содержать следующие элементы:
id - идентификатор товара
warehouse_id - идентификатор точки продаж
quantity - количество (приводится к целому)

Ответ сервера

В ответе содержится информация:

success - о количестве успешно обновленных/добавленных записей об остатках
errors - массив с ошибками по неуспешно обновленным записям

{
    "success": 2,
    "errors": {
        "ЦБ-00004899": "Warehouse not found"
    }
}

Обработка полных остатков

В соответствии с регламентом, раз в сутки необходимо передавать остатки по всем товарам по точке продаж. Для запроса такого типа необходимо указать GET параметр isfull=1.

Пример запроса

POST /onhand/batch-update?isfull=1
HTTP/1.1
HOST: api.zelenka.ru
[
    {"id": "ЦБ-00004897", "warehouse_id": 341, "quantity": 8.1},
    {"id": "ЦБ-00004898", "warehouse_id": 341, "quantity": 12},
    {"id": "ЦБ-00004899", "warehouse_id": 342, "quantity": 3.00}
    {"id": "ЦБ-00004897", "warehouse_id": 342, "quantity": 90.00}
    ...... остатки по всем товарам точек продаж 341, 342  ...... 

]

 

Добавление/обновление информации по одному товару

POST /onhand/update
HTTP/1.1
HOST: api.zelenka.ru
{
  "id": 7,
  "warehouse_id": 123,
  "quantity": 8.1
}

Параметры запроса

Информация принимается в теле запроса в формате JSON.

id - обязательный параметр - идентификатор товара.
warehouse_id - идентификатор точки продаж
quantity - количество (приводится к целому)

Ответ сервера

При успешном добавлении ответ возвращается с кодом статуса 201, при обновлении 200.

В теле ответа переданные параметры и количество которое было принято.

{
    "id": 44,
    "warehouse_id": "341",
    "quantity": 8
}

 
5.     Order - Заказы

 

Статусы заказов

1 - Новый
2 - Собран, готов к выдаче
3 - Получен, выдан
4 - Завершен
5 - Отменен
7 - Принят в работу
9 - Ожидает отмены (отмена инициирована клиентом)
10 - Отменён клиентом

Статус оплаты заказа

0 - не оплачен
1 - оплачен

Обновление заказа:

Пример запроса на обновление данных:

POST /order/update
HTTP/1.1
HOST: api.zelenka.ru

{
    "id": 123,
    "status": 2,
    "is_paid": 1,
    "guid": "12345",
    "items": [
        {
            "id": "ЦБ-00031525",
            "quantity": 2,
            "price": 120
        },
        {
            "id": "ЦБ-00031524",
            "quantity": 1,
            "price": 252
        }
    ],
    "fiscal_datetime": "18.01.01 12:00",
    "fiscal_number": "123123",
    "fiscal_doc": "123123",
    "fiscal_attribute": "12341234"
}

Параметры:

id (обязателен) - идентификатор заказа;
status - статуст заказа;
is_paid - признак того что заказ оплачен;
guid - номер заказа в системе контрагента
items - элементы заказа:

item_id - идентификатор товара;
quantity - количество товара;
price - цена продажи;

Дополнительно для заказов статуса 4 –выполнен:

fiscal_datetime – дата и время чека по ККТ в формате ГГ.ММ.ДД ЧЧ:ММ
fiscal_number – номер фискального накопителя (16-значное число)
fiscal_doc – номер фискального документа (10-значное число)
fiscal_attribute – фискальный признак документа (10-значное число)

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

{
    "id": 123,
    "status": 2,
    "is_paid": 1
}

 

 При попытке сменить статус на недопустимый будет возвращена ошибка.

Получение информации о последних заказах

Пример запроса:

POST /order/list
HTTP/1.1
HOST: api.zelenka.ru
{
  "check_from": "2018-12-01 10:11:12",
  “check_by”: “created”,
  "warehouse_id": 555
}

 Параметры запроса:

check_from (обязательный) - дата и время последнего успешного получения заказов.
check_by - определяет чем является check_from датой создания или датой обновления заказа. Принимает два значения: created (по-умолчанию), updated
warehouse_id - код точки продаж, если не указан, то по всем точкам.
fields - дополнительная информация по заказу и элементам заказа. В настоящий момент может принимать значение: barcodes

Пример ответа:

{
  "check": "2018-12-04 12:41:20",
  "check_by": "created",
  "orders": [
    {
      "id": 451,
      "user_name": "Тест",
      "user_phone": "79219613944",
      "warehouse_id": "555",
      "created_at": "2018-11-27 15:52:20",
      "status": 1,
      "is_paid": 0,
      "promocode": null,
      "items": [
        {
          "id": 456456,
          "quantity": "2.000",
          "price": "1062.00",
          "amount": "2124.00"
        }
      ]
    }
  ]
}

Ответ содержит:

check - метка времени, на какой момент произведена выгрузка заказов. Рекомендуется её сохранять и использовать при следующем запросе.
check_by - с каким значением использовалось поле check. См. описание запроса выше.
orders - массив заказов

id - идентификатор заказа
user_name - ФИО клиента
user_phone - телефон клиента
warehouse_id - код точки продаж
created_at - дата создания заказа
status - статус заказа (коды статусов указаны в начале)
is_paid - признак оплаты заказа
promocode - промокод, если он был применён
items - элементы заказа

id - идентификатор товара
name - название товара, выводится при отсутствии сопоставления 
barcodes - штрихкоды товара, выводятся при отсутствии сопоставления
manufacturer - производитель, выводится при отсутствии сопоставления
quantity - количество
price - цена
amount - сумма

Ответ содержит максимум 100 заказов.

Обработка отмены заказа пользователем

1. При получении списка заказов отобрать заказы со статусом 9 (отмена инициирована пользователем)
2. Отменить заказ у себя в системе
3. Прислать изменения по статусу заказа (статус 10). Запрос Обновление заказа.

 

Договор

 Шаблон договора находится здесь

Базовая комиссия составляет 6% от суммы выкупленных заказов.
Все скидки, которые транслируются покупателям со стороны платформы компенсируются по итогам расчетного периода.