Перейти к основному содержимому

Подключение CRM с помощью шаблона

MonoPbx подключается к CRM без написания кода. Вы передаёте АТС шаблон: краткое описание HTTP API CRM в формате YAML или JSON с учётными данными, которые назван в шаблоне. Механизм шаблонов затем использует его для четырёх задач:

ЧтоКогда это происходит
Lookup: поиск контакта по номеру телефонаВсплывающая карточка и имена звонящих
Search: поиск контактов по введённому текстуПоиск контактов
Create contact: создание контакта в CRMПо запросу пользователя или API
Journal: запись каждого завершённого звонка в CRMАвтоматически, для каждого завершённого внешнего звонка, с повторными попытками
Click to call: преобразование телефонных номеров из CRM в номера для набораКогда пользователь набирает контакт

Это руководство описывает полную интеграцию с примерной CRM под названием sample-crm. Замените значения данными вашей CRM.

Перед началом​

Вам понадобятся:

  • Базовый адрес API вашей CRM. Он должен быть https и публичным, без строки запроса и без учётных данных в адресе.
  • Ключ API или токен для CRM с правом читать и создавать контакты и записывать записи о звонках.
  • Право integrations:write в MonoPbx.

1. Изучите шаблон​

Шаблон имеет фиксированную структуру. Вот шаблон с lookup, journal и click-to-call:

schema: mpbx.crm-template/v1 # required, exactly this value
id: sample-crm # lowercase letters, digits, - and _
name: Sample CRM
base_url: https://crm.example.com/api/v1
secrets: [api_token] # credentials the admin enters, write-only
operations:
lookup:
request:
method: GET
path: "/contacts/lookup?phone={{phone|digits}}"
headers:
Authorization: "Bearer {{secret.api_token}}"
response:
contacts: "$.data[*]" # where the list of contacts is
fields:
id: "$.id"
name: "$.full_name" # required for lookup and search
company: "$.account.name"
email: "$.email"
phones: "$.phones[*]"
url: "$.web_url"
not_found_status: [404] # "no such contact", not an error
timeout_ms: 3000
journal:
request:
method: POST
path: "/calls"
headers:
Authorization: "Bearer {{secret.api_token}}"
body:
json:
direction: "{{direction}}"
number: "{{number|digits}}"
started_at: "{{started_at}}"
duration_secs: "{{duration_secs|num}}"
disposition: "{{disposition}}"
note: "Call {{call_id}}"
click_to_call:
default_country_code: "+52" # added to numbers written nationally
national_prefix: "01" # removed from numbers written nationally

