Falcon Space. Создание сервиса API (входящие и исходящие запросы API)

Введение в API

В системе реализованы 2 механизм для работы API 

  • Универсальный механизм входящих запросов по API - позволяет извне запускать некоторые команды по HTTPS GET/POST и получать некий отклик в JSON/XML/Plain text формате.
  • Исходящие запросы к внешним API - система подготавливает запрос к внешней системе, отправляет его по HTTPS GET/POST и обрабатывает ответ. 

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

Управление API происходит на странице /asapi

Универсальный механизм входящих запросов по API

Как проходит основной процесс входящего запроса: 

  1. Обращение извне по HTTPS GET к методу auth для получения token доступа (система проверяет логин, пароль и выдает токен, который будет проверяться в дальнейших обращениях). 
  2. Отправка запроса action для выполнения некоего действия (Получить заказы, создать новый заказ). В рамках запроса происходит следующее:
    1. Проверяются права на выполнение операции
    2. Запускается хранимая процедура обработки действия, подготавливается ответ для вызывающей стороны в виде JSON, XML, Plain text.
    3. Выдается некий отклик на вызывающую сторону

Для API используются обычный HTTPS запросы с ответом в формате JSON. Основные методы: 
  • auth - создание сессии пользования API (параметры username, password)
  • action - выполнение некоего метода API (параметры могут быть любые)
Использование API
1. Вызываем по Get или Post метод авторизации /api/auth?username=&password={password}&output=json
  • Имя и пароль пользователя API задается в таблице as_api_users (это не логин/пароль обычного пользователя системы). 
  • output - необязательный параметр, задает формат вывода (json, xml,text).
Если данные корректные, то получим токен в отклике сервера. {"errorCode":0,"token":"7285440B-BD32-405F-813D-C26DFED23DF5","result":true,"msg":""}
Если есть ошибки, то result = false и errorCode содержит код ошибки. 

2. Вызываем метод API 

/api/action/getOrders?token=7285440B-BD32-405F-813D-C26DFED23DF5&catID=1

Передаем token, action (код метода) и произвольные параметры. 

Если все хорошо, то мы получаем result: true и в data содержатся выходные данные от результата выполнения метода. 
Коды ошибок и описания к ним: 

Код

Описание ошибки

1

100

Неверный токен

2

101

Истекло время сессии

3

102

Не найдена реализация метода АПИ (т.е. нет хранимой процедуры метода)

4

103

Выполнение метода завершилось с ошибкой

5

104

Имя/пароль неверные

Примечание: 
  1. в ExtendedDictionaryParameter @parameters используем Key, Value2, а не Key, Value!
  2. в @parameters также передается содержимое самого запроса Request.InputStream (в Key=InputStream)
  3. в @parameters также передается ключ remoteIP - IP вызывающий стороны (например, по нему можно проверить легитимность запроса к API)
  4. Если используете для отправки метод POST, то обязательно указывайте   'content-type': 'application/x-www-form-urlencoded'. Проверять подобные запросы можно через программу postman.

Создание нового метода API

API создается следующим образом: 
  1. Создается действие в таблице as_api_actions (на странице /asapi)
  • entityCode указывает код сущности, с которой мы работаем, например order
  • code - задает код действия. 

    2. Создается хранимая процедура api_{entityCode}_{code}, которая возвращает 2 select. 

CREATE procedure [dbo].[api_order_getOrders]
@parameters ExtendedDictionaryParameter READONLY, -- параметры которые переданы в метод
@username nvarchar(256) --пользователь API (это не логин пользователя в системе)
as
begin
	declare @catID int
	select @catID = cast(Value2 as int) from @parameters where [Key] = 'catID'

	/* select 1 - это информация об операции. В errorCode можно указать
          специфичные коды ошибок по операциям */
	select '' Msg, 1 Result, 0 errorCode

	/* select 2 - это данные, которые необходимо передать источнику запроса к API
        (в выходном JSON передаются в параметре data) */
	select * from ord_orders


        /* SELECT 3 Вызов внешних действий (напр Запрос API)*/

