- APInita
- Возможности
- Сервисы
- Решения
- Рерайт статей с помощью ИИ и публикацией в Telegram
- Распознавание чеков и документов по фото с помощью APInita
- Генерация изображений с помощью ИИ и отправка в Телеграм
- Получение и передача файлов в Telegram по API
- Авторизация в Telegram-боте с использованием Google-таблицы в качестве базы данных
- Другие решения
- Начать бесплатно
- Вход
- Контакты
Добавление сделок и контактов в amoCRM при помощи Telegram-бота
Данное решение позволит осуществлять быстрое добавление сделок и/или контактов в систему amoCRM посредством отправки сообщений заданного формата в бот Telegram.
1. Подготовка к обмену данными
1.1 Создание бота в Telegram и подключения в APInita
Создадим в APInita новый сценарий, назовем его, к примеру, "Telegram to amoCRM", и добавим модуль Webhook:


Скопированный URL используем в настройке Telegram-бота, которую будем выполнять в соответствии с пунктами 1-4 решения по созданию Telegram-бота.
Результатом выполненных действий для данной интеграции станет:
- входящий вебхук, являющийся первым шагом (триггером) сценария;
- подключение к боту, которое будет передаваться в запросах на отправку сообщений в последующих шагах.

1.2 Настройка подключения к amoCRM
Создадим новое подключение в APInita, назовем его amoCRM, тип подключения: OAuth 2.0

Перейдя по кнопке “Начать настройку”, видим поле, содержащее URL вида https://cabinet.apinita.ru/connections/xx:

Нажатием на URL копируем его для дальнейших действий.
Заходим в раздел "амоМаркет" того аккаунта, с которым будет осуществляться интеграция. Нажимаем “Создать интеграцию”:


При создании интеграции вставляем ранее скопированный URL подключения APInita, предоставляем доступ, указываем название и описание интеграции, сохраняем:

Находим созданную интеграцию во вкладке “Установленные” в amoМаркет’е:

Открыв окно интеграции, во вкладке “Ключи и доступы” находим уникальные значения, соответствующие ключам “client_secret”, “client_id” и “code”. Оставим это окно открытым, чтобы в процессе настройки авторизации копировать значения по кнопке клипборда справа от каждого из них.

Далее подготовим 2 URL, подставив свои значения:
URL авторизации:
https://www.amocrm.ru/oauth?client_id={{ client_id }}&mode=post_messageзначение переменной {{ client_id }} будет автоматически подставлено в URL, когда будет заполнено соответствующее поле.
URL для получения Access Token:
https://{user_account}.amocrm.ru/oauth2/access_token{user_account} заменяем на свой поддомен аккаунта, который можно увидеть в адресной строке amoCRM.
Приступаем к редактированию подключения в APInita.
0. Вставить значения “client_id” и “client_secret”;
1. Вставить URL авторизации;
2. Вставить URL для получения Access Token https://{user_account}.amocrm.ru/oauth2/access_token, указать метод POST и формат данных application/json, в полях запроса ключи { “grant_type”: “authorization_code”, “client_id”: “{{ client_id }}”, “client_secret”: “{{ client_secret }}” } будут сформированы по умолчанию (на скриншоте подчеркнуто зеленым), далее вставить значение ключа “code”, добавить ключ “redirect_uri”, в значение которого подставить URL подключения APInita;

3. В заголовке запроса { “Authorization”: “Bearer {{ access_token }}” } сформируется по умолчанию;
4. В качестве URL для обновления токена используется тот же URL для получения Access Token: https://{user_account}.amocrm.ru/oauth2/access_token. Указать метод POST и формат данных application/json, в полях запроса ключи { “grant_type”: “refresh_token”, “client_id”: “{{ client_id }}”, “client_secret”: “{{ client_secret }}”, “refresh_token”: “{{ refresh_token }}” } будут сформированы по умолчанию, далее добавить ключ “redirect_uri”, в значение которого подставить URL подключения APInita;

Нажимаем кнопку “Сохранить и авторизоваться”, произойдет перенаправление на авторизацию приложения в amoCRM. Выбираем аккаунт и нажимаем “Разрешить”:

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

Теперь можем выйти из редактирования подключения. Оно находится в списке подключений со статусом “Подключено”.

