Добавить повторный лид
Scope:
crmКто может выполнять методы: чтобы пройти сценарий целиком, нужно самое строгое из перечисленных прав — «право на создание лидов»
- crm.duplicate.findbycomm — пользователь с правом на чтение элементов CRM
- crm.lead.list — пользователь с правом на чтение лидов
- crm.lead.add — пользователь с правом на создание лидов
Выберите инструмент для разработки с AI-агентом:
- используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
- используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации
Когда клиент заполняет форму на сайте, его данные передаются в обработчик. Скрипт ищет в CRM совпадения по телефону или электронной почте среди лидов, контактов и компаний. Если совпадения найдены, лид помечается как повторный и привязывается к имеющейся записи. Такой подход помогает избежать дублей и повышает эффективность работы менеджеров.
В результате сценария в CRM появится новый лид. Если клиент уже обращался, у лида будут заполнены поля COMPANY_ID и CONTACT_ID — связь с компанией и контактом, которые получились из предыдущего обращения.
В Битрикс24 должен быть включен режим работы с повторными лидами. Подробнее читайте в статье Повторные лиды и сделки.
Настройка состоит из двух этапов:
-
Подготавливаем поля и размещаем форму на странице
-
Создаем файл-обработчик, который вызывает последовательно методы crm.duplicate.findbycomm, crm.lead.list, crm.lead.add
Что нужно до начала
-
в Битрикс24 включен режим работы с повторными лидами. Без него лид создастся, но повторным не станет
-
вебхук создан от имени пользователя с правом на создание лидов и на чтение элементов CRM
-
есть сервер, который отдает страницу с формой и принимает данные формы методом
POST. В примерах это Express для JS, PHP-скрипт и Flask для Python -
путь вебхука хранится в окружении, а не в коде страницы. Форма находится на публичной странице, и попадать в нее секрет не должен
1. Создаем веб-форму
Создаем HTML-форму с полями:
-
NAME— имя клиента, обязательное поле -
LAST_NAME— фамилия -
PHONE— телефон -
EMAIL— электронная почта
Форма передает данные методом POST в обработчик.
Как использовать примеры в документации
<form id="form_to_crm">
<input type="text" name="NAME" placeholder="Name" required>
<input type="text" name="LAST_NAME" placeholder="Last name">
<input type="text" name="PHONE" placeholder="Phone">
<input type="text" name="EMAIL" placeholder="E-mail">
<input type="submit" value="Submit">
</form>
<script>
document.getElementById('form_to_crm').addEventListener('submit', async (el) => {
el.preventDefault();
const formData = Object.fromEntries(new FormData(el.currentTarget).entries());
const response = await fetch('/form', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
});
const data = await response.json();
alert(data.message);
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#form_to_crm').on( 'submit', function(el) {//event submit form
el.preventDefault();//the default action of the event will not be triggered
var formData = $(this).serialize();
$.ajax({
'method': 'POST',
'dataType': 'json',
'url': '/form', // маршрут обработчика на Flask
'data': formData,
success: function(data){//success callback
alert(data.message);
}
});
});
});
</script>
<form id="form_to_crm">
<input type="text" name="NAME" placeholder="Name" required>
<input type="text" name="LAST_NAME" placeholder="Last name">
<input type="text" name="PHONE" placeholder="Phone">
<input type="text" name="EMAIL" placeholder="E-mail">
<input type="submit" value="Submit">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#form_to_crm').on( 'submit', function(el) {//event submit form
el.preventDefault();//the default action of the event will not be triggered
var formData = $(this).serialize();
$.ajax({
'method': 'POST',
'dataType': 'json',
'url': 'form.php', // файл для сохранения заполненных форм
'data': formData,
success: function(data){//success callback
alert(data.message);
}
});
});
});
</script>
<form id="form_to_crm">
<input type="text" name="NAME" placeholder="Name" required>
<input type="text" name="LAST_NAME" placeholder="Last name">
<input type="text" name="PHONE" placeholder="Phone">
<input type="text" name="EMAIL" placeholder="E-mail">
<input type="submit" value="Submit">
</form>
2. Создаем обработчик формы
Создаем обработчик. Он будет обрабатывать данные, проверять дубликаты и создавать лид.
Получаем данные из формы
Получаем и безопасно обрабатываем данные из полей NAME, LAST_NAME, PHONE, EMAIL, чтобы избежать XSS-атак.
const sName = String(req.body.NAME ?? '')
const sLastName = String(req.body.LAST_NAME ?? '')
const sPhone = String(req.body.PHONE ?? '')
const sEmail = String(req.body.EMAIL ?? '')
s_name = request.form.get("NAME", "")
s_last_name = request.form.get("LAST_NAME", "")
s_phone = request.form.get("PHONE", "")
s_email = request.form.get("EMAIL", "")
$sName = htmlspecialchars($_POST["NAME"]);
$sLastName = htmlspecialchars($_POST["LAST_NAME"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$sEmail = htmlspecialchars($_POST["EMAIL"]);
Формируем массив $arFields с данными нового лида.
const arFields = {
TITLE: 'From the site: ' + [sName, sLastName].join(' '),
NAME: sName || 'Empty name',
LAST_NAME: sLastName,
PHONE: sPhone ? [{ VALUE: sPhone, VALUE_TYPE: 'HOME' }] : [],
EMAIL: sEmail ? [{ VALUE: sEmail, VALUE_TYPE: 'HOME' }] : [],
}
ar_fields = {
"TITLE": "From the site: " + " ".join([s_name, s_last_name]),
"NAME": s_name or "Empty name",
"LAST_NAME": s_last_name,
"PHONE": [{"VALUE": s_phone, "VALUE_TYPE": "HOME"}] if s_phone else [],
"EMAIL": [{"VALUE": s_email, "VALUE_TYPE": "HOME"}] if s_email else [],
}
$arFields = [
'TITLE' => 'From the site: ' . implode(' ', [$sName, $sLastName]),
'NAME' => (!empty($sName)) ? $sName : 'Empty name',
'LAST_NAME' => $sLastName,
'PHONE' => (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'HOME')) : array(),
'EMAIL' => (!empty($sEmail)) ? array(array('VALUE' => $sEmail, 'VALUE_TYPE' => 'HOME')) : array()
];
Заголовок лида формируем как From the site: Имя Фамилия.
Система хранит телефон и электронную почту как массивы объектов crm_multifield, поэтому формируем массивы PHONE и EMAIL с помощью значений $sPhone и $sEmail.
-
В поля
VALUEзаписываем$sPhoneи$sEmail -
В поля
VALUE_TYPEпередаем типы, например,HOME
Если в переменных $sPhone и $sEmail нет значений, указываем пустые массивы.
Ищем дубликаты лидов
Чтобы найти повторяющиеся лиды по телефону и электронной почте, используем метод crm.duplicate.findbycomm дважды. В него нужно передать следующие данные:
-
entity_type— тип объекта. ПередаемLEAD— лид -
type— тип коммуникации. При первом вызове указываемPHONE, при втором —EMAIL -
values— массив значений для поиска. В вызове сtype:PHONEпередаем телефон$sPhone, в вызове сtype:EMAIL— электронную почту$sEmail. Оба значения получены из формы
Идентификаторы найденных дубликатов будем накапливать в массиве $arLeadDuplicate. Заводим его до первого вызова.
Поиск по телефону, "type" => "PHONE".
let arLeadDuplicate = []
if (sPhone) {
const resultDuplicate = await $b24.actions.v2.call.make({
method: 'crm.duplicate.findbycomm',
params: { entity_type: 'LEAD', type: 'PHONE', values: [sPhone] },
requestId: 'dup-phone'
})
const found = resultDuplicate.getData()?.result?.LEAD
if (found) arLeadDuplicate = arLeadDuplicate.concat(found)
}
ar_lead_duplicate = []
if s_phone:
result_duplicate = client.crm.duplicate.findbycomm(
type="PHONE", values=[s_phone], entity_type="LEAD",
).result
# если совпадений нет, метод возвращает пустой массив, а не объект,
# поэтому приводим результат к словарю перед обращением по ключу
found = (result_duplicate or {}).get("LEAD")
if found:
ar_lead_duplicate += found
$arLeadDuplicate = [];
if (!empty($sPhone)) {
$result = $sb->getCRMScope()->duplicate()->findByPhone(
[$sPhone],
\Bitrix24\SDK\Services\CRM\Duplicates\Service\EntityType::Lead
)->getCoreResponse()->getResponseData()->getResult();
if (!empty($result['LEAD'])) {
$arLeadDuplicate = array_merge($arLeadDuplicate, $result['LEAD']);
}
}
Поиск дубликатов по электронной почте, "type" => "EMAIL".
if (sEmail) {
const resultDuplicate = await $b24.actions.v2.call.make({
method: 'crm.duplicate.findbycomm',
params: { entity_type: 'LEAD', type: 'EMAIL', values: [sEmail] },
requestId: 'dup-email'
})
const found = resultDuplicate.getData()?.result?.LEAD
if (found) arLeadDuplicate = arLeadDuplicate.concat(found)
}
if s_email:
result_duplicate = client.crm.duplicate.findbycomm(
type="EMAIL", values=[s_email], entity_type="LEAD",
).result
found = (result_duplicate or {}).get("LEAD")
if found:
ar_lead_duplicate += found
if (!empty($sEmail)) {
$result = $sb->getCRMScope()->duplicate()->findByEmail(
[$sEmail],
\Bitrix24\SDK\Services\CRM\Duplicates\Service\EntityType::Lead
)->getCoreResponse()->getResponseData()->getResult();
if (!empty($result['LEAD'])) {
$arLeadDuplicate = array_merge($arLeadDuplicate, $result['LEAD']);
}
}
Если совпадения найдены, метод возвращает объект с ключом LEAD и массивом идентификаторов.
{
"result": {
"LEAD": [3277, 3281]
}
}
Если совпадений нет, метод возвращает пустой массив, а не пустой объект. Обращаться по ключу LEAD напрямую нельзя — сначала проверьте тип результата, иначе код упадет на первом же обращении без дублей.
{
"result": []
}
Идентификаторы найденных дубликатов объединяем в массиве $arLeadDuplicate.
Обрабатываем дубликаты
Если дубликаты найдены, вызываем метод crm.lead.list.
-
Применяем фильтр по идентификатору и статусу
CONVERTED -
Выбираем поля:
ID,COMPANY_ID,CONTACT_ID -
Сохраняем результат в массиве
$arDuplicateLead -
Заполняем поля
COMPANY_IDиCONTACT_IDв массиве$arFieldsзначениями из$arDuplicateLead
Статус CONVERTED отбирает только те лиды, которые уже превратились в контакт или компанию. У остальных лидов поля COMPANY_ID и CONTACT_ID пустые, привязывать новый лид не к чему.
if (arLeadDuplicate.length) {
const duplicateLead = await $b24.actions.v2.callList.make({
method: 'crm.lead.list',
params: {
filter: { '=ID': arLeadDuplicate, STATUS_ID: 'CONVERTED' },
select: ['ID', 'COMPANY_ID', 'CONTACT_ID']
},
requestId: 'dup-lead-list'
})
const arDuplicateLead = duplicateLead.getData()?.result ?? []
const company = arDuplicateLead.map(r => r.COMPANY_ID).find(v => v > 0)
const contact = arDuplicateLead.map(r => r.CONTACT_ID).find(v => v > 0)
if (company) arFields.COMPANY_ID = company
if (contact) arFields.CONTACT_ID = contact
}
if ar_lead_duplicate:
ar_duplicate_lead = client.crm.lead.list(
filter={"=ID": ar_lead_duplicate, "STATUS_ID": "CONVERTED"},
select=["ID", "COMPANY_ID", "CONTACT_ID"],
).as_list().result
company = next((r["COMPANY_ID"] for r in ar_duplicate_lead if int(r["COMPANY_ID"] or 0) > 0), None)
contact = next((r["CONTACT_ID"] for r in ar_duplicate_lead if int(r["CONTACT_ID"] or 0) > 0), None)
if company:
ar_fields["COMPANY_ID"] = company
if contact:
ar_fields["CONTACT_ID"] = contact
if (!empty($arLeadDuplicate)) {
$arDuplicateLead = [];
foreach ($sb->getCRMScope()->lead()->batch->list(
order: [],
filter: ['=ID' => $arLeadDuplicate, 'STATUS_ID' => 'CONVERTED'],
select: ['ID', 'COMPANY_ID', 'CONTACT_ID']
) as $lead) {
$arDuplicateLead[] = $lead;
}
foreach ($arDuplicateLead as $lead) {
if ($lead->COMPANY_ID > 0 && empty($arFields['COMPANY_ID'])) {
$arFields['COMPANY_ID'] = $lead->COMPANY_ID;
}
if ($lead->CONTACT_ID > 0 && empty($arFields['CONTACT_ID'])) {
$arFields['CONTACT_ID'] = $lead->CONTACT_ID;
}
}
}
Метод возвращает идентификаторы строками, а незаполненные связи — значением null. Поэтому проверяем значения перед тем, как переложить их в $arFields.
{
"result": [
{
"ID": "3277",
"COMPANY_ID": "1789",
"CONTACT_ID": "2431"
}
],
"total": 1
}
Добавляем новый лид
Чтобы добавить лид, используем метод crm.lead.add. В него передаем массив $arFields — с полями из формы и с COMPANY_ID и CONTACT_ID, если дубликаты нашлись.
Проверьте, какие обязательные поля настроены для лидов в вашем Битрикс24. Все обязательные поля нужно передать в метод crm.lead.add.
await $b24.actions.v2.call.make({
method: 'crm.lead.add',
params: { fields: arFields },
requestId: 'repeat-lead-add'
})
client.crm.lead.add(fields=ar_fields)
$sb->getCRMScope()->lead()->add($arFields);
Если лид создан успешно, метод вернет его идентификатор. Если вы получили ошибку error, изучите описание возможных ошибок в документации метода crm.lead.add.
{
"result": 3289
}
Проверим результат
Откройте созданный лид в Битрикс24. У повторного лида в карточке заполнен блок «Клиент»: там отображаются компания и контакт из предыдущего обращения.
Через REST лид проверяет метод crm.lead.get с идентификатором из ответа предыдущего шага.
const checkResponse = await $b24.actions.v2.call.make({
method: 'crm.lead.get',
params: { id: 3289 },
requestId: 'lead-get'
})
console.dir(checkResponse.getData().result)
lead = client.crm.lead.get(bitrix_id=3289).result
$lead = $sb->getCRMScope()->lead()->get(3289)->lead();
Сценарий выполнен, если в ответе:
-
TITLEначинается сFrom the site:— лид пришел из формы -
PHONEиEMAILсовпадают с тем, что отправила форма -
COMPANY_IDиCONTACT_IDзаполнены, когда клиент уже обращался. Для первого обращения эти поля остаются пустыми, и это тоже верный результат — привязывать лид не к чему
Проверить, что сценарий отработал именно как поиск дубликатов, проще всего так: отправьте форму дважды с одним телефоном. Между отправками сконвертируйте первый лид в контакт или компанию, иначе фильтр по статусу CONVERTED не найдет его и второй лид создастся без связей.
Ошибки и диагностика
Если метод вернул ошибку, проверьте данные запроса.
|
Код |
Причина и действие |
|
|
У пользователя нет прав на чтение элементов CRM или на создание лидов. Проверьте, от имени какого пользователя создан вебхук |
|
|
В crm.duplicate.findbycomm не передан обязательный параметр |
|
|
В crm.duplicate.findbycomm не передан обязательный параметр |
|
|
В |
Лид может создаться без ошибки, но без связей с компанией и контактом. Это не сбой сценария, а один из его исходов. Проверьте по порядку:
-
crm.duplicate.findbycomm вернул пустой результат. Совпадений по телефону и почте в CRM нет, клиент обращается впервые
-
дубликаты нашлись, но crm.lead.list вернул пустой список. Ни один из найденных лидов не имеет статус
CONVERTED— они еще не превращены в контакт или компанию -
поиск не учитывает добавочный номер телефона, но чувствителен к формату записи. Если в CRM телефон сохранен как
+7 900 123-45-67, а форма прислала89001234567, совпадения не будет
Повторяйте сценарий с того шага, который вернул ошибку. Поиск дубликатов и получение списка ничего не создают, их можно выполнять сколько угодно раз. Если ошибку вернул crm.lead.add, лид не создан: исправьте fields и повторите только этот вызов.
Что важно учитывать
-
метод crm.duplicate.findbycomm принимает не больше 20 значений в
valuesза вызов -
если по одному типу объекта найдено 20 и более дублей, остальные типы в ответе не возвращаются. В сценарии это не мешает: мы ищем только по
LEAD -
сценарий связывает новый лид с компанией и контактом, но сам старый лид не изменяет и дубли не объединяет. Для слияния используйте метод crm.entity.mergeBatch
-
повторный запуск формы с теми же данными каждый раз создает новый лид. Дубли не отсеиваются, поиск нужен только для привязки
-
поиск идет только среди лидов, потому что в
entity_typeпереданLEAD. Чтобы найти совпадения еще и среди контактов и компаний, уберитеentity_type— тогда метод вернет объект с ключамиLEAD,CONTACTиCOMPANY
Полный пример кода обработчика
import express from 'express'
import { B24Hook } from '@bitrix24/b24jssdk'
const $b24 = B24Hook.fromWebhookUrl(process.env.B24_HOOK)
// B24_HOOK = 'https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/'
const app = express()
app.use(express.json())
// Обработчик принимает данные формы по маршруту /form
app.post('/form', async (req, res) => {
const sName = String(req.body.NAME ?? '')
const sLastName = String(req.body.LAST_NAME ?? '')
const sPhone = String(req.body.PHONE ?? '')
const sEmail = String(req.body.EMAIL ?? '')
const arFields = {
TITLE: 'From the site: ' + [sName, sLastName].join(' '),
NAME: sName || 'Empty name',
LAST_NAME: sLastName,
PHONE: sPhone ? [{ VALUE: sPhone, VALUE_TYPE: 'HOME' }] : [],
EMAIL: sEmail ? [{ VALUE: sEmail, VALUE_TYPE: 'HOME' }] : [],
}
let arLeadDuplicate = []
if (sPhone) { // поиск дубликатов по телефону
const r = await $b24.actions.v2.call.make({
method: 'crm.duplicate.findbycomm',
params: { entity_type: 'LEAD', type: 'PHONE', values: [sPhone] },
requestId: 'dup-phone'
})
const found = r.getData()?.result?.LEAD
if (found) arLeadDuplicate = arLeadDuplicate.concat(found)
}
if (sEmail) { // поиск дубликатов по email
const r = await $b24.actions.v2.call.make({
method: 'crm.duplicate.findbycomm',
params: { entity_type: 'LEAD', type: 'EMAIL', values: [sEmail] },
requestId: 'dup-email'
})
const found = r.getData()?.result?.LEAD
if (found) arLeadDuplicate = arLeadDuplicate.concat(found)
}
if (arLeadDuplicate.length) { // получение дубликата лида с полями связанных контакта и компании
const duplicateLead = await $b24.actions.v2.callList.make({
method: 'crm.lead.list',
params: {
filter: { '=ID': arLeadDuplicate, STATUS_ID: 'CONVERTED' },
select: ['ID', 'COMPANY_ID', 'CONTACT_ID']
},
requestId: 'dup-lead-list'
})
const arDuplicateLead = duplicateLead.getData()?.result ?? []
const company = arDuplicateLead.map(r => r.COMPANY_ID).find(v => v > 0)
const contact = arDuplicateLead.map(r => r.CONTACT_ID).find(v => v > 0)
if (company) arFields.COMPANY_ID = company
if (contact) arFields.CONTACT_ID = contact
}
const result = await $b24.actions.v2.call.make({ // создание повторного лида
method: 'crm.lead.add',
params: { fields: arFields },
requestId: 'repeat-lead-add'
})
if (result.isSuccess && result.getData()?.result) {
res.json({ message: 'Lead add' })
} else {
res.json({ message: 'Lead not added: ' + result.getErrorMessages().join('; ') })
}
})
app.listen(3000)
# pip install b24pysdk flask
from flask import Flask, request, jsonify
from b24pysdk import BitrixWebhook, Client
app = Flask(__name__)
client = Client(BitrixWebhook(
domain="your-domain.bitrix24.ru",
webhook_token="USER_ID/TOKEN", # только user_id/token, без https://
))
def find_lead_duplicates(comm_type: str, value: str) -> list:
"""Возвращает идентификаторы лидов с совпадающим телефоном или почтой.
Если совпадений нет, метод возвращает пустой массив, а не объект,
поэтому приводим результат к словарю перед обращением по ключу.
"""
result = client.crm.duplicate.findbycomm(
type=comm_type, values=[value], entity_type="LEAD",
).result
return (result or {}).get("LEAD") or []
@app.route("/form", methods=["POST"])
def handle_form():
s_name = request.form.get("NAME", "")
s_last_name = request.form.get("LAST_NAME", "")
s_phone = request.form.get("PHONE", "")
s_email = request.form.get("EMAIL", "")
ar_fields = {
"TITLE": "From the site: " + " ".join([s_name, s_last_name]),
"NAME": s_name or "Empty name",
"LAST_NAME": s_last_name,
"PHONE": [{"VALUE": s_phone, "VALUE_TYPE": "HOME"}] if s_phone else [],
"EMAIL": [{"VALUE": s_email, "VALUE_TYPE": "HOME"}] if s_email else [],
}
ar_lead_duplicate = []
if s_phone: # поиск дубликатов по телефону
ar_lead_duplicate += find_lead_duplicates("PHONE", s_phone)
if s_email: # поиск дубликатов по email
ar_lead_duplicate += find_lead_duplicates("EMAIL", s_email)
if ar_lead_duplicate: # получение дубликата лида с полями связанных контакта и компании
ar_duplicate_lead = client.crm.lead.list(
filter={"=ID": ar_lead_duplicate, "STATUS_ID": "CONVERTED"},
select=["ID", "COMPANY_ID", "CONTACT_ID"],
).as_list().result
company = next((r["COMPANY_ID"] for r in ar_duplicate_lead if int(r["COMPANY_ID"] or 0) > 0), None)
contact = next((r["CONTACT_ID"] for r in ar_duplicate_lead if int(r["CONTACT_ID"] or 0) > 0), None)
if company:
ar_fields["COMPANY_ID"] = company
if contact:
ar_fields["CONTACT_ID"] = contact
try:
client.crm.lead.add(fields=ar_fields) # создание повторного лида
return jsonify({"message": "Lead add"})
except Exception as e:
return jsonify({"message": f"Lead not added: {e}"})
<?php
// composer require bitrix24/b24phpsdk:"^3.0"
require_once 'vendor/autoload.php';
use Bitrix24\SDK\Services\ServiceBuilderFactory;
use Bitrix24\SDK\Services\CRM\Duplicates\Service\EntityType;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('b24');
$log->pushHandler(new StreamHandler('php://stdout'));
$sb = (new ServiceBuilderFactory(new EventDispatcher(), $log))
->initFromWebhook('https://your-domain.bitrix24.ru/rest/USER_ID/TOKEN/');
$sName = htmlspecialchars($_POST["NAME"]);
$sLastName = htmlspecialchars($_POST["LAST_NAME"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$sEmail = htmlspecialchars($_POST["EMAIL"]);
$arFields = [
'TITLE' => 'From the site: ' . implode(' ', [$sName, $sLastName]),
'NAME' => (!empty($sName)) ? $sName : 'Empty name',
'LAST_NAME' => $sLastName,
'PHONE' => (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'HOME')) : array(),
'EMAIL' => (!empty($sEmail)) ? array(array('VALUE' => $sEmail, 'VALUE_TYPE' => 'HOME')) : array()
];
$arLeadDuplicate = [];
if (!empty($sPhone)) { // поиск дубликатов по телефону
$r = $sb->getCRMScope()->duplicate()->findByPhone([$sPhone], EntityType::Lead)
->getCoreResponse()->getResponseData()->getResult();
if (!empty($r['LEAD'])) {
$arLeadDuplicate = array_merge($arLeadDuplicate, $r['LEAD']);
}
}
if (!empty($sEmail)) { // поиск дубликатов по email
$r = $sb->getCRMScope()->duplicate()->findByEmail([$sEmail], EntityType::Lead)
->getCoreResponse()->getResponseData()->getResult();
if (!empty($r['LEAD'])) {
$arLeadDuplicate = array_merge($arLeadDuplicate, $r['LEAD']);
}
}
if (!empty($arLeadDuplicate)) { // получение дубликата лида с полями связанных контакта и компании
foreach ($sb->getCRMScope()->lead()->batch->list(
order: [],
filter: ['=ID' => $arLeadDuplicate, 'STATUS_ID' => 'CONVERTED'],
select: ['ID', 'COMPANY_ID', 'CONTACT_ID']
) as $lead) {
if ($lead->COMPANY_ID > 0 && empty($arFields['COMPANY_ID'])) {
$arFields['COMPANY_ID'] = $lead->COMPANY_ID;
}
if ($lead->CONTACT_ID > 0 && empty($arFields['CONTACT_ID'])) {
$arFields['CONTACT_ID'] = $lead->CONTACT_ID;
}
}
}
try {
$sb->getCRMScope()->lead()->add($arFields); // создание повторного лида
echo json_encode(['message' => 'Lead add']);
} catch (\Throwable $e) {
echo json_encode(['message' => 'Lead not added: ' . $e->getMessage()]);
}