Rus
Eng
Автоматическая отправка сообщений в ВК пользователю по статусу в Битрикс24

Постановка задачи: нужно отправлять пользователям Вконтакте автоматические сообщения от имени группы если у ассоциированных лидов в Битрикс24 стоит определенный статус и прошло заданное кол-во времени. Если пользователь начинает общаться, то отправка должна прекратиться

Ассоциация лидов останется за скобками данного материала. Ее можно провести с помощью соответствующих плагинов Вконтакте или вручную с помощью API

Задачу решим использованием двух скриптов. Первый будет на регулярной основе опрашивать Битрикс24 на предмет новых пользователей с искомым статутом. Второй будет отправлять этим пользователям сообщение.

Так же у нас будет таблица-прокладка в которой мы будем хранить все результаты

Структура HL таблицы

Тип: строка; 			Имя: UF_NAME; 				Название: Имя
Тип: строка; 			Имя: UF_LASTNAME; 			Название: Фамилия
Тип: строка; 			Имя: UF_VK_ID; 				Название: ВК Id
Тип: строка; 			Имя: UF_VK_LINK; 			Название: Вк ссылка
Тип: Да/Нет; 			Имя: UF_1DAY_SEND; 			Название: 1D СМС
Тип: Да/Нет; 			Имя: UF_2DAY_SEND; 			Название: 2D СМС
Тип: Да/Нет; 			Имя: UF_5DAY_SEND; 			Название: 5D СМС
Тип: Да/Нет; 			Имя: UF_7DAY_SEND; 			Название: 7D СМС
Тип: Да/Нет; 			Имя: UF_30DAY_SEND; 		Название: 30D СМС
Тип: Дата со временем; 	Имя: UF_DATE_STATUS_CHANG; 	Название: Дата начала; Значение по умолчанию: текущее время
Тип: Целое число; 		Имя: UF_BITRIX24; 			Название: Lead ID
Тип: Строка; 			Имя: UF_VK_PREFIX; 			Название: Префикс ВК
Тип: Да/Нет; 			Имя: UF_ACTIVE; 			Название: Активность

В Битрикс24 есть кастомное поле UF_CRM_435324332 - в нем хранится кастомная группа пользователей, а так же стандартное поле WEB в котором лежит ссылка на профиль пользователя в ВК

Так же нам понадобятся 4 небольших класса помощника

Листинг high.php

use Bitrix\Highloadblock\HighloadBlockTable;

class tHighload {
    public function getHighloadData($id,$dbClass,$arFilter = array()){
        $hlblock   = Bitrix\Highloadblock\HighloadBlockTable::getById( $id )->fetch();
        $entity   = Bitrix\Highloadblock\HighloadBlockTable::compileEntity( $hlblock );
        $entity_data_class = $entity->getDataClass();

        $ar = array(
            "filter" => $arFilter,
            "select" => array('*')
        );

        // Данные
        $arData = $entity_data_class::getList($ar);

        $arData = new CDBResult($arData, $dbClass);

        while($arResult = $arData->Fetch()){
            $result[]=$arResult;
        }

        return $result;
    }

    /*Апдейт одиночной записи*/
    public function updateHighloadData($id,$data){
        $hlblock   = Bitrix\Highloadblock\HighloadBlockTable::getById( $id )->fetch();
        $entity   = Bitrix\Highloadblock\HighloadBlockTable::compileEntity( $hlblock );
        $entity_data_class = $entity->getDataClass();

        $elId = $data['ID'];
        unset($data['ID']);

        $result = $entity_data_class::update($elId, $data);

        return $result;
    }

    public function setHighloadData($id, $arProps){
        $hlblock   = Bitrix\Highloadblock\HighloadBlockTable::getById( $id )->fetch();
        $entity   = Bitrix\Highloadblock\HighloadBlockTable::compileEntity( $hlblock );
        $entity_data_class = $entity->getDataClass();

        $otvet = $entity_data_class::add($arProps);

        if ($otvet->isSuccess()) {
            return 'Success';
        } else {
            return implode(', ', $otvet->getErrors());
        }
    }
}

Листинг date.php

