HEX
Server: nginx/1.18.0
System: Linux test-ipsremont 5.4.0-214-generic #234-Ubuntu SMP Fri Mar 14 23:50:27 UTC 2025 x86_64
User: ips (1000)
PHP: 8.0.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
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'];
    }

}