2. Настройка сценария в APInita
В рамках данного решения входящее сообщение в Telegram-бот может иметь один из двух форматов: добавление/обновление сделки или контакта. Для конструирования и обработки этих форматов нам понадобятся маркеры сделки или контакта (lead_marker и contact_marker), которые пользователь будет указывать в начале сообщения для определения его назначения, а так же разделитель текста (message_delimiter) для разграничения полей (название, сумма, телефон, и т.д.).
2.1 Переменные сценария
Введем в сценарий следующие переменные:
"lead_marker" : "сдел.",
"contact_marker": "конт.",
"message_delimiter": "\n"( \n - управляющий символ переноса строки)


2.2.1 Проверка сообщения на условия (модули IF)
Создадим 3 модуля IF для запуска трех основных веток сценария:

Посредством перетаскивания за иконку руки расположим их на одном уровне, следующем после входящего вебхука:


Используя переменные сценария, составим для каждого модуля свое условие:
- сообщение свободного формата:
{{ s1.body.message.text|split(' ')|first != scenario.lead_marker and s1.body.message.text|split(' ')|first != scenario.contact_marker }}(текст НЕ начинается с маркера сделки и НЕ начинается с маркера контакта);
- сообщение содержит сделку:
{{ s1.body.message.text|split(' ')|first == scenario.lead_marker }}(текст начинается с маркера сделки);
- сообщение содержит контакт:
{{ s1.body.message.text|split(' ')|first == scenario.contact_marker }}(текст начинается с маркера контакта).
При помощи фильтров split и first здесь текст сообщения разбивается по пробелам, и затем выводится первый элемент.
Прописываем условие и соответствующее название в редакторе каждого модуля:

2.2.2 Отправка информационного сообщения (Telegram API)
Следующим после модуля IF "сообщение свободного формата" создадим модуль HTTP:

Осуществляем отправку запроса на URL:
https://api.telegram.org/bot{{ connection.body.bot_id }}/sendMessage(значение {{ connection.body.bot_id }} будет автоматически подставлено из данных подключения).
Метод: POST, формат данных: text/plain.
В заголовке запроса передаем:
- {"Content-Type": "application/json"}
- подключение, созданное в пункте 1.1
В теле запроса, используя переменные сценария, составим информационное сообщение, описывающее формат ввода данных.
{
"chat_id": {{ s1.body.message.chat.id }},
"text": "Для добавления сделки пишите в начале сообщения:
{{ scenario.lead_marker }}
Для добавления контакта пишите в начале сообщения:
{{ scenario.contact_marker }}
Порядок заполнения полей:
---
{{ scenario.lead_marker }} \{Название сделки\} {{ scenario.message_delimiter }} \{Сумма сделки, цифрами\} {{ scenario.message_delimiter }} \{контактная информация в произвольном формате\} {{ scenario.message_delimiter }} \{Имя контакта\} {{ scenario.message_delimiter }} \{Номер телефона\} {{ scenario.message_delimiter }} \{Адрес E-mail\}
---
{{ scenario.contact_marker }} \{Имя контакта\} {{ scenario.message_delimiter }} \{Номер телефона\} {{ scenario.message_delimiter }} \{Адрес E-mail\}
---
Поле может быть не заполнено, но количество полей до последнего заполненного поля должно соблюдаться.
Примеры сообщений:
---
{{ scenario.contact_marker }} Андрей {{ scenario.message_delimiter }} {{ scenario.message_delimiter }} andrey@example.com
---
{{ scenario.lead_marker }} Аудит сайта, SEO {{ scenario.message_delimiter }} 15000 {{ scenario.message_delimiter }} {{ scenario.message_delimiter }} Андрей {{ scenario.message_delimiter }} +79600000000
---
{{ scenario.lead_marker }} Разработка сайта {{ scenario.message_delimiter }} 30000 {{ scenario.message_delimiter }} телеграм @username, Антон - химчистка
---
"
}
Временно включим сценарий и отправим в бот тестовое сообщение:

Бот отправляет информационное сообщение в ответ на сообщение, которое не содержит ни маркера сделки, ни маркера контакта:

На странице сценария отобразилось, по какой ветке он сработал:

2.3 Парсинг сообщений в данные (модули PHP)
Снова выключим сценарий для возможности редактирования. После проверки условия "сообщение содержит сделку" поставим модуль PHP.