class tDate {
    public function dateGap($date1, $date2)
    {
        $time = new DateTime($date1);

        $since_time = $time->diff( new DateTime($date2) );

        $A['days'] = $since_time->days;
        $A['hours'] = $since_time->days * 24 + $since_time->h;
        $A['minutes'] = ($since_time->days * 24 * 60) + ($since_time->h * 60) + $since_time->i;

        return $A;
    }
}

Листинг файла bitrix24.php

class bitrix24 {
    public function getLeadList($arSelect, $arFilter){

        $queryUrl = 'https://BITRIX24_SERVER/REST_API_HOOK_PATH/crm.lead.list'; //Список сделок

        $queryData = http_build_query($arFilter);

        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_SSL_VERIFYPEER => 0,
            CURLOPT_POST => 1,
            CURLOPT_HEADER => 0,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_URL => $queryUrl,
            CURLOPT_POSTFIELDS => $queryData,
        ));

        $result = curl_exec($curl);
        curl_close($curl);

        return json_decode($result);
    }
}

Листинг файла vk.php

class tVK
{
    const TOKEN = 'TOKEN';

    public function curlGet($url){
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $response = curl_exec($ch);
        curl_close($ch);

        return $response;
    }

    public function getUserInfo($user_id){
        $url='https://api.vk.com/method/users.get?user_ids='.$user_id.'&fields=bdate,photo_200,status&access_token='.self::TOKEN.'&v=5.41';

        $response=$this->curlGet($url);

        return $response;
    }

    public function sendMessage($data){
        $params = array(
            'message' => str_replace("#Имя#", $data['USER_NAME'], $data['MESSAGE']),
            'user_id' => $data['USER_ID'],
            'access_token' => self::TOKEN,
            'v' => '5.81'
        );

        $query = http_build_query($params);

        return file_get_contents('https://api.vk.com/method/messages.send?' . $query);
    }

}

Листинг файла getStatusFromBitrix.php

//Не забываем рассчитать правильный путь к папке сайта
$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/../..");
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];

define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS",true);
define("BX_CRONTAB", true);
define('BX_NO_ACCELERATOR_RESET', true);

require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");

use Bitrix\Main\Type\DateTime;

@set_time_limit(0);
@ignore_user_abort(true);

require_once ($_SERVER['DOCUMENT_ROOT'].'/PATH_TO_PROJECT/lib/bitrix24.php');
require_once ($_SERVER['DOCUMENT_ROOT'].'/PATH_TO_PROJECT/libs/high.php');
require_once ($_SERVER['DOCUMENT_ROOT'].'/PATH_TO_PROJECT/libs/vk.php');

$tHigh = new tHighload;
$tVK = new tVK;

//Текущее время по Москве
$date = new DateTime();
$hour = date("H");
$data = $common = array();

//Работаем только днем
if($hour>21 || $hour<8){die();}

//Рекурсивно перебираем всех подходящих под условие запроса пользователей
function getLeads($id=0,$arData = array()){
    $bitrix24 = new bitrix24;

    //Выбираем поля
    $arSelect = array('ID', 'TITLE', 'NAME', 'LAST_NAME', 'ASSIGNED_BY_ID', 'UF_CRM_435324332', 'WEB');

    //Фильтруем
    $arFilter = array(
        'order' => array('ID'=>'DESC'),
        'select' => $arSelect,
        "filter" => array(
            'UF_CRM_435324332' => array(2078,2079), //Статус "Рассылать сообщения" и Статус "Начал общаться"
            "!WEB" => false, //Ссылка заполнена
        )
    );

    if($id!=0){
        $arFilter['filter']['<ID'] = $id;
    }

    //Получаем список пользователей у которыех есть параметр WEB, 
    // и у которых статус (UF_CRM_435324332) установлен в "Рассылать сообщения"
    $result = json_decode(json_encode($bitrix24->getLeadList($arSelect,$arFilter)), True);

    foreach ($result['result'] as $key => $value){
        $arData[] = $value;
    }

    if($result['next']==50){
        $arData = getLeads($result['result'][49]['ID'],$arData);
    }

    return $arData;
}


$common = getLeads();
$bitrix24 = new bitrix24;

