The last notes
All English-language materials have been translated fully automatically using the Google service
Statement of the problem: You need to send Vkontakte users automatic messages on behalf of the group if the associated leads in Bitrix24 have a certain status and the specified amount of time has passed. If the user starts chatting, then sending should stop
Lead Association will remain outside the parentheses of this article. It can be done using the appropriate plugins Vkontakte
or manually using API
Let's solve the problem using two scripts. The first one will regularly poll Bitrix24 for new users with the required statute. The second will send a message to these users.
We will also have a pane table in which we will store all the results
Structure of HL
tables
Type: string; Name: UF_NAME; Name: Name
Type: string; Name: UF_LASTNAME; Name: Surname
Type: string; Name: UF_VK_ID; Name: VK Id
Type: string; Name: UF_VK_LINK; Name: Vk link
Type: Yes / No; Name: UF_1DAY_SEND; Name: 1D SMS
Type: Yes / No; Name: UF_2DAY_SEND; Name: 2D SMS
Type: Yes / No; Name: UF_5DAY_SEND; Name: 5D SMS
Type: Yes / No; Name: UF_7DAY_SEND; Name: 7D SMS
Type: Yes / No; Name: UF_30DAY_SEND; Name: 30D SMS
Type: Date with time; Name: UF_DATE_STATUS_CHANG; Title: Start date; Default value: current time
Type: Integer; Name: UF_BITRIX24; Title: Lead ID
Type: String; Name: UF_VK_PREFIX; Name: VK prefix
Type: Yes / No; Name: UF_ACTIVE; Title: Activity
We will also need 4 small helper classes
Listing 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('*')
);
// Data
$arData = $entity_data_class::getList($ar);
$arData = new CDBResult($arData, $dbClass);
while($arResult = $arData->Fetch()){
$result[]=$arResult;
}
return $result;
}
/ * Single entry update * /
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());
}
}
}
Listing 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;
}
}
Listing of the file 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);
}
}
Listing of the file 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);
}
}
Listing of the file getStatusFromBitrix.php
// Don't forget to calculate the correct path to the site folder
$_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;
// Current time in Moscow
$date = new DateTime();
$hour = date("H");
$data = $common = array();
// We work only during the day
if($hour>21 || $hour<8){die();}
// Recursively iterate over all users matching the request condition
function getLeads($id=0,$arData = array()){
$bitrix24 = new bitrix24;
// Select fields
$arSelect = array('ID', 'TITLE', 'NAME', 'LAST_NAME', 'ASSIGNED_BY_ID', 'UF_CRM_435324332', 'WEB');
// Filter
$arFilter = array(
'order' => array('ID'=>'DESC'),
'select' => $arSelect,
"filter" => array(
'UF_CRM_435324332' => array(2078,2079), // "Send messages" status and "Start chatting" status
"!WEB" => false, // Link is complete
)
);
if($id!=0){
$arFilter['filter']['<ID'] = $id;
}
// Get a list of users who have the WEB parameter,
// and whose status (UF_CRM_435324332) is set to "Send messages"
$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){
// Get the link to the page
$link = explode('/',$value['WEB'][0]['VALUE']);
// Get the last index of the array
$lastKey = key(array_slice($link, -1, 1, true));
$vkID = 0;
if($link){
// Get information about the user
$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'){// Status "Send messages"
$arProps['UF_ACTIVE']=1;
}
if($value['UF_CRM_435324332']=='2079'){// Status "Started chatting"
$arProps['UF_ACTIVE']=0;
}
$user = $tHigh->getHighloadData(HL_TABLE_ID,'HL_TABLE_NAME', array('UF_BITRIX24' => $value['ID']));
// If the statuses haven't changed, then we do nothing
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);
}
}
Listing of the file 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;
// Current time in Moscow
$date = date("Y-m-d H:i:s");
$hour = date("H");
$data = array();
// We work only during the day
if($hour>21 || $hour<8){die();}
$ messages = array (
'1' => 'Hello # Name #. This is test message 1 ',
'2' => 'This is test message 2',
'3' => '# Name #, This is test message 3',
'7' => 'This is test message 4',
'30' => 'This is test message 5'
);
$users = $tHigh->getHighloadData(HL_TABLE_ID,'HL_TABLE_NAME', array('UF_ACTIVE'=>'1'));
foreach ($users as $key => $u){
if(!$u['UF_VK_ID']){
// Get the link to the page
$link = explode('/',$u['UF_VK_LINK']);
// Get the last index of the array
$lastKey = key(array_slice($link, -1, 1, true));
if($link){
// Get information about the user
$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']
);
// Find out the difference in dates
$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){// A day later
// Create parameters for sending messages
$data['MESSAGE'] = $messages[1];
$arProps['UF_1DAY_SEND'] = 1;
}
if($u['UF_2DAY_SEND'] == 0 && $diff['hours']>48){// Two days later
// Create parameters for sending messages
$data['MESSAGE'] = $messages[2];
$arProps['UF_2DAY_SEND'] = 1;
}
if($u['UF_3DAY_SEND'] == 0 && $diff['hours']>120){// After 5 days
// Create parameters for sending messages
$data['MESSAGE'] = $messages[3];
$arProps['UF_3DAY_SEND'] = 1;
}
if($u['UF_7DAY_SEND'] == 0 && $diff['hours']>168){// After 7 days
// Create parameters for sending messages
$data['MESSAGE'] = $messages[7];
$arProps['UF_7DAY_SEND'] = 1;
}
if($u['UF_30DAY_SEND'] == 0 && $diff['hours']>720){// After 30 days
// Create parameters for sending messages
$data['MESSAGE'] = $messages[30];
$arProps['UF_30DAY_SEND'] = 1;
}
if(isset($data['MESSAGE'])){
// Send a message to VKontakte
$vkAnswer = json_decode($tVK->sendMessage($data));
if(!isset($vkAnswer->error)){
// Update the record in the database
$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);
}
}
}
Now it remains to configure the launch of the last two files through crowns. Calling crowns:
crontab -u bitrix -e
Add records with execution every hour at 10 and 15 minutes
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
Updating Crowns
systemctl restart crond.service
Comments