В коде пропишем обработку данных, полученных модулем Webhook - на выходе строка из сообщения в Telegram преобразуется в массив, к которому будут обращаться последующие шаги сценария:
$messageText = $s1['body']['message']['text'];
// создание переменной из строкового значения выходных данных вебхука
list($leadName_raw, $leadPrice, $contactAbout, $contactName, $contactPhone_raw, $contactEmail_raw) = array_pad(explode($scenario['message_delimiter'], $messageText), 6, null);
// создание массива заданного размера из строки
list($marker, $leadName) = array_pad(explode(" ", $leadName_raw, 2), 2, " ");
// разбиение строки на части до пробела и после него
$contactPhone = isset($contactPhone_raw) ? trim($contactPhone_raw) : null ;
$contactEmail = isset($contactEmail_raw) ? trim($contactEmail_raw) : null ;
// удаление пробелов и переносов из строк, содержащих телефон и email
return ['leadName' => $leadName, 'leadPrice' => $leadPrice, 'contactAbout' => $contactAbout, 'contactName' => $contactName, 'contactPhone' => $contactPhone, 'contactEmail' => $contactEmail];
// возвращение итогового массива с полученными даннымиПрописываем в соответствующие поля название шага (парсинг сообщения в данные сделки) и код, сохраняем модуль.

Аналогичным образом пропишем модуль "парсинг сообщения в данные контакта" для условия "сообщение содержит контакт".
Код для обработки строки в данные контакта отличается размером возвращаемого массива:
$messageText = $s1['body']['message']['text'];
list($contactName_raw, $contactPhone_raw, $contactEmail_raw) = array_pad(explode($scenario['message_delimiter'], $messageText), 3, null);
list($marker, $contactName) = array_pad(explode(" ", $contactName_raw, 2), 2, " ");
$contactPhone = isset($contactPhone_raw) ? trim($contactPhone_raw) : null ;
$contactEmail = isset($contactEmail_raw) ? trim($contactEmail_raw) : null ;
return ['contactName' => $contactName, 'contactPhone' => $contactPhone, 'contactEmail' => $contactEmail];
Временно включим сценарий и отправим в бот Telegram сообщение о сделке:

В выходных данных модуля увидим преобразованные данные:

Аналогичным образом модуль "парсинг сообщения в данные контакта" (по соседней ветке) обработает сообщение, начинающееся с маркера контакта, заданного переменной сценария.
2.4 Запросы к amoCRM API (модули HTTP)
2.4.1 Запрос к методу добавления сделки
Осуществим отправку запроса на добавление сделки в amoCRM. Следующим за PHP-обработкой данных добавляем модуль HTTP.

URL запроса:
https://{user_account}.amocrm.ru/api/v4/leads/complex{user_account} заменяем на свой поддомен аккаунта, который можно увидеть в адресной строке amoCRM.
Метод: POST, формат данных: text/plain.
В заголовке запроса передаем:
- {"Content-Type": "application/json"}
- подключение, созданное в пункте 1.2
В теле запроса передаем следующие данные:
[
{
"name": "{{ s6.body.leadName }}",
"price": {{ s6.body.leadPrice }},
"custom_fields_values": [
{
"field_id": 820005,
"values": [
{
"value": "{{ s6.body.contactAbout }}"
}
]
}
],
"_embedded": {
{% if s6.body.contactName != null and s6.body.contactName != "" and s6.body.contactName != " " %}
"contacts": [
{
"name": "{{ s6.body.contactName }}",
"custom_fields_values": [
{% if s6.body.contactPhone != null and s6.body.contactPhone != "" %}
{
"field_code": "PHONE",
"values": [
{
"value": "{{ s6.body.contactPhone }}"
}
]
}
{% endif %}
{% if s6.body.contactPhone != null and s6.body.contactPhone != "" and s6.body.contactEmail != null and s6.body.contactEmail != "" %}
,
{% endif %}
{% if s6.body.contactEmail != null and s6.body.contactEmail != "" %}
{
"field_code": "EMAIL",
"values": [
{
"value": "{{ s6.body.contactEmail }}"
}
]
}
{% endif %}
]
}
]
{% endif %}
}
}
]Здесь условиями, заданными при помощи шаблонизатора Twig, определяется передача определенных элементов массива в зависимости от наличия соответствующих данных в PHP-обработке входящего сообщения.

