Архитектура пользовательских интеграций
Документация
Главная

Архитектура пользовательских интеграцийBETA

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

Интеграция строится из отдельных логических блоков, каждый из которых выполняет конкретную задачу:

  • Блоки — выполняют определенный тип запроса
  • Подключения — содержат данные для доступа к внешнему API

Пример структуры интеграции:

app = {
    schema: 2,
    version: 'Номер версии',
    label: 'Название интеграции',
    description: 'Описание интеграции',
    blocks: [],
    connections: []
}

Блоки

Блок представляет собой основной исполняемый элемент интеграции. Он отвечает за выполнение конкретного запроса к внешнему API.

Блок может выполнять следующие задачи:

  • Отправлять данные во внешнюю систему
  • Получать и обрабатывать ответы от API
  • Формировать выходные данные для следующих блоков
  • Использовать переменные из контекста (например, значения, полученные ранее)

Такой блок является ключевым элементом логики интеграции, так как именно он взаимодействует с внешним сервисом.

bundle и context в блоках

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

При выполнении блока в функцию executePagination передаются дополнительные аргументы — bundle и context.

    executePagination: (z, bundle, context) => {
    }

Где:

  • bundle содержит входные данные блока, параметры подключения и служебную информацию
  • context используется для хранения состояния между вызовами блока и может быть возвращен для использования на следующем шаге выполнения

Пример функционального блока

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

export const getAllScripts: IntegrationBlock<
  { onlyActive: boolean },
  ICommonAuthData
> = {
  label: "Получить все скрипты в системе",
  description: "Блок получает все скрипты в системе",
  inputFields: [
    {
      key: "onlyActive",
      type: "boolean",
      label: "Только активные скрипты",
      default: true,
    },
  ],
  executePagination: (service, bundle, _context) => {
    if (!bundle.authData || !bundle.authData.url) {
      service.stringError("Отсутствует подключение.");
    }
    const explorer = new GraphQLClient(service);
    const response = explorer.query<IApiResponse>(
      bundle.authData.url,
      `query {
        automation {
          script {
            script_general_list {
              items {
                element {
                  id
                  name
                  enabled
                }
              }
            }
          }
        }
      }`
    );

    const items = response.data?.automation.script.script_general_list.items ?? [];

    const output = items.reduce<TNormalizedItem[]>((acc, { element }) => {
      if (element.name.includes("_DISABLE_")) {
        return acc;
      }

      if (bundle.inputData.onlyActive && !element.enabled) {
        return acc;
      }

      acc.push([element.id, element.name, element.enabled]);
      return acc;
    }, []);

    const outputVariables: OutputBlockVariables[] = [
      { type: "Long", name: "id" },
      { type: "String", name: "name" },
      { type: "Boolean", name: "enabled" },
    ];

    return {
      output,
      output_variables: outputVariables,
      state: undefined,
      hasNext: false,
    };
  }
}

Подключения

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

oAuth2

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

Сервисы, поддерживающие OAuth2, позволяют получить клиентский идентификатор и секретный ключ. Для этого необходимо перейти на официальный сайт выбранного сервиса в раздел с документацией по API и следовать инструкциям для регистрации приложения и получения необходимых данных.

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

Этот способ аутентификации используется в интеграциях с такими сервисами, как Google Drive, Google Таблицы, Microsoft SharePoint, amoCRM и другими.

Basic Auth

Этот метод аутентификации использует передачу логина и пароля пользователя для доступа к интегрируемому сервису.

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

Например, этот способ аутентификации используют интеграции с инструментом управления проектами Jira.

API Key

Ключ API — это уникальный идентификатор, используемый для аутентификации запросов к API, который позволяет системам взаимодействовать между собой и обеспечивает доступ к нужным ресурсам без прохождения пользовательской аутентификации. Ключ API обычно передается в заголовках HTTP-запросов или в параметрах URL. Он служит для идентификации приложения и разрешает доступ к API сервиса.

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

Например, этот способ аутентификации используют интеграции с Proceset.

Пример блока подключений

Ниже приведен пример подключения по API-ключу. Он демонстрирует, как описываются поля авторизации и формируется URL для обращения к API.