foreach ($common as $key => $value){

    //Получаем ссылку на страницу
    $link = explode('/',$value['WEB'][0]['VALUE']);
    //Получаем последний индекс массива
    $lastKey = key(array_slice($link, -1, 1, true));

    $vkID = 0;
    if($link){
        //Получаем информацию о пользователе
        $getId = json_decode($tVK->getUserInfo($link[$lastKey]));
        $vkID = $getId->response[0]->id;
    }

    $arProps = array(
        'UF_NAME' => $value['NAME'],
        'UF_LASTNAME' => $value['LAST_NAME'],
        'UF_VK_ID' => $vkID,
        'UF_VK_LINK' => $value['WEB'][0]['VALUE'],
        'UF_DATE_STATUS_CHANG' => $date->toString(),
        'UF_BITRIX24' => $value['ID'],
        'UF_VK_PREFIX' => $link[$lastKey]
    );

    if($value['UF_CRM_435324332']=='2078'){//Статус "Рассылать сообщения"
        $arProps['UF_ACTIVE']=1;
    }

    if($value['UF_CRM_435324332']=='2079'){//Статус "Начал общаться"
        $arProps['UF_ACTIVE']=0;
    }

    $user = $tHigh->getHighloadData(HL_TABLE_ID,'HL_TABLE_NAME', array('UF_BITRIX24' => $value['ID']));

    //Если статусы не изменились, то ничего не делаем
    if($arProps['UF_ACTIVE']==$user[0]['UF_ACTIVE']){continue;}

    if($user){
        $arProps['ID'] = $user[0]['ID'];
        $res = $tHigh->updateHighloadData(HL_TABLE_ID, $arProps);
    }else{
        $res = $tHigh->setHighloadData(HL_TABLE_ID, $arProps);
    }

}

Листинг файла checkIfNeedSMS.php

$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/../..");
$DOCUMENT_ROOT = $_SERVER["DOCUMENT_ROOT"];

define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS",true);
define("BX_CRONTAB", true);
define('BX_NO_ACCELERATOR_RESET', true);

require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");

use Bitrix\Main\Type\DateTime;

@set_time_limit(0);
@ignore_user_abort(true);

require_once ($_SERVER['DOCUMENT_ROOT'].'/PATH_TO_PROJECT/libs/high.php');
require_once ($_SERVER['DOCUMENT_ROOT'].'/PATH_TO_PROJECT/libs/vk.php');
require_once ($_SERVER['DOCUMENT_ROOT'].'/PATH_TO_PROJECT/libs/date.php');

$tHigh = new tHighload;
$tVK = new tVK;

$tDate = new tDate;

//Текущее время по Москве
$date = date("Y-m-d H:i:s");
$hour = date("H");
$data = array();

//Работаем только днем
if($hour>21 || $hour<8){die();}

$messages = array(
    '1' => 'Привет #Имя#. Это тестовое сообщение 1',
    '2' => 'Это тестовое сообщение 2',
    '3' => '#Имя#, Это тестовое сообщение 3',
    '7' => 'Это тестовое сообщение 4',
    '30' => 'Это тестовое сообщение 5'
);

$users = $tHigh->getHighloadData(HL_TABLE_ID,'HL_TABLE_NAME', array('UF_ACTIVE'=>'1'));

