К нам обратилась компания “Твой Знакомый Юрист” с целью внедрения сервиса, который позволял бы их клиентам самостоятельно отслеживать статусы своих дел по аналогии с отслеживанием доставки писем в почте России.
Компания уже пользовалась crm Bitrix24, поэтому было решено брать информацию прямо из crm. Однако из-за тарифа “стандартный”, воспользоваться бизнес-процессами было невозможно.
Мы определили такой алгоритм решения задачи:
2. В этой странице клиенты заполняют поле с номером телефона,
3. После заполнения поля отправляется запрос в Bitrix24,
4. Bitrix24 получает этот запрос и отправляет отфильтрованные данные,
5. Клиент на сайте видит нужные данные о статусе своей сделки.
Разберем реализацию подробнее.
Для отслеживания клиентами статуса своих сделок в Bitrix24 нужно:
- Создать пользовательское поле в Bitrix24 типа “строка”
- На каждую стадию сделки добавить и настроить робота “Изменить элемент”
- Создать отдельный файл формы с разрешением .php
- Стили для файла формы с разрешением .css
- Backend для получения информации с Bitrix 24
- JS скрипт для реализации вывода на видимую часть для пользователей без перезагрузки страницы
- Размещение на сайте
Теперь подробно разберем каждый шаг.
Создаем пользовательское поле в Bitrix24 типа “строка”
Первым делом в карточке сделок нужно создать пользовательское поле с помощью кнопки “Создать поле“. Так же создать поле можно через меню настроек:
(Настройки > Настройки CRM > Настройки форм и отчетов > Пользовательские поля)
В данном поле у нас будет находится информация о статусе сделки, и именно это мы выведем клиентам в дальнейшем. Для того, чтобы заполнять поле нужным текстом, нужно добавить робота. Об этом ниже.
На каждую стадию сделки добавить и настроить робота “Изменить элемент”
Заполняют данное поле роботы (Изменить элемент), в зависимости от стадии, содержание поля будет разным
Создаем отдельный файл формы с разрешением .php
Как создавать и редактировать подобные файлы читайте в статье на нашем сайте.
1) Создадим файл с расширением .php и html разметку в нём
Добавим поле ввода для клиентов, и кнопку для получения информации
<div class="title-form"> Узнайте статус своего дела</div>
<div class="phone-text-form"> Для этого введите номер телефона, <br>указанный в договоре с нами</div>
<form class="form-active" action='b24.php' method='post'>
<input class="phone-number-text" type="text" id="phone">
<button class="phone-number-button"type="button" id="button">
Узнать статус дела
</button>
</form>
<div id="area" class="area-form"></div>
</form>
Подключаем Jquery и наш файл скриптов
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="scripts.js"></script>
Стилизуем нашу форму
Создаем файл с разрешением .css и подключаем к форме
<link rel="stylesheet" href="style.css">
Не забываем изначально сбросить стандартные стили, я использовал github.com/necolas/normalize.css
Backend для получения информации с Bitrix 24
Создаем файл с расширением .php (к примеру b24.php)
Для получения информации с Битрикс 24 нам понадобятся вебхуки. Как их создавать и использовать вы можете узнать в нашей статье (статья о вебхуках).
Основная задача – найти всех клиентов по номеру телефона, и уже по данным клиента получить его сделки. Будем использовать следующие методы REST (ссылка на документацию):
crm.duplicate.findbycomm – для поиска id контакта по номеру (в нашем случае контакт у номера всегда один)
crm.deal.list (можно сделать ссылку на метод в документации rest битрикс24) – для поиска сделок по id контакта
Получаем данные:
Используем curl запрос с 2 вебхуками (сначала crm.duplicate.findbycomm, затем crm.deal.list), на выходе будет список сделок, отфильтрованный по номеру клиента, в качестве аргумента будет переменная (номер который ввёл клиент) полученная с JS скрипта Ajax’ом
$curl = curl_init();
curl_setopt_array(
$curl,
[
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $queryUrl,
CURLOPT_POSTFIELDS => http_build_query($queryData)
]
);
Используем фильтры
$queryData = [
'type' => 'PHONE',
'values' => $phone,
'entity_type' => 'CONTACT'
];
$queryData = [
'filter' => [
'CONTACT_ID' => $contactId,
'CATEGORY_ID' => '0' //Фильтр по воронке
],
'select' => ['UF_*'] //отображение пользовательских полей
];
Итоговый код функции
function get_deal($phoneForm)
{
$queryUrl = ''; //в '' url вебхука который ищет ID контакта по по номеру
$phone = [
$phoneForm
];
$queryData = [
'type' => 'PHONE',
'values' => $phone,
'entity_type' => 'CONTACT'
];
$curl = curl_init();
curl_setopt_array(
$curl,
[
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $queryUrl,
CURLOPT_POSTFIELDS => http_build_query($queryData)
]
);
$contactId = curl_exec($curl);
curl_close($curl);
$contactId = strstr($contactId, '[');
$contactId = strstr($contactId, ']', true);
$contactId = trim($contactId, '['); //срезаем лишнее
$queryUrl = ''; //в '' url вебхука который ищет сделки по контакту
$queryData = [
'filter' => [
'CONTACT_ID' => $contactId,
'CATEGORY_ID' => '0' //Воронка Защита прав потребителей
],
'select' => ['UF_*'] //отображение пользовательских полей
];
$curl = curl_init();
curl_setopt_array(
$curl,
[
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_POST => true,
CURLOPT_HEADER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $queryUrl,
CURLOPT_POSTFIELDS => http_build_query($queryData)
]
);
$deal = curl_exec($curl);
curl_close($curl);
return $deal;
}
Информация по текстовым полям приходит из Б24 в виде юникода, необходимо преобразить в читабельный вариант.
Пример полученных данных с поля в Б24: “SOURCE_DESCRIPTION”:”\u041d\u0430\u0432\u044f\u0437\u0430\u043b\u0438 \u043f\u043e\u0440\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e \u041e\u041e\u041e \u0411\u0420\u041e\u041a\u0415\u0420 \u043f\u043e \u043a\u0440\u0435\u0434\u0438\u0442\u0443 \u0432 \u0411\u044b\u0441\u0442\u0440\u043e\u0411\u0430\u043d\u043a\u0435 \u043d\u0430 \u0441\u0443\u043c\u0443 107 \u0442\u044b\u0441\u044f\u0447
Для этого будем использовать функции раскодировки
function replace_unicode_escape_sequence($match) {
return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
} //Функции раскодировки
function unicode_decode($str) {
return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', 'replace_unicode_escape_sequence', $str);
}
Необходимо разделить строку по полям, т.к нам нужны не все поля, а только поля ответчик и стадия.
Преобразуем строку с REST в массив, разделитель будет ‘UF_CRM_’.
$text = explode('UF_CRM_', $result);
Получаем нужные поля и смотрим их наличие
Фильтровать будем по ID (как его получить), в данном случае ID нужного нам поля 1653490399007
foreach ($text as $elem) {
$check = stripos($elem,'1653490399007'); //пользовательское поле с б24
if ($check === 0){ //Проверка существование поля
$elem = str_replace('1653490399007\":\"', '' ,$elem);
$elem = unicode_decode($elem); //Раскодируем
$elem = str_replace($unnchars, '', $elem);
$elem = stripslashes($elem);
$respondent[] = 'По делу с ' . trim($elem) . ':' . '.*_';
// .*_ - разделитель для JS скрипта
}
}
В дальнейшем полученную информацию передаем JS скрипту, который выведет данные клиенту
JS скрипт
Скрипт у нас будет отдельным файлом в разрешении .js
Основная задача – вывести информацию, полученную с backend клиенту.
Создадим функцию, которая создаст div’ы, в случае пустоты в запросах
(информация с поля равна null (строковое значение)), выведем соответствующее сообщение, что информация не найдена.
Связь между JS и PHP будем выполнять с помощью Ajax.
function getData(){
let phone = document.getElementById('phone').value;
$.ajax({ //запрос на сервер для получения данных с б24
type: "GET",
url: '', //в '' название файла из шага 3, например b24.php
data: {value: phone},
success: function (data) {
dataarr = data.split('.*_');
let index = 0;
dataarr.pop();
clear(document.querySelectorAll('.element-form'));
index = 0;
let result = dataarr.filter((_, index)=>index % 2 !== 0).concat(dataarr.filter((_, index)=>index % 2 === 0));
let deal = result.slice(result.length / 2);
let status = result.slice(0, result.length / 2);
let nothingFound = true;
deal.forEach((element) => { //обход массива и создание div
if (status[index].indexOf('null') === -1 && deal[index].indexOf('null') === -1) {
let area = document.getElementById('area');
let newDeal = document.createElement('div');
newDeal.className = 'element-form';
area.appendChild(newDeal);
newDeal.textContent = element;
let newStatus = document.createElement('div');
newStatus.className = 'element-form';
area.appendChild(newStatus);
newStatus.textContent = status[index];
nothingFound = false;
}
index++
})
if (nothingFound) {
let newDeal = document.createElement('div');
let area = document.getElementById('area');
newDeal.className = 'element-form';
area.appendChild(newDeal);
newDeal.textContent = 'Дела с таким номером телефона не найдены. \n' +
'Попробуйте еще раз, проверив предварительно номер телефона: он должен совпадать с номером, указанным в договоре с нами';
}
}
});
}
Необходимо назначить выполнение функции на клик мыши по кнопке, а так же на клавишу Enter.
let button = document.getElementById('button');
button.addEventListener('click', () => {
getData();
}
)
$(document).keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
getData();
}
});
Не забываем создать функцию очистки в случае набора клиентом другого номера. Клиент может ошибиться в наборе, или ввести чужой.
Данная функция стирает ранее заполненные данные и добавляет новые.
function clear(elems) {
if (elems.length > 0) {
elems.forEach((clearelem) => {
clearelem.remove();
})
}
}
Результат работы:
При совпадении набранного клиентом номера с номером контакта в существующей сделке выводим пользовательское поле
Обратная ситуация, когда информация по сделкам не найдена
Размещение на сайте
Для размещения на сайте нужно переместить файлы на сайт, пути разные, в зависимости от структуры и процесса работы с сайтом.
1) Это можно сделать через файловый менеджер в вашем хостинге.
2) С помощью FTP Клиента FileZilla, предварительно соединившись по данным с вашего хостинга.
3) С помощью вкладки Deployment в IDE, но данный вариант уже требует соответствующих технических знаний для настройки.
После размещения на сайте вам необходимо настроить редирект, либо же изначально правильно создавать структуру размещения, это уже индивидуально.
Если у вас есть какие-то вопросы, свяжитесь с нами.