import { IntegrationConnection } from "@infomaximum/integration-sdk";
import { ICommonAuthData } from "../types/connections";

export const basicConnect: IntegrationConnection<ICommonAuthData> = {
  label: "Подключение по ApiKey",
  description: "Подключение по ApiKey",
  inputFields: [
    {
      key: "connection_apiKey",
      type: "text",
      label: "API-ключ",
    },
    {
      key: "connection_host",
      type: "text",
      label: "Хост",
    },
    {
      key: "connection_port",
      type: "text",
      label: "Порт ",
    },
    {
      key: "host_button",
      type: "button",
      label: "Автоопределение хоста",
      typeOptions: {
        saveFields: (service, bundle) => {
          const preparedHost = bundle.authData.BASE_URL.replace(
            /^https?:\/\//,
            ""
          ).replace("/webhook/" + bundle.authData.GUID, "");

          const [host, port = ""] = preparedHost.split(":");

          return {
            connection_host: host,
            connection_port: port,
          };
        },
      },
    },
  ],
  execute: (service, bundle) => {
    function createUrl(host: string, port: string, apiKey: string): string {
      const hasProtocol = /^https?:\/\//.test(host);
      const base = hasProtocol ? host : `http://${host}`;

      if (!port || port === "0") {
        return `${base}/graphql?api_key=${apiKey}`;
      }
      return `${base}:${port}/graphql?api_key=${apiKey}`;
    }

    return {
      apiKey: bundle.authData.connection_apiKey,
      host: bundle.authData.connection_host,
      port: bundle.authData.connection_port,
      url: createUrl(
        bundle.authData.connection_host,
        bundle.authData.connection_port,
        bundle.authData.connection_apiKey
      ),
    };
  },
  refresh: () => {
    /*Empty*/
  },
};

Пример использования redirect

Механизм redirect используется при OAuth-аутентификации для перенаправления пользователя на страницу авторизации внешнего сервиса.

Пример формирования URL для авторизации:

redirect: (_service, bundle) =>
  "https://login.microsoftonline.com/" +
  bundle.authData.tenant_id +
  "/oauth2/v2.0/authorize?" +
  "response_type=code" +
  "&client_id=" +
  bundle.authData.client_id +
  "&redirect_uri=" +
  bundle.authData.redirect_url +
  "&scope=User.Read Calendars.Read OnlineMeetingTranscript.Read.All OnlineMeetings.Read offline_access",

Пример использования saveFields

Метод saveFields применяется для сохранения данных авторизации, полученных после успешного OAuth-обмена.

Важно

access_token, refresh_token, expiration_time должны иметь именно такие названия при сохранении, иначе механизм обновления не сработает.

saveFields: (service, bundle) => {
const body =
  "code=" +
  authCode +
  "&client_id=" +
  clientId +
  "&redirect_uri=" +
  bundle.authData.redirect_url +
  "&client_secret=" +
  clientSecret +
  "&grant_type=authorization_code";

const response = service.request<ArrayBuffer>({
  url: `https://login.microsoftonline.com/${catalogIdentifier}/oauth2/v2.0/token`,
  method: "POST",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded",
  },
  jsonBody: body,
});
const exchangeCode = JSON.parse(new TextDecoder().decode(response.response));

const accTok = exchangeCode.access_token;
if (!accTok) {
  service.stringError(
    "Не удалось выполнить обмен Authorization Code на access_token.\n" +
      JSON.stringify(exchangeCode.response)
  );
}
  return {
    access_token: accTok,
    refresh_token: exchangeCode.refresh_token,
    expiration_time: exchangeCode.expires_in,
  };
},

Была ли статья полезна?

Да
Нет
Предыдущая
Инструменты для разработки интеграций
Следующая
Поля ввода и их использование

Дайджест новостей и обновлений —

один раз в месяц

Заполняя форму, я даю согласие на обработку моих персональных данных
430006, Саранск,
Северо-восточное шоссе, д. 3
ОКВЭД 62.01
ИНН 1328​909857
Код вида деятельности
в области ИТ 15.02 и 17.01
Языки программирования