Сохраняем модуль.
При успешном выполнении операции в ответе возвращается объект созданной сделки:

В случае если в HTTP-запросе (в соответствии с прописанными условиями) были переданы поля сущности контакта, в системе amoCRM создается не только сделка, но и связанный с ней контакт:

2.4.2 Запрос к сущности контакта
Запрос непосредственно к сущности контакта в amoCRM разделим по двум веткам сценария: создание нового или обновление существующего контакта.
Чтобы произвести поиск контакта по телефону, осуществляем запрос на URL:
https://{user_account}.amocrm.ru/api/v4/contactsМетод: GET, формат данных: application/x-www-form-urlencoded. В заголовке запроса передаем подключение, созданное в пункте 1.2.
В теле запроса прописываем следующее условие в значение ключа "query":
{% if s7.body.contactPhone != null and s7.body.contactPhone != "" %} {{ s7.body.contactPhone }} {% else %} "ааааааааа" {% endif %}Условие работает так: если значение ключа "телефон" не null и не пустая строка, подставляем это значение, в противном случае - "ааааааааа", или по сути любой набор символов, который не может содержаться в поле "телефон", соответственно, поиск по нему не даст результата и в ответе вернет "пусто".
Данное условие необходимо потому, что данный метод amoCRM API возвращает в виде массива весь список контактов в случае если критерием поиска выступает пустая строка. Так как дальнейшее выполнение сценария будет разветвляться в зависимости от условия наличия возвращаемого элемента массива, здесь нужно избежать возвращения массива, не релевантного поиску, в тех случаях, когда номер телефона не содержится во входящем сообщении.

Сохраняем модуль.
Теперь добавим контакт через бот (временно включив сценарий):

В выходных данных модуля видим, что контакт с таким телефоном не найден, и в этом случае данный метод возвращает пустое тело ответа:

Теперь добавим этот контакт в amoCRM вручную:

Повторим сообщение боту, после чего увидим, что метод вернул массив "contacts", содержащий в виде элемента массива контакт с соответствующим номером телефона:

2.4.3 Проверка данных, возвращаемых HTTP-модулями, на условия
После шага с запросом на добавление сделки поместим модуль IF.

Сделка добавлена:
{{ s8.body.0.id is defined }}(это условие проверяет, что метод amoCRM API вернул массив, содержащий добавленную сделку).

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

- телефон не найден:
{{ not s9.body._embedded.contacts.0.id is defined }}условие проверяет, что метод поиска контакта по телефону НЕ вернул массив, содержащий найденный контакт;
- телефон найден:
{{ s9.body._embedded.contacts.0.id is defined }}условие проверяет, что метод поиска контакта по телефону вернул массив, содержащий найденный контакт.
Разместим два модуля с этими условиями параллельно друг другу после модуля "поиск контакта":

В результате наш сценарий после парсинга входящего сообщения разделился на три основные ветки:

2.4.4. Запрос к методу добавления контакта
После модуля с условием "телефон не найден" создадим HTTP-запрос на добавление контакта:

URL запроса:
https://{user_account}.amocrm.ru/api/v4/contactsметод: POST, формат данных: text/plain.
В заголовке запроса передаем:
- {"Content-Type": "application/json"}
- подключение, созданное в пункте 1.2
[
{
"name": "{{ s7.body.contactName }}",
"custom_fields_values": [
{
"field_code": "PHONE",
"values": [
{
"value": "{{ s7.body.contactPhone }}"
}
]
},
{
"field_code": "EMAIL",
"values": [
{
"value": "{{ s7.body.contactEmail }}"
}
]
}
]
}
]

