Rest API Введение - datawizio/pythonAPI GitHub Wiki

Datawiz Business Intelligent Application Program Interface v.1

Сервис Datawiz BI располагается в сети Интернет и предлагает услуги по анализу ретейл-данных, предоставленных его клиентами. Для успешной работы сервиса необходимо загрузить в него начальные данные (кассовые чеки и некоторые справочники) за сравнительно большой период (год и более), после чего ежедневно пополнять его новыми данными. Именно этим целям и служит Программный интерфейс взаимодействия (сокращенно - API - Application Program Interface) "Datawiz BI API v.1."

Схема взаимодействия программного обеспечения клиента с сервисом Datawiz BI представляет собой классическую схему "Клиент-сервер". Где в роли сервера выступает сервис "Datawiz BI", а в роли клиента - программное обеспечение клиента сервиса. Исходя из этого можно легко представить себе основные елементы взаимодействия этих двух систем:

  1. Клиент обращается к серверу и устанавливает соединение
  2. Клиент отправляет на сервер запрос с данными
  3. Сервер возвращает ответ с данными либо кодом ошибки
  4. Соединение разрывается

Теперь о реализации. Datawiz BI API v.1 построен с использованием технологии [REST] (http://uk.wikipedia.org/wiki/REST), что значительно упрощает процесс взаимодействия клиента и сервера. Давайте в дальнейшем будем именовать Datawiz BI API сокращенно: REST API и ознакомимся с его основными елементами:

Краткое описание REST API:

Ресурсы

REST API для обеспечения взаимодействия сервера и клиента использует стандартный HTTP-протокол. Согласно этому протоколу вся информация, сосредоточенная в сети, называется ресурсами. Каждый такой ресурс имеет свой уникальный унифицированный локатор ресурса (Unified Resource Locator - [URL] (http://uk.wikipedia.org/wiki/URL)) - адрес, с помощью которого можно четко идентифицировать тот или иной ресурс.

Пример ресурса: http://api.datawiz.io/api/v1/ - указывает на корневой элемент REST API v.1 сервиса [datawiz BI] (http://api.datawiz.io)

Как видно, ресурс похож на путь файловой системы, указывающий на объект внутри её. Если внимательно разобрать, то можно увидить: корневой каталог - //; первый уровень - доменное имя (api.datawiz.io); далее следует имя корневого каталога (api) на сервере, следующий уровень - его уточнение (v1) и т.д...

Команды

Взаимодействие клиента и сервера, в терминах HTTP-протокола, начинается отправкой запроса клиентом на сервер. При этом клиент передает на сервер заголовок и тело запроса, в заголовке указывается команда и другие необходимые параметры, в теле запроса направляется объект (в JSON формате), который необходимо добавить или изменить на сервере. В результате взаимодействия клиента с сервером клиент получает ответ сервера (заголовок и тело), в которых сервер передает HTTP-код ответа и данные (в JSON формате). Далее цикл взаимодействия клиента и сервера повторяется.

Для управления ресурсами используется стандартный набор команд HTTP-протокола:

Команда Описание
GET для получения информации с сервера
POST для добавления информации на сервер
PUT для внесения изменений (модификации) информации на сервере
PATCH для выборочного изменения информации (например, не целого объекта, а только отдельных его полей)
DELETE для удаления информации с сервера
OPTIONS получения мета-информации о ресурсе
HEAD аналог GET, только с сервера возвращается один заголовок, без тела

Формат данных

Объекты в теле запроса представляются в определенном формате. Самыми популярными форматами представления структурной информации в REST API являются [JSON] (http://uk.wikipedia.org/wiki/JSON), [XML] (http://uk.wikipedia.org/wiki/XML), [HTML] (http://uk.wikipedia.org/wiki/HTML). Datawiz BI API v.1 использует формат JSON для взаимодействия приложений и HTML для презентационного представления API по адресу: http://api.datawiz.io/api/.

Пример ответа сервера в формате JSON на запрос клиента GET http://api.datawiz.io/api/.json:

{
     "v1": "http://api.datawiz.io/api/v1/", 
     "v2": "not available yet" 
}

Выбор формата данных лежит на клиенте. И сделать это он может несколькими способами (представлено в порядке убывания приоритета):

  1. Формат данных можно указать в виде суффикса URL: .json (JSON) или.api (HTML). См. предыдущий пример.
  2. Формат данных можно указать в виде дополнительного параметра format:?Format=json или ?Format=api. Если одновременно указаны и суффикс и параметр, то предпочтен будет суффикс. Пример: http://api.datawiz.io/api/?Format=api.
  3. Формат данных можно указать в заголовке HTTP Content-Type указав application/json или application/html. Этот способ выбора формата действует только тогда, когда другие способы выбора формата отсутствуют.
  4. По договоренности, если ни один из вышеуказанных способов выбора формата не представлен, выбирается формат JSON.

РЕСУРСЫ REST API:

Ресурсы REST API представлены двумя видами:

  • коллекции
  • объекты

Коллекции

Коллекции - это списки объектов. Коллекции представляются в виде массивов JSON и используются для отправки на сервер или получения с сервера сразу нескольких объектов за один запрос. Завершающий элемент коллекции (endpoint) - это всегда название ресурса.

Пример ресурсов типа "коллекция":

  • /Products/ - получить первые 10 элементов из справочника по товарам либо отправить указанное клиентом колличество товаров на сервер
  • /Receipts/ - получить с сервера первые 10 чеков либо отправить указанное клиентом колличество чеков на сервер
  • /Receipts/1-1_20141120195527_297/cartitems/ - получить список (коллекцию) всех покупок с чека с id=1-1_20141120195527_297

Параметры управления коллекциями, получаемыми с сервера.

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

Таким способом является "пролистывания" коллекций (pagenating). Под "пролистыванием" понимают разбиение коллекции на страницы и выгрузкой за один запрос всего одной такой страницы.

Для управления "пролистыванием" коллекций используются дополнительные параметры URL:

Параметр Помощь
page_size размер страницы. По договоренности, если этот параметр не указан, размер страницы - 10 элементов)
page номер страницы. По договоренности, если этот параметр не указан, выгружаются первые page_size элементов, то есть по договоренности - page = 1.

Структура коллекции

Для легкого управления коллекцией (в том числе, для управления "пролистыванием") каждая коллекция возвращает клиенту JSON-словарь, в котором представлены 4 параметра:

  • Count - общее количество объектов в коллекции
  • Next - указатель (url) на следующую "страницу" данных в коллекции
  • Previous - указатель (url) на предыдущую "страницу" данных в коллекции
  • Results - массив объектов данной страницы. К-во элементов в массиве всегда меньше или равно page_size.

Пример ответа сервера на запрос: "Вернуть коллекцию из 2 записей из справочника по товарам в формате json":

GET http://api.datawiz.io/api/v1/products/?Format=json&page_size=2:

{
     "count": 24880, 
     "next": "http://api.datawiz.io/api/v1/products/?page=2&page_size=2&format=json", 
     "previous": null, 
     "results": [
         {
             "url": "http://api.datawiz.io/api/v1/products/17786/", 
             "product_id": "17786", 
             "name": "\" La Festa \ "Капучино GV 12,5 * 10 * 8шт (нап/раств) (сливки" 
         } 
         {
             "url": "http://api.datawiz.io/api/v1/products/17785/", 
             "product_id": "17785", 
             "name": "\" La Festa \ "Капучино GV 12,5х10х8шт (нап/раств) орех" 
         } 
     ] 
}

Управление коллекциями, отравляемых на сервер

Коллекциями объектов, отправляемые на сервер управляет клиент. Именно он выбирает способ передачи данных на сервер - по-одиночке или списком. Тут нужно принять во внимание следующее: передача данных поодиночке - медленный процесс, и используется тогда, когда необходимо добавить или изменить один-два объекта, тогда как передача списком значительно ускоряет процесс передачи данных на сервер, но усложняет контроль над отдельными объектами. Кроме того нужно помнить, что сервер имеет ограничение на размер передаваемых данных (около 200Кб ~ 2000 объектов), поэтому при необходимости данные на сервер нужно передавать частями.

Объекты

Объекты - это структуры данных, представлены в виде словарей JSON, в которых ключевыми словами (ключами) служат названия полей, а данными - значения этих полей. Поля могут указывать на вложенные структы (словари и массивы), таким образом выстраивается сложная структура объекта. Получить информацию о структуре объекта можно, отправив на сервер запрос OPTIONS. Завершающий элемент объекта (endpoint) - это всегда идентификатор ресурса.

Пример ресурсов типа "объект":

  • /Products/*12345* - взаимодействовать с определенным элементом из справочника по товарам с id = 12345
  • /Receipts/*12345* - получить доступ к чеку с id=12345
  • /Receipts/*12345*/cartitems/*1* - прочитать первую строчку в чеке с id = 12345

Пример ответа сервера на запрос: "Вернуть запись из справочника по товарам с id=77087-24316 в формате json": GET http://api.datawiz.io/api/v1/products/77087-24316/.json:

{
    "url": "http://api.datawiz.io/api/v1/products/77087-24316/", 
    "product_id": "77087-24316", 
    "name": ". баликова н/к 1с. (ш/о/б) вак . (кг)", 
    "category_id": "79", 
    "category_url": "http://api.datawiz.io/api/v1/categories/79/", 
    "unit_id": "3-1-0", 
    "unit_url": "http://api.datawiz.io/api/v1/units/3-1-0/"
}

Если же вместо GET указать OPTIONS, то для вышеуказанного запроса будем иметь описание структуры вышеуказанного запроса:

OPTIONS http://api.datawiz.io/api/v1/products/77087-24316/.json

HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: GET, PUT, DELETE, HEAD, OPTIONS, PATCH
{
    "name": "Product Instance", 
    "description": "Объект 'Товар' предназначен для хранения информации о товаре", 
    "renders": [
        "application/json", 
        "text/html"
    ], 
    "parses": [
        "application/json", 
        "application/x-www-form-urlencoded", 
        "multipart/form-data"
    ], 
    "actions": {
        "PUT": {
            "url": {
                "type": "field", 
                "required": false, 
                "read_only": true
            }, 
            "product_id": {
                "type": "string", 
                "required": true, 
                "read_only": false, 
                "max_length": 100
            }, 
            "name": {
                "type": "string", 
                "required": true, 
                "read_only": false, 
                "label": "name", 
                "max_length": 200
            }, 
            "category_id": {
                "type": "string", 
                "required": true, 
                "read_only": false, 
                "max_length": 100
            }, 
            "category_url": {
                "type": "field", 
                "required": false, 
                "read_only": true
            }, 
            "unit_id": {
                "type": "string", 
                "required": true, 
                "read_only": false, 
                "max_length": 50
            }, 
            "unit_url": {
                "type": "field", 
                "required": false, 
                "read_only": true
            }
        }
    }
}

Описание структуры, предоставленное по запросу OPTIONS позволяет понять, какие данные мы можем получить с сервера, или какие данные необходимо подготовить для внесения изменений на сервере. Например, анализируя параметры required и read_only можно понять, какие поля можно модифицировать и какие из них обязательны к заполнению.

Из вышеуказанного результата команды OPTIONS видно, что для регистрации нового товара в справочнике по товарам небходимо и достаточно заполнить 4 обязательных поля: product_id, name, category_id и unit_id. Как несложно догадаться, поля category_id и unit_id - идентификаторы из справочников "Категории товаров" и "Единицы измерения".

Идентификаторы ресурсов (поле url)

Для надежной идентификации ресурсов и связывания их между собой используются идентификаторы объектов. Идентификаторы объектов представляют собой URL, записанные в поле url. При необходимости загрузить данные из связанного объекта достаточно прочитать содержимое поля url и использовать его в GET-запросе. Поля url являются полями "только для чтения", поэтому при передаче объектов на сервер их заполнять не нужно.

Тестовая площадка

Для лучшего понимания структуры REST API и команд, которые он представляет, можно воспользоваться тестовой площадкой по адресу http://api.datawiz.io/api/. Получить доступ к нему можно, указав имя клиента и пароль, используемые для входа в веб-интерфейс ресурса http://api.datawiz.io

Авторизация доступа

На данный момент REST API поддерживает 2 модели авторизации:

  1. OAuth v2 - с помощью имени и пароля
  2. Авторизации на базе подписи (HTTP Signature Authentication)

Справочник ресурсов REST API

Теперь, давайте ознакомимся с ресурсами REST API. Всего REST API представляет доступ к 8 ресурсам:

  1. Shops - список магазинов клиента (только чтение)
  2. Terminals - список кассовых терминалов для каждого из магазинов
  3. Categories - иерархический список категорий товаров
  4. Units - единицы измерения
  5. Products - номенклатура (список товаров)
  6. Loyalty - программа лояльности
  7. Cashiers - список кассиров
  8. Receipts/Cartitems - чеки

Ресурсы с п.1 по п.7 являются справочниками и необходимы для правильного представление информации из п.8 Чеки.

Все ресурсы связаны друг с другом. Вот краткое описание связей:

  1. Пользователь сервиса (Client) может иметь несколько магазинов (Client->Shops). Но не менее одного. - Связь "Один ко многим"
  2. Магазин (Shop) может иметь несколько кассовых терминалов (Shop->Terminals) . Но не менее одного. - Связь "Один ко многим"
  3. Список категорий товаров (Categories) - иерархическая структура. Иерархия создается с помощью поля parent_id, в которое записывается идентификатор родительской категории. Корневой елемент иерархии один, для которого parent_id не определен (пустой) и содержит в поле "Наименование категории" имя пользователя сервиса (первый уровень иерархии); Категории второго уровня представляют вершину иерархии категорий товаров
  4. Единицы измерения (Units) могут быть целыми (их можно посчитать) (шт.) и дробными (их можно разделить на части) (кг.). Также единицы измерения могут быть упаковками (ящ. 12 шт.)
  5. Номенклатура (список товаров) (Products) содержит наименования товаров. Каждый товар привязан (связь 1:1) к единице измерения (Product->Unit) и к категории товара (Product->Category) (связь 1:1). И в первом и во втором случае связи должны быть определены.
  6. Программа лояльности (Loyalty) - данные о клиенте-учаснике программы лояльности (ид.карточки клиента, имя, день рождения...)
  7. Список кассиров (Cashiers) - глобальный список (не привязанный к конкретному магазину) всех касиров (идентификатор, имя)
  8. Чеки. (Receipts) - список чеков. Центральный елемент всей структуры. Каждый чек идентифицируються связкой полей: "Дата чека" (date) + "Кассовый терминал" (terminal) + "Идентификатор чека" (check_id) и имеет такие связи:
  • Receipt->Shop (связь 1:1) - чек привязан к Магазину. Связь должна быть определена
  • Receipt->Terminal (связь 1:1) - чек привязан к конкретному кассовому терминалу. Связь должна быть определена
  • Receipt->Cashier (связь 1:1) - чек МОЖЕТ БЫТЬ привязан к кассиру. Эта связь МОЖЕТ быть НЕ ОПРЕДЕЛЕНА
  • Receipt->Loyalty (связь 1:1) - чек МОЖЕТ БЫТЬ привязан к программе лояльности (указывать на клиента, совершившего покупку). Эта связь МОЖЕТ быть НЕ ОПРЕДЕЛЕНА
  • Receipt->Cartitems (связь 1:N) - чек СОДЕРЖИТ 0 или более "Позиций товаров" (Cartitems). Каждая позиция (Cartitem) указывает на товар из "Списка номенклатуры" (Product) (связь 1:1) (связь должна быть определена), содержит цену за единицу товара, колличество и общую цену позиции. ЗАМЕЧАНИЕ: Cartitems рассматривается не как отдельный ресурс, а как часть Чека (Receipt).

Перечень основных ресурсов REST API можно найти по адресу http://api.datawiz.io/api/v1/. Выполнив запрос к этому ресурсу получим следующий JSON-объект типа словарь (dictionary): Запрос: GET http://api.datawiz.io/api/v1

HTTP 200 OK
Content-Type: application/json
Vary: Accept
Allow: GET, HEAD, OPTIONS

{ "terminals": "http://api.datawiz.io/api/v1/terminals/", "products": "http://api.datawiz.io/api/v1/products/", "cashiers": "http://api.datawiz.io/api/v1/cashiers/", "units": "http://api.datawiz.io/api/v1/units/", "shops": "http://api.datawiz.io/api/v1/shops", "loyalty": "http://api.datawiz.io/api/v1/loyalty/", "categories": "http://api.datawiz.io/api/v1/categories/", "receipts": "http://api.datawiz.io/api/v1/receipts/" }

⚠️ **GitHub.com Fallback** ⚠️