File: //var/www/quadcode/app/Helpers/BitrixHelper.php
<?php
namespace App\Helpers;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class BitrixHelper
{
// https://apidocs.bitrix24.ru/
private string $host;
private int $userId;
private string $token;
public const LOG_CHANNEL = 'bitrix';
public const ENTITY_ID_STATUS = 'STATUS';
public const ENTITY_ID_DEAL_STAGE = 'DEAL_STAGE';
public const STATUS_JUNK = 'JUNK';
public const STATUS_GIVEAWAY = 'UC_4B9543';
public const DEAL_STAGE_APOLOGY = 'APOLOGY';
public const DEAL_STAGE_NOT_ANSWERED = 'LOSE';
public const DEAL_STAGE_WON = 'WON';
public const CUSTOM_FIELD_LANDING_URL = 'UF_CRM_1708364992';
public const CUSTOM_FIELD_GCLID = 'UF_CRM_1708366868784';
public const CUSTOM_FIELD_LANG = 'UF_CRM_1708365178';
public const CUSTOM_FIELD_BUSINESS_IDENTIFICATION = 'UF_CRM_1709012311521';
public const CUSTOM_FIELD_INITIAL_INVESTMENT = 'UF_CRM_1708365367';
public const CUSTOM_FIELD_REGION = 'UF_CRM_1708366122';
public const CUSTOM_FIELD_COUNTRY_CODE = 'UF_CRM_1708366441792';
public const CUSTOM_FIELD_UTM_CONTENT = 'UF_CRM_1712249375';
public const CUSTOM_FIELD_UTM_TERMS = 'UF_CRM_1712249249';
public const CUSTOM_FIELD_UTM_MEDIUM = 'UF_CRM_1712248114';
public const CUSTOM_FIELD_UTM_CAMPAIGN = 'UF_CRM_1712248092';
public const CUSTOM_FIELD_UTM_SOURCE = 'UF_CRM_1712248129';
public const CUSTOM_LEAD_MAGNET = 'UF_CRM_1726733528543';
public const CUSTOM_LANG_BY_BROWSER = 'UF_CRM_1728917539511';
public const CUSTOM_DEAL_COUNTRY_BY_IP = 'UF_CRM_660FA634CE713';
public const CUSTOM_ROISTAT_ID = 'UF_CRM_1744804235';
public const CUSTOM_FIELD_COMPANY_NAME = 'UF_CRM_COMPANY_TITLE';
public const CUSTOM_FIELD_SHORT_BIO = 'UF_CRM_1761209155062';
public const CUSTOM_FIELD_TG_CHANNEL = 'UF_CRM_1763371894';
public const CUSTOM_FIELD_INSTAGRAM = 'UF_CRM_1763371831';
public const CUSTOM_FIELD_YOU_TUBE = 'UF_CRM_1763371853';
public const CUSTOM_FIELD_TIK_TOK = 'UF_CRM_1763371879';
public const CUSTOM_FIELD_FTS_SUM = 'UF_CRM_1763371917';
public const CUSTOM_FIELD_HAS_NETWORK = 'UF_CRM_1763371959';
public const CUSTOM_FIELD_LAUNCH_REASON = 'UF_CRM_1761209155062'; // Why do you want to launch?
private static array $businessIdentifications = [
'Brokerage business' => '79',
'Introducing broker' => '81',
'Affiliate' => '83',
'Trader' => '85',
'Entrepreneur' => '87',
'Other' => '89',
];
private static array $initialInvestments = [
'$0' => '45',
'$1000' => '47',
'$5000' => '49',
'$10000' => '51',
'$25000' => '53',
'$50000' => '55',
'More then $50000' => '57',
];
private static array $regions = [
'Europe' => '69',
'North America' => '71',
'South America' => '73',
'Asia-Pacific' => '75',
'Africa' => '77',
'Middle East' => '1207',
];
private static array $customFields = [
'landing_url' => self::CUSTOM_FIELD_LANDING_URL,
'gclid' => self::CUSTOM_FIELD_GCLID,
'lang' => self::CUSTOM_FIELD_LANG,
'business_identification' => self::CUSTOM_FIELD_BUSINESS_IDENTIFICATION,
'initial_investment' => self::CUSTOM_FIELD_INITIAL_INVESTMENT,
'region' => self::CUSTOM_FIELD_REGION,
'country_code' => self::CUSTOM_FIELD_COUNTRY_CODE,
'utm_content' => self::CUSTOM_FIELD_UTM_CONTENT,
'utm_term' => self::CUSTOM_FIELD_UTM_TERMS,
'utm_medium' => self::CUSTOM_FIELD_UTM_MEDIUM,
'utm_campaign' => self::CUSTOM_FIELD_UTM_CAMPAIGN,
'utm_source' => self::CUSTOM_FIELD_UTM_SOURCE,
'lead_magnet' => self::CUSTOM_LEAD_MAGNET,
'lang_by_browser' => self::CUSTOM_LANG_BY_BROWSER,
'roistat_id' => self::CUSTOM_ROISTAT_ID,
'company_name' => self::CUSTOM_FIELD_COMPANY_NAME,
'short_bio' => self::CUSTOM_FIELD_SHORT_BIO,
'tg_channel' => self::CUSTOM_FIELD_TG_CHANNEL,
'instagram' => self::CUSTOM_FIELD_INSTAGRAM,
'youtube' => self::CUSTOM_FIELD_YOU_TUBE,
'tiktok' => self::CUSTOM_FIELD_TIK_TOK,
'ftd_sum' => self::CUSTOM_FIELD_FTS_SUM,
'has_network' => self::CUSTOM_FIELD_HAS_NETWORK,
'launch_reason' => self::CUSTOM_FIELD_LAUNCH_REASON,
];
public function __construct()
{
$this->host = config('bitrix.host');
$this->userId = config('bitrix.user_id');
$this->token = config('bitrix.token');
}
public function check(): bool
{
return !empty($this->host) && !empty($this->userId) && !empty($this->token);
}
public function convertLead(array $additional = []): array
{
$title = 'New lead from ' . $additional['landing_url'] . ' from ' . $additional['email'];
$data = [
'fields' => [
'TITLE' => $title,
'NAME' => $additional['first_name'],
'LAST_NAME' => $additional['last_name'] ?? null,
'COMMENTS' => $additional['message'] ?? null,
'PHONE' => [
[
'VALUE' => $additional['phone'],
'VALUE_TYPE' => 'WORK',
],
],
'EMAIL' => [
[
'VALUE' => $additional['email'],
'VALUE_TYPE' => 'WORK',
],
],
'UTM_CONTENT' => $additional['utm_content'] ?? null,
'UTM_TERM' => $additional['utm_term'] ?? null,
'UTM_MEDIUM' => $additional['utm_medium'] ?? null,
'UTM_CAMPAIGN' => $additional['utm_campaign'] ?? null,
'UTM_SOURCE' => $additional['utm_source'] ?? null,
],
];
if (!empty($additional['tg'])) {
$data['fields']['IM'][] = [
'VALUE' => $additional['tg'],
'VALUE_TYPE' => 'TELEGRAM',
];
}
if (!empty($additional['crm_status_id'])) {
$data['fields']['STATUS_ID'] = $additional['crm_status_id'];
}
$data['fields'] = array_filter($data['fields']);
$toUnset = ['first_name', 'last_name', 'message', 'phone', 'email', 'tg'];
foreach ($toUnset as $field) {
unset($additional[$field]);
}
foreach (self::$customFields as $field => $externalKey) {
if (!empty($additional[$field]) || 'calendly_scheduled' === $field) {
$data['fields'][$externalKey] = match ($field) {
'business_identification' => self::$businessIdentifications[$additional[$field]],
'initial_investment' => self::$initialInvestments[$additional[$field]],
'has_network' => 'yes' === $additional[$field],
default => $additional[$field],
};
if ('region' === $field) {
$data['fields'][$externalKey] = [];
foreach ($additional[$field] as $region) {
$data['fields'][$externalKey][] = self::$regions[$region];
}
}
unset($additional[$field]);
}
}
if (!empty($additional)) {
$data['fields']['SOURCE_DESCRIPTION'] = json_encode($additional, JSON_THROW_ON_ERROR);
}
return $data;
}
private function get(string $apiMethod, $data): Response
{
return Http::get($this->host . '/rest/' . $this->userId . '/' . $this->token . $apiMethod, $data);
}
public function getStatusList(array $filter): array
{
$data = ['filter' => $filter];
Log::channel(self::LOG_CHANNEL)->info('Get status list request', compact('data'));
$response = $this->get('/crm.status.list', $data)->json();
$response ??= [];
Log::channel(self::LOG_CHANNEL)->info('Get status list response', $response);
return $response;
}
public function addLead(array $data = []): array
{
$data = $this->convertLead($data);
Log::channel(self::LOG_CHANNEL)->info('Add lead request', compact('data'));
$response = $this->get('/crm.lead.add.json', $data)->json();
$response ??= [];
Log::channel(self::LOG_CHANNEL)->info('Add lead response', $response);
return $response;
}
public function leadList(array $filter, array $select = []): array
{
$data = [
'filter' => $filter,
'start' => 1,
];
if (!empty($select)) {
$data['select'] = $select;
}
Log::channel(self::LOG_CHANNEL)->info('Get lead list request', compact('data'));
$data['start'] = 1;
$response = $this->get('/crm.lead.list', $data)->json();
$index = 1;
Log::channel(self::LOG_CHANNEL)->info('Get lead list response #' . $index++, $response);
$leads = $response['result'];
while (isset($response['next'])) {
$data['start'] = $response['next'];
$response = $this->get('/crm.lead.list', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Get lead list response #' . $index++, $response);
$leads = array_merge($leads, $response['result']);
}
return $leads;
}
public function statusesList(array $filter): array
{
$data = ['filter' => $filter, 'start' => 1];
Log::channel(self::LOG_CHANNEL)->info('Get status list request', compact('data'));
$index = 1;
$response = $this->get('/crm.status.list', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Get status list response #' . $index++, $response);
$statuses = $response['result'];
while (isset($response['next'])) {
$data['start'] = $response['next'];
$response = $this->get('/crm.status.list', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Get status list response #' . $index++, $response);
$statuses = array_merge($statuses, $response['result']);
}
return $statuses;
}
public function updateLeadStatus(string $leadId, array $fields): array
{
$data = ['id' => $leadId, 'fields' => $fields];
Log::channel(self::LOG_CHANNEL)->info('Update lead status request', compact('data'));
$response = $this->get('/crm.lead.update', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Update lead status response', $response);
return $response;
}
public function dealList(array $filter, array $select = []): array
{
$data = [
'filter' => $filter,
'start' => 1,
];
if (!empty($select)) {
$data['select'] = $select;
}
Log::channel(self::LOG_CHANNEL)->info('Get deal list request', compact('data'));
$response = $this->get('/crm.deal.list', $data)->json();
$index = 1;
Log::channel(self::LOG_CHANNEL)->info('Get deal list response #' . $index++, $response);
$leads = $response['result'];
while (isset($response['next'])) {
$data['start'] = $response['next'];
$response = $this->get('/crm.deal.list', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Get deal list response #' . $index++, $response);
$leads = array_merge($leads, $response['result']);
}
return $leads;
}
public function contactsList(array $filter = [], array $select = []): array
{
$data = ['start' => 1];
if (!empty($filter)) {
$data['filter'] = $filter;
}
if (!empty($select)) {
$data['select'] = $select;
}
Log::channel(self::LOG_CHANNEL)->info('Get contact list request', compact('data'));
$response = $this->get('/crm.contact.list', $data)->json();
$index = 1;
Log::channel(self::LOG_CHANNEL)->info('Get contact list response #' . $index++, $response);
$leads = $response['result'];
while (isset($response['next'])) {
$data['start'] = $response['next'];
$response = $this->get('/crm.contact.list', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Get contact list response #' . $index++, $response);
$leads = array_merge($leads, $response['result']);
}
return $leads;
}
public function getContact(string|int $id): array
{
$data = ['id' => $id];
Log::channel(self::LOG_CHANNEL)->info('Get contact request', compact('data'));
$response = $this->get('/crm.contact.get', $data)->json();
Log::channel(self::LOG_CHANNEL)->info('Get contact response', $response);
return $response['result'];
}
}