end

3.Вызываем метод как /api/action/actioncode1?token=token1&...{доп параметры}....


Вызов API без авторизации


В этом случае нет необходимости использовать токены.
  • У action укажите параметр withoutToken=true.
  • Вызывайте метод без токена: /api/action/getOrders?catID=1
Установка формата вывода для действия. 
Для этого укажите json,text или xml в параметре outputType для действия (as_api_actions). 

Свойство идемпотентности для создаваемых методов API
Для включения идемпотентности необходимо в запросе к API передаваться определенный параметр или заголовок(напр X-Request-ID),
содержащий уникальный идентификатор: guid, комбинация из номера заказа, даты и суммы.
Каждый новый запрос, который необходимо обработать, должен включать новое значение X-Request-ID.
Таким образом можно избежать проблем с повторными запросами (когда операция дважды выполнится на сервере для 1 запроса).

Исходящие запросы к внешним API

Вы можете обратиться к внешним API через использование Внешних действий (код apirequest, использование описано в документации по Формам). 
Чтобы создать запрос, необходимо выполнить следующее:
  • создать запись о новом запросе (таблицы Исходящие запросы API на /asapi) 
  • реализовать процедуру request(она выдает адрес и параметры для выполнения запроса)
    • На входе @parameters ExtendedDictionaryParameter (коллекция входных параметров в Key nvarchar(32), Value2 nvarchar(max))  и @username (текущий пользователь)
    • Возвращает SELECT 1 (Msg, Result и URL, ContentType)
      • URL - адрес, который будет вызван по HTTPS
      • ContentType - можно задать для POST запросов свой ContentType (для формы).
        • По умолчанию он подставляется для форм multipart/form-data; boundary=------
        • и для json тела application/json
    •  и SELECT 2 (параметры которые будут передаваться вовне - name, value, type). 
      • type - вариант form, header, json. 
        • Если отправить надо post запрос, то параметры ставьте в form.  
        • Если передан json (используется для POST) - то его содержимое будет телом всего запроса POST. Все остальные параметры в этом случае игнорируются. 
        • Если нужны обычные get параметры - то передавайте их через URL
  • реализовать процедуру обработки ответа - response
    • На входе ответ от внешнего источника в виде строки @response, @parameters ExtendedDictionaryParameter (коллекция входных параметров в Key, Value2, которые приходили в Request процедуру)
    • Ответ 
      • SELECT 1 Msg, Result и Response (может быть дополнительная обработка и выдача ответа вовне). 
      • SELECT 2 Вызов внешних действий (Внешние запросы API и т.д.)
  • вызвать запрос через внешние действия (при сохранении формы, отпправке уведомления или других местах).
Для тестирования API можно использовать метод /Api/Req/{code} - он вернет ответ в JSON формате. 

Как отправить исходящий запрос POST с JSON телом?

Для этого указываем тип запроса POST и передаем только 1 параметр с type=json в формате строки с JSON.


Примечание
Учитывайте длину кодов и ключей (не должны быть больше 32 символов).

Работа с JSON в SQL Server
https://docs.microsoft.com/ru-ru/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver15
https://stackoverflow.com/questions/2867501/parse-json-in-tsql
https://habr.com/ru/post/343062/
https://habr.com/ru/post/317166/

Работа с XML в SQL Server 
https://www.sql.ru/forum/841296/razbor-xml-v-tablicu
https://stackoverflow.com/questions/15680259/parse-xml-in-sql-server/15681388
https://stackoverflow.com/questions/3989395/convert-xml-to-table-sql-server

Онлайн редакторы для XML и JSON

Инструменты позволяют скопировать большой текст и просматривать через дерево элементов.

https://xmlgrid.net/ - просмотр XML

https://jsoneditoronline.org/ - редактор JSON