Скопированный URL используем в настройке Telegram-бота, которую будем выполнять в соответствии с пунктами 1-4 решения по созданию Telegram-бота.
Результатом выполненных действий для данной интеграции станет:
Создадим новое подключение в 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: есть.
Теперь можем выйти из редактирования подключения. Оно находится в списке подключений со статусом “Подключено”.
В рамках данного решения входящее сообщение в Telegram-бот может иметь один из двух форматов: добавление/обновление сделки или контакта. Для конструирования и обработки этих форматов нам понадобятся маркеры сделки или контакта (lead_marker и contact_marker), которые пользователь будет указывать в начале сообщения для определения его назначения, а так же разделитель текста (message_delimiter) для разграничения полей (название, сумма, телефон, и т.д.).
Введем в сценарий следующие переменные:
"lead_marker" : "сдел.",
"contact_marker": "конт.",
"message_delimiter": "\n"
( \n - управляющий символ переноса строки)
Создадим 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 здесь текст сообщения разбивается по пробелам, и затем выводится первый элемент.
Прописываем условие и соответствующее название в редакторе каждого модуля:
Следующим после модуля IF "сообщение свободного формата" создадим модуль HTTP:
Осуществляем отправку запроса на URL:
https://api.telegram.org/bot{{ connection.body.bot_id }}/sendMessage
(значение {{ connection.body.bot_id }} будет автоматически подставлено из данных подключения).
Метод: POST, формат данных: text/plain.
В заголовке запроса передаем:
В теле запроса, используя переменные сценария, составим информационное сообщение, описывающее формат ввода данных.
{
"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, Антон - химчистка
---
"
}
Временно включим сценарий и отправим в бот тестовое сообщение:
Бот отправляет информационное сообщение в ответ на сообщение, которое не содержит ни маркера сделки, ни маркера контакта:
На странице сценария отобразилось, по какой ветке он сработал:
Снова выключим сценарий для возможности редактирования. После проверки условия "сообщение содержит сделку" поставим модуль 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 сообщение о сделке:
В выходных данных модуля увидим преобразованные данные:
Аналогичным образом модуль "парсинг сообщения в данные контакта" (по соседней ветке) обработает сообщение, начинающееся с маркера контакта, заданного переменной сценария.
Осуществим отправку запроса на добавление сделки в amoCRM. Следующим за PHP-обработкой данных добавляем модуль HTTP.
URL запроса:
https://{user_account}.amocrm.ru/api/v4/leads/complex
{user_account} заменяем на свой поддомен аккаунта, который можно увидеть в адресной строке amoCRM.
Метод: POST, формат данных: text/plain.
В заголовке запроса передаем:
В теле запроса передаем следующие данные:
[
{
"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 создается не только сделка, но и связанный с ней контакт:
Запрос непосредственно к сущности контакта в 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", содержащий в виде элемента массива контакт с соответствующим номером телефона:
После шага с запросом на добавление сделки поместим модуль 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 }}
условие проверяет, что метод поиска контакта по телефону вернул массив, содержащий найденный контакт.
Разместим два модуля с этими условиями параллельно друг другу после модуля "поиск контакта":
В результате наш сценарий после парсинга входящего сообщения разделился на три основные ветки:
После модуля с условием "телефон не найден" создадим HTTP-запрос на добавление контакта:
URL запроса:
https://{user_account}.amocrm.ru/api/v4/contacts
метод: POST, формат данных: text/plain.
В заголовке запроса передаем:
[
{
"name": "{{ s7.body.contactName }}",
"custom_fields_values": [
{
"field_code": "PHONE",
"values": [
{
"value": "{{ s7.body.contactPhone }}"
}
]
},
{
"field_code": "EMAIL",
"values": [
{
"value": "{{ s7.body.contactEmail }}"
}
]
}
]
}
]
После модуля с условием "телефон найден" создадим HTTP-запрос на обновление существующего контакта.
URL запроса:
https://{user_account}.amocrm.ru/api/v4/contacts/{{ s9.body._embedded.contacts.0.id }}
метод: PATCH, формат данных: text/plain.
В заголовке запроса передаем:
{
"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-обработке входящего сообщения.
Теперь сценарий позволяет создать контакт, а затем обновить его же. Временно включим сценарий и отправим сообщение:
Перейдя на страницу сценария, увидим, по какой ветке он сработал:
В результате выполнения сценария в системе amoCRM появился контакт:
Теперь повторим сообщение боту, на этот раз добавив email в соответствующее поле по заданному формату сообщения:
Теперь сценарий сработал по ветке, соответствующей тому условию, что контакт с таким телефоном уже существует:
В amoCRM видим, что контакт обновился:
Создадим модули IF, проверяющие условия, что методы запросов на создание и обновление контакта вернули ответы, свидетельствующие об успешном выполнении операции, и разместим их после соответствующих HTTP-модулей.
Контакт создан:
{{ s13.body._embedded.contacts.0.id is defined }}
Контакт обновлен:
{{ s14.body.id is defined }}
После модуля условия 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 была добавлена сделка и связанный с ней контакт:
Затем отдельной операцией обновлен этот контакт, созданный при добавлении сделки:
А также был добавлен еще один новый контакт:
Оставить комментарий