foreach ($users as $key => $u){

    if(!$u['UF_VK_ID']){
        //Получаем ссылку на страницу
        $link = explode('/',$u['UF_VK_LINK']);
        //Получаем последний индекс массива
        $lastKey = key(array_slice($link, -1, 1, true));

        if($link){
            //Получаем информацию о пользователе
            $getId = json_decode($tVK->getUserInfo($link[$lastKey]));
            $u['UF_VK_ID'] = $getId->response[0]->id;
        }
    }

    $arProps = array(
        'ID' => $u['ID'],
        'UF_NAME' => $u['UF_NAME'],
        'UF_LASTNAME' => $u['UF_LASTNAME'],
        'UF_VK_ID' => $u['UF_VK_ID'],
        'UF_VK_LINK' => $u['UF_VK_LINK'],
        'UF_BITRIX24' => $u['UF_BITRIX24'],
        'UF_VK_PREFIX' => $u['UF_VK_PREFIX']
    );

    //Выясняем разницу в датах
    $diff = $tDate->dateGap($u['UF_DATE_STATUS_CHANG'],$date);

    $data = array(
        'USER_ID' => $u['UF_VK_ID'],
        'USER_NAME' => $u['UF_NAME'] ? $u['UF_NAME'] : $u['UF_LASTNAME']
    );

    if($u['UF_1DAY_SEND'] == 0 && $diff['hours']>24){//Спустя сутки
        //Составляем параметры отправки сообщений
        $data['MESSAGE'] = $messages[1];
        $arProps['UF_1DAY_SEND'] = 1;
    }

    if($u['UF_2DAY_SEND'] == 0 && $diff['hours']>48){//Спустя двое суток
        //Составляем параметры отправки сообщений
        $data['MESSAGE'] = $messages[2];
        $arProps['UF_2DAY_SEND'] = 1;
    }

    if($u['UF_3DAY_SEND'] == 0 && $diff['hours']>120){//Спустя 5 суток
        //Составляем параметры отправки сообщений
        $data['MESSAGE'] = $messages[3];
        $arProps['UF_3DAY_SEND'] = 1;
    }

    if($u['UF_7DAY_SEND'] == 0 && $diff['hours']>168){//Спустя 7 суток
        //Составляем параметры отправки сообщений
        $data['MESSAGE'] = $messages[7];
        $arProps['UF_7DAY_SEND'] = 1;
    }

    if($u['UF_30DAY_SEND'] == 0 && $diff['hours']>720){//Спустя 30 суток
        //Составляем параметры отправки сообщений
        $data['MESSAGE'] = $messages[30];
        $arProps['UF_30DAY_SEND'] = 1;
    }

    if(isset($data['MESSAGE'])){

        //Отправляем сообщение во вконтакте
        $vkAnswer = json_decode($tVK->sendMessage($data));

        if(!isset($vkAnswer->error)){
            //Обновляем запись в БД
            $tHigh->updateHighloadData(HL_TABLE_ID, $arProps);
        }else{
            $filename = '/tmp/checkIfNeedSMS.log';

            $data = $vkAnswer->error;
            file_put_contents($filename, date('[Y-m-d H:i:s] ') . print_r($data, true) . PHP_EOL, FILE_APPEND | LOCK_EX);
        }

    }
}

Теперь осталось настроить запуск двух последних файлов через крон. Вызов крон:

crontab -u bitrix -e

Добавляем записи с выполнением каждый час в 10 и 15 минуты

10 */1 * * * php -f /PATH_TO_YOUR_PROJECT/getStatusFromBitrix.php > /tmp/getStatusFromBitrix.log
15 */1 * * * php -f /PATH_TO_YOUR_PROJECT/checkIfNeedSMS.php > /tmp/checkIfNeedSMS.log

Обновляем крон

systemctl restart crond.service

Комментарии

Комментариев еще нет, Вы можете стать первым кто его оставит

Оставьте комментарий

На сайте используется система премодерирования комментариев, поэтому ваше сообщение будет опубликовано лишь после одобрения модератором

Вы отвечаете на комментарий пользователя

Отправить

ОБРАТНАЯ СВЯЗЬ

Напишите мне

Вы разрабатываете новый сервис, вносите доработки в существующий и хотите лучше чем у конкурентов? Вы обратились по адресу. Предлагаю вам комплексную разработку сайтов студийного уровня. У меня вы можете заказать дизайн, верстку, програмированние, разработку нетрадиционного функционала, реализацию связи между CMS, CRM и Data Analitics, а так же все остальное касаемое сайтов, кроме продвижения.

Обращайтесь, я всегда проконсультирую по всем вопросам и помогу подобрать наиболее эффективное решение для Вашего бизнеса. Я занимаюсь созданием сайтов в Новосибирске и в других регионах России, также работаю со странами СНГ. Вы останетесь довольны нашим сотрудничеством

Во время отправки произошла ошибка, пожалуйста попробуйте еще раз через некоторое время
Сообщение отправлено успешно

Телефоны

+7(993) 007-18-96

Email

info@tichiy.ru

Адрес

Россия, г. Москва

Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта

Написать мне
Отправить
Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта
Отправка успешна!
Thank you for your feedback. I will answer you within the next working hours
Отправка не удалась
Во время отправки запроса произошла ошибка. Пожалуйста, подождите и попробуйте снова через некоторое время или свяжитесь со мной