2.4.5 Запрос к методу обновления контакта по ID
После модуля с условием "телефон найден" создадим HTTP-запрос на обновление существующего контакта.
URL запроса:
https://{user_account}.amocrm.ru/api/v4/contacts/{{ s9.body._embedded.contacts.0.id }}метод: PATCH, формат данных: text/plain.
В заголовке запроса передаем:
- {"Content-Type": "application/json"}
- подключение, созданное в пункте 1.2
{
"id": {{ s9.body._embedded.contacts.0.id }},
"name": "{{ s7.body.contactName }}",
"custom_fields_values": [
{% if s7.body.contactPhone != null and s7.body.contactPhone != "" %}
{
"field_code": "PHONE",
"values": [
{
"value": "{{ s7.body.contactPhone }}"
}
]
}
{% endif %}
{% if s7.body.contactEmail != null and s7.body.contactEmail != "" %}
,
{
"field_code": "EMAIL",
"values": [
{
"value": "{{ s7.body.contactEmail }}"
}
]
}
{% endif %}
]
}Здесь условиями, заданными при помощи шаблонизатора Twig, определяется передача определенных элементов массива в зависимости от наличия соответствующих данных в PHP-обработке входящего сообщения.

2.5 Проверка условий и отправка сообщений
Теперь сценарий позволяет создать контакт, а затем обновить его же. Временно включим сценарий и отправим сообщение:

Перейдя на страницу сценария, увидим, по какой ветке он сработал:

В результате выполнения сценария в системе amoCRM появился контакт:

Теперь повторим сообщение боту, на этот раз добавив email в соответствующее поле по заданному формату сообщения:

Теперь сценарий сработал по ветке, соответствующей тому условию, что контакт с таким телефоном уже существует:

В amoCRM видим, что контакт обновился:

2.5.1 Проверка данных, возвращаемых HTTP-модулями, на условия
Создадим модули IF, проверяющие условия, что методы запросов на создание и обновление контакта вернули ответы, свидетельствующие об успешном выполнении операции, и разместим их после соответствующих HTTP-модулей.
Контакт создан:
{{ s13.body._embedded.contacts.0.id is defined }}
Контакт обновлен:
{{ s14.body.id is defined }}
2.5.2 Отправка ответных сообщений об успешном выполнении операций (Telegram API)
После модуля условия IF "контакт создан" поместим модуль HTTP.
URL запроса:
https://api.telegram.org/bot{{ connection.body.bot_id }}/sendMessage(значение {{ connection.body.bot_id }} будет автоматически подставлено из данных подключения)
Метод: POST, формат данных: application/json
В заголовке запроса передаем подключение, созданное в пункте 1.1
В теле запроса пропишем ключи со значениями:
{
"chat_id": {{ s1.body.message.chat.id }} ,
"text": "Контакт создан"
}
После модуля условия IF "контакт обновлен" - аналогичный модуль:
URL запроса:
https://api.telegram.org/bot{{ connection.body.bot_id }}/sendMessageМетод: POST, формат данных: application/json.
В заголовке запроса передаем подключение, созданное в пункте 1.1
В теле запроса пропишем ключи со значениями:
{
"chat_id": {{ s1.body.message.chat.id }} ,
"text": "Контакт найден и обновлен"
}
Также аналогичный запрос осуществим по ветке модуля условия IF "сделка добавлена":
URL запроса:
https://api.telegram.org/bot{{ connection.body.bot_id }}/sendMessageМетод: POST, формат данных: application/json
В заголовке запроса передаем подключение, созданное в пункте 1.1
В теле запроса пропишем ключи со значениями:
{
"chat_id": {{ s1.body.message.chat.id } ,
"text": "Сделка добавлена"
}
Интеграция в действии
Включаем готовый сценарий и отправляем в бот сначала тестовое сообщение, в ответ на которое получаем информационное сообщение о формате ввода. Затем, придерживаясь данного формата, добавляем сделки и контакты. Бот сообщает об успешном выполнении операций в ответных сообщениях:

В результате обработки сообщений, отправленных в нашем примере, в системе amoCRM была добавлена сделка и связанный с ней контакт:


Затем отдельной операцией обновлен этот контакт, созданный при добавлении сделки:

А также был добавлен еще один новый контакт:

Похожие решения
- Создание мини чат-бота в Telegram
- Телеграм чат-бот на модуле PHP
- Авторизация в Telegram-боте с использованием Google-таблицы в качестве базы данных
- Получение и передача файлов в Telegram по API
- Интеграция amoCRM и Telegram: автоматизация бизнес-процессов
- Интеграция amoCRM и Google Таблиц: автоматизация без кода
- Интеграция amoCRM и Битрикс 24: автоматизация без программирования
- Интеграция amoCRM и Яндекс.Метрики для автоматизации бизнеса
- Интеграция amoCRM и ВКонтакте: автоматизация работы с клиентами