Что важно знать:

  • Шаблон — это данные, а не код. Он может использовать только заполнители {{name}}, перечисленные для каждой операции, {{secret.<name>}} для объявленного учётного данного и фильтры |digits и |num. Условий, циклов и скриптов нет.
  • Заключайте в кавычки каждое значение, содержащее {{, в YAML; иначе YAML прочитает его как отображение.
  • Адрес остаётся на хосте шаблона. Сформированный запрос, который выходит за пределы хоста, указанного в base_url, отклоняется.
  • JSON тоже поддерживается. Документ, который начинается с {, читается как JSON.
  • Размер шаблона не более 64 КиБ. Якоря, псевдонимы и теги YAML не принимаются.

Точный список заполнителей каждой операции см. в GET /api/v1/integrations/crm/reference. Там перечислены ограничения, переменные для каждой операции и полный пример шаблона.

2. Проверьте шаблон​

Проверка охватывает весь шаблон и сообщает о каждой проблеме с её местом в документе, например operations.lookup.request.path. Сетевой запрос не выполняется, поэтому проверку можно запустить до получения учётных данных.

Отправьте шаблон на POST /api/v1/integrations/crm/validate (право integrations:write). Точное тело запроса есть в документе OpenAPI по адресу /api/v1/openapi.json. Исправьте каждую указанную проблему и проверьте снова. Создание или изменение интеграции выполняет те же проверки.

3. Создайте интеграцию с учётными данными​

Создайте интеграцию через POST /api/v1/integrations/crm. Отправьте шаблон и значения учётных данных для каждого имени, перечисленного в secrets. Нужно право integrations:write.

  • Учётные данные доступны только для записи. При сохранении они зашифровываются ключом вашей компании, никакой маршрут их не возвращает, и они никогда не попадают в журналы или журнал аудита. При чтении выводятся только имена учётных данных и признак того, задано ли каждое из них.
  • Чтобы изменить учётные данные позже, отправьте все их снова через PUT /api/v1/integrations/crm/{id}/credentials.
  • Если при изменении шаблон переносится на другой адрес (схема, хост или порт base_url), сохранённые учётные данные удаляются, а интеграция выключается, чтобы значения могли уходить только на адрес, который одобрил их владелец.

Запомните id интеграции: он понадобится на следующих шагах.

4. Запустите консоль тестирования​

Консоль тестирования выполняет одну операцию с переданными вами переменными и показывает, что произошло.

POST /api/v1/integrations/crm/{id}/test выполняет операцию. Начните с dry_run: true: запрос формируется и показывается, а учётные данные отображаются как <name>, но ничего не отправляется. Это самый безопасный способ проверить заполнители.

Затем выполните операцию по-настоящему, например lookup для известного номера телефона. Ответ показывает запрос, код состояния CRM, задержку и контакты, которые прочитал шаблон.

:::caution Консоль тестирования обращается к настоящей CRM Запуск create_contact создаёт контакт, а запуск journal записывает запись. Используйте тестовый контакт или тестовую учётную запись в CRM. Консоль разрешает не более 20 запусков на компанию в минуту. :::

5. Включите интеграцию​

Включите интеграцию (PATCH /api/v1/integrations/crm/{id}). Включённая интеграция используется для поиска, поиска контактов и журналирования.

Проверьте её состояние через GET /api/v1/integrations/crm. Каждая интеграция показывает одно из следующих состояний:

СостояниеЗначение
disabledВыключена.
needs_credentialsУчётному данному, указанному в шаблоне, не задано значение.
unknownВключена, но ещё не вызывалась.
healthyПоследний вызов выполнен успешно.
degradedОдин или два вызова подряд завершились ошибкой.
failingТри и более вызовов подряд завершились ошибкой.

Вызов, который не покинул АТС, например ошибка шаблона или отсутствующих учётных данных, не влияет на состояние CRM.

6. Как работает журналирование​

Каждый завершённый внешний звонок (входящий или исходящий, с номером телефона) становится одним заданием журналирования для каждой включённой интеграции, в шаблоне которой есть операция journal. Задание отправляется АТС в фоновом режиме:

  • Задание, которое завершилось ошибкой по временной причине (проблемы сети, тайм-аут, ответ 408, 425, 429 или 5xx), повторяется через 30 секунд, 2 минуты, 10 минут, 1 час и 4 часа. После шести попыток оно считается недоставленным.
  • Задание, которое CRM отклоняет (любой другой 4xx, заблокированный адрес, шаблон, который не может сформировать запрос, или отсутствующие учётные данные), сразу считается недоставленным.
  • Недоставленное задание можно повторить через POST /api/v1/integrations/crm/jobs/{id}/retry. Недоставленные задания хранятся 30 дней.
  • Выключенная интеграция держит свои задания в ожидании, пока её снова не включат.

Если операция journal использует contact_id, а в шаблоне есть также lookup, АТС сначала ищет номер, чтобы получить идентификатор контакта в CRM.

Для журнала ошибок используйте GET /api/v1/integrations/crm/{id}/log?filter=outcome:eq:error. Журнал хранит машинный код ошибки, код статуса HTTP и задержку, а также номер или текст, замаскированные, кроме последних четырёх символов. Тело ответа, URL и учётные данные он никогда не хранит.

Права доступа​

ДействиеПраво
Просмотр интеграций, журнала и состоянияintegrations:read
Создание, изменение, проверка, тестирование и повторintegrations:write
Поиск контактов по номеру и текстуcontacts:read

Чего шаблон пока не умеет​

  • Потоки обновления OAuth. Шаблон проходит аутентификацию с учётными данными, которые он указывает: ключи API, bearer-токены в заголовке или в строке запроса, либо HTTP Basic. Для HTTP Basic введите уже закодированные в Base64 user:password как учётное данное и напишите в шаблоне Authorization: "Basic {{secret.basic}}".
  • Готовые коннекторы для конкретных CRM планируются на том же механизме. До их появления напишите шаблон для вашей CRM.