Добавить лид с файлами через веб-форму
Scope:
crmКто может выполнять метод: пользователи с правом создания лидов в CRM
Выберите инструмент для разработки с AI-агентом:
- используйте Битрикс24 Вайбкод, чтобы создать приложение для Битрикс24 по описанию задачи без знания языков программирования. Агент напишет код и разместит приложение на сервере без ручной настройки хостинга
- используйте MCP-сервер, чтобы разрабатывать интеграцию через REST API в своем проекте. Агент будет обращаться к официальной REST-документации
На сайте можно разместить форму для сбора данных потенциальных клиентов. Когда клиент заполнит форму и приложит файлы, его данные попадут в CRM, и вы сможете обработать заявку.
Настройка формы состоит из двух шагов.
-
Разместите форму на HTML-странице. Она отправит данные в обработчик.
-
Создайте файл для обработки данных. Обработчик примет и подготовит данные, а затем создаст лид методом crm.lead.add.
1. Создаем веб-форму
В Битрикс24 из лида можно автоматически создать контакт и компанию. Чтобы форма подходила для разных случаев, сделаем ее универсальной. Для контакта нужно указать имя и фамилию, а для компании — название. Создадим на странице сайта веб-форму с полями:
-
NAME— имя, обязательное, -
LAST_NAME— фамилия, -
COMPANY_TITLE— название компании, -
EMAIL— электронная почта, -
PHONE— телефон.
Чтобы клиент мог загрузить файлы, добавим в форму поля:
-
FILE— для одного файла, -
FILES— для добавления нескольких файлов.
При отправке форма передает данные в обработчик.
<form id="form_to_crm" enctype="multipart/form-data">
<!-- Имя (обязательное поле) -->
<input type="text" name="NAME" placeholder="Имя" required>
<!-- Фамилия -->
<input type="text" name="LAST_NAME" placeholder="Фамилия">
<!-- Название компании -->
<input type="text" name="COMPANY_TITLE" placeholder="Название компании">
<!-- Email -->
<input type="text" name="EMAIL" placeholder="Почта">
<!-- Телефон -->
<input type="text" name="PHONE" placeholder="Телефон">
<!-- Поле для одного файла -->
<input type="file" name="FILE">
<!-- Поле для нескольких файлов -->
<input type="file" name="FILES" multiple>
<!-- Кнопка отправки -->
<input type="submit" value="Отправить">
</form>
<script>
document.getElementById('form_to_crm').addEventListener('submit', async (el) => {
el.preventDefault();
// FormData сам соберёт текстовые поля и файлы (multipart/form-data)
const formData = new FormData(el.currentTarget);
// Content-Type не указываем — браузер выставит multipart с boundary
const response = await fetch('/form', { method: 'POST', body: formData });
const data = await response.json();
alert(data.message);
});
</script>
<form id="form_to_crm" method="POST" action="form.php" enctype="multipart/form-data">
<!-- Имя (обязательное поле) -->
<input type="text" name="NAME" placeholder="Имя" required>
<!-- Фамилия -->
<input type="text" name="LAST_NAME" placeholder="Фамилия">
<!-- Название компании -->
<input type="text" name="COMPANY_TITLE" placeholder="Название компании">
<!-- Email -->
<input type="text" name="EMAIL" placeholder="Почта">
<!-- Телефон -->
<input type="text" name="PHONE" placeholder="Телефон">
<!-- Поле для одного файла -->
<input type="file" name="FILE">
<!-- Поле для нескольких файлов -->
<input type="file" name="FILES" multiple>
<!-- Кнопка отправки -->
<input type="submit" value="Отправить">
</form>
<!-- Подключаем jQuery для AJAX-запроса -->
<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) {
el.preventDefault();
var formData = new FormData(this); // Собираем данные формы с файлами
$.ajax({
method: 'POST',
url: 'form.php',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(data) {
alert(data.message);
},
error: function() {
alert('Ошибка при отправке формы');
}
});
});
});
</script>
<form id="form_to_crm" enctype="multipart/form-data">
<!-- Имя (обязательное поле) -->
<input type="text" name="NAME" placeholder="Имя" required>
<!-- Фамилия -->
<input type="text" name="LAST_NAME" placeholder="Фамилия">
<!-- Название компании -->
<input type="text" name="COMPANY_TITLE" placeholder="Название компании">
<!-- Email -->
<input type="text" name="EMAIL" placeholder="Почта">
<!-- Телефон -->
<input type="text" name="PHONE" placeholder="Телефон">
<!-- Поле для одного файла -->
<input type="file" name="FILE">
<!-- Поле для нескольких файлов -->
<input type="file" name="FILES" multiple>
<!-- Кнопка отправки -->
<input type="submit" value="Отправить">
</form>
<!-- Подключаем jQuery для AJAX-запроса -->
<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) {
el.preventDefault();
var formData = new FormData(this); // Собираем данные формы с файлами
$.ajax({
method: 'POST',
url: '/form', // маршрут обработчика на Flask
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function(data) {
alert(data.message);
},
error: function() {
alert('Ошибка при отправке формы');
}
});
});
});
</script>
2. Создаем обработчик формы
Чтобы обработать значения из полей формы и добавить лид в CRM, создадим обработчик.
Подготавливаем данные из формы
Чтобы использовать данные из формы в методе создания лида, нужно их подготовить.
Очищаем от HTML-тегов
Получаем и очищаем от HTML-тегов данные из формы.
// Получаем данные из формы
const sName = String(req.body.NAME ?? '')
const sLastName = String(req.body.LAST_NAME ?? '')
const sCompanyTitle = String(req.body.COMPANY_TITLE ?? '')
const sPhone = String(req.body.PHONE ?? '')
const sEmail = String(req.body.EMAIL ?? '')
// Получаем и очищаем данные из формы
$sName = htmlspecialchars($_POST["NAME"]);
$sLastName = htmlspecialchars($_POST["LAST_NAME"]);
$sCompanyTitle = htmlspecialchars($_POST["COMPANY_TITLE"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$sEmail = htmlspecialchars($_POST["EMAIL"]);
# Получаем данные из формы
s_name = request.form.get("NAME", "")
s_last_name = request.form.get("LAST_NAME", "")
s_company_title = request.form.get("COMPANY_TITLE", "")
s_phone = request.form.get("PHONE", "")
s_email = request.form.get("EMAIL", "")
Подготавливаем файлы
Подготавливаем файлы для загрузки в Битрикс24. Для каждого файла нужно передать массив:
-
с именем файла,
-
строкой с кодировкой файла в Base64.
Чтобы закодировать файл, используем функцию base64_encode.
Документация
// Создаем переменные для массивов с файлами
const arFiles = []
let arSingleFile = []
// Обрабатываем поле FILES с несколькими файлами (multer хранит их в req.files)
for (const file of req.files?.FILES ?? []) {
arFiles.push({
fileData: [
file.originalname, // название файла
file.buffer.toString('base64'), // контент файла, закодированный в base64
]
})
}
// Обрабатываем поле FILE с одним файлом
const single = req.files?.FILE?.[0]
if (single) {
arSingleFile = {
fileData: [
single.originalname, // название файла
single.buffer.toString('base64'), // контент файла, закодированный в base64
]
}
}
// Создаем переменные для массивов с файлами
$arFiles = [];
$arSingleFile = [];
// Обрабатываем поле FILES с несколькими файлами
if(!empty($_FILES['FILES']['tmp_name'])) {
foreach($_FILES['FILES']['tmp_name'] as $key => $tmpName) {
if(!empty($tmpName)) {
$arFiles[] = [
'fileData' => [
$_FILES['FILES']['name'][$key], // название файла
base64_encode(file_get_contents($tmpName)) // контент файла, закодированный в base64
]
];
}
}
}
// Обрабатываем поле FILE с одним файлом
if(!empty($_FILES['FILE']['tmp_name'])) {
$arSingleFile = [
'fileData' => [
$_FILES['FILE']['name'], // название файла
base64_encode(file_get_contents($_FILES['FILE']['tmp_name'])) // контент файла, закодированный в base64
]
];
}
import base64
# Создаем переменные для массивов с файлами
ar_files = []
ar_single_file = []
# Обрабатываем поле FILES с несколькими файлами
for file in request.files.getlist("FILES"):
if file and file.filename:
ar_files.append({
"fileData": [
file.filename, # название файла
base64.b64encode(file.read()).decode(), # контент файла, закодированный в base64
]
})
# Обрабатываем поле FILE с одним файлом
single = request.files.get("FILE")
if single and single.filename:
ar_single_file = {
"fileData": [
single.filename, # название файла
base64.b64encode(single.read()).decode(), # контент файла, закодированный в base64
]
}
Форматируем телефон и почту
Телефон и email система хранит как массив объектов crm_multifield, поэтому их нужно привести к формату массива.
-
Если значение есть, добавляем его первым элементом
VALUEв массив, а вторым значением указываем типVALUE_TYPE, например:-
WORK— для телефона, -
HOME— для email.
-
-
Если значения нет, передаем пустой массив.
// Форматируем телефон и почту для Битрикс24 в формат crm_multifield
const arPhone = sPhone ? [{ VALUE: sPhone, VALUE_TYPE: 'WORK' }] : []
const arEmail = sEmail ? [{ VALUE: sEmail, VALUE_TYPE: 'HOME' }] : []
// Форматируем телефон и почту для Битрикс24 в формат crm_multifield
$arPhone = (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'WORK')) : array();
$arEmail = (!empty($sEmail)) ? array(array('VALUE' => $sEmail, 'VALUE_TYPE' => 'HOME')) : array();
# Форматируем телефон и почту для Битрикс24 в формат crm_multifield
ar_phone = [{"VALUE": s_phone, "VALUE_TYPE": "WORK"}] if s_phone else []
ar_email = [{"VALUE": s_email, "VALUE_TYPE": "HOME"}] if s_email else []
Формируем заголовок лида
Заголовок лида сформируем из имени и фамилии. Для компаний добавим в заголовок название компании.
// Формируем заголовок лида из имени и фамилии
let sTitle = 'С сайта: ' + `${sName} ${sLastName}`.trim()
// Если есть название компании — добавляем его через тире после имени и фамилии
if (sCompanyTitle) {
sTitle += ' — ' + sCompanyTitle
}
// Формируем заголовок лида из имени и фамилии
$sTitle = 'С сайта: ' . trim($sName . ' ' . $sLastName);
// Если есть название компании — добавляем его через тире после имени и фамилии
if (!empty($sCompanyTitle)) {
$sTitle .= ' — ' . $sCompanyTitle;
}
# Формируем заголовок лида из имени и фамилии
s_title = "С сайта: " + f"{s_name} {s_last_name}".strip()
# Если есть название компании — добавляем его через тире после имени и фамилии
if s_company_title:
s_title += " — " + s_company_title
Создаем лид
Для создания лида используем метод crm.lead.add. В объекте fields передаем поля:
-
TITLE— заголовок лида, -
NAME— имя лида, -
LAST_NAME— фамилия, -
COMPANY_TITLE— название компании, -
PHONE— номер телефона, -
EMAIL— электронная почта, -
UF_CRM_LEAD_FILES— пользовательское поле для добавления нескольких файлов, -
UF_CRM_LEAD_FILE— пользовательское поле для файла.
Пользовательские поля UF_CRM_* нужно создать в Битрикс24 до создания лида. Добавьте их на портале вручную или методом crm.lead.userfield.add. В примере подставьте свои названия полей вместо UF_CRM_LEAD_FILES и UF_CRM_LEAD_FILE.
Проверьте, какие обязательные поля настроены для лидов в вашем Битрикс24. Все обязательные поля нужно передать в метод crm.lead.add.
await $b24.actions.v2.call.make({
method: 'crm.lead.add',
params: {
fields: {
TITLE: sTitle, // Заголовок лида
NAME: sName, // Имя
LAST_NAME: sLastName, // Фамилия
COMPANY_TITLE: sCompanyTitle, // Название компании
PHONE: arPhone, // Телефон
EMAIL: arEmail, // Email
UF_CRM_LEAD_FILES: arFiles, // Поле для добавления нескольких файлов
UF_CRM_LEAD_FILE: arSingleFile, // Поле для файла
}
},
requestId: 'lead-add'
})
$sb->getCRMScope()->lead()->add([
'TITLE' => $sTitle, // Заголовок лида
'NAME' => $sName, // Имя
'LAST_NAME' => $sLastName, // Фамилия
'COMPANY_TITLE' => $sCompanyTitle, // Название компании
'PHONE' => $arPhone, // Телефон
'EMAIL' => $arEmail, // Email
'UF_CRM_LEAD_FILES' => $arFiles, // Поле для добавления нескольких файлов
'UF_CRM_LEAD_FILE' => $arSingleFile, // Поле для файла
]);
client.crm.lead.add(fields={
"TITLE": s_title, # Заголовок лида
"NAME": s_name, # Имя
"LAST_NAME": s_last_name, # Фамилия
"COMPANY_TITLE": s_company_title, # Название компании
"PHONE": ar_phone, # Телефон
"EMAIL": ar_email, # Email
"UF_CRM_LEAD_FILES": ar_files, # Поле для добавления нескольких файлов
"UF_CRM_LEAD_FILE": ar_single_file, # Поле для файла
})
В результате получим идентификатор нового лида 5.
{
"result": 5
}
Полный пример кода обработчика
import express from 'express'
import multer from 'multer'
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()
// multer хранит файлы в памяти — доступны как Buffer в req.files
const upload = multer({ storage: multer.memoryStorage() })
// Обработчик принимает данные формы (multipart) по маршруту /form
app.post('/form', upload.fields([{ name: 'FILE' }, { name: 'FILES' }]), async (req, res) => {
// Получаем и очищаем данные из формы
const sName = String(req.body.NAME ?? '')
const sLastName = String(req.body.LAST_NAME ?? '')
const sCompanyTitle = String(req.body.COMPANY_TITLE ?? '')
const sPhone = String(req.body.PHONE ?? '')
const sEmail = String(req.body.EMAIL ?? '')
// Создаем переменные для массивов с файлами
const arFiles = []
let arSingleFile = []
// Обрабатываем поле FILES с несколькими файлами
for (const file of req.files?.FILES ?? []) {
arFiles.push({
fileData: [
file.originalname, // название файла
file.buffer.toString('base64'), // контент файла, закодированный в base64
]
})
}
// Обрабатываем поле FILE с одним файлом
const single = req.files?.FILE?.[0]
if (single) {
arSingleFile = {
fileData: [
single.originalname, // название файла
single.buffer.toString('base64'), // контент файла, закодированный в base64
]
}
}
// Форматируем телефон и почту для Битрикс24 в формат crm_multifield
const arPhone = sPhone ? [{ VALUE: sPhone, VALUE_TYPE: 'WORK' }] : []
const arEmail = sEmail ? [{ VALUE: sEmail, VALUE_TYPE: 'HOME' }] : []
// Формируем заголовок лида из имени и фамилии
let sTitle = 'С сайта: ' + `${sName} ${sLastName}`.trim()
if (sCompanyTitle) {
sTitle += ' — ' + sCompanyTitle
}
// Отправляем данные в Битрикс24
const response = await $b24.actions.v2.call.make({
method: 'crm.lead.add',
params: {
fields: {
TITLE: sTitle, // Заголовок лида
NAME: sName, // Имя
LAST_NAME: sLastName, // Фамилия
COMPANY_TITLE: sCompanyTitle, // Название компании
PHONE: arPhone, // Телефон
EMAIL: arEmail, // Email
UF_CRM_LEAD_FILES: arFiles, // Поле для добавления нескольких файлов
UF_CRM_LEAD_FILE: arSingleFile, // Поле для файла
}
},
requestId: 'lead-add'
})
// Проверяем результат и выводим сообщение
if (response.isSuccess && response.getData()?.result) {
res.json({ message: 'Лид добавлен успешно' })
} else {
res.json({ message: 'Лид не добавлен: ' + response.getErrorMessages().join('; ') })
}
})
app.listen(3000)
<?php
// composer require bitrix24/b24phpsdk:"^3.0"
require_once 'vendor/autoload.php';
use Bitrix24\SDK\Services\ServiceBuilderFactory;
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"]);
$sCompanyTitle = htmlspecialchars($_POST["COMPANY_TITLE"]);
$sPhone = htmlspecialchars($_POST["PHONE"]);
$sEmail = htmlspecialchars($_POST["EMAIL"]);
// Создаем переменные для массивов с файлами
$arFiles = [];
$arSingleFile = [];
// Обрабатываем поле FILES с несколькими файлами
if (!empty($_FILES['FILES']['tmp_name'])) {
foreach ($_FILES['FILES']['tmp_name'] as $key => $tmpName) {
if (!empty($tmpName)) {
$arFiles[] = [
'fileData' => [
$_FILES['FILES']['name'][$key], // название файла
base64_encode(file_get_contents($tmpName)) // контент файла, закодированный в base64
]
];
}
}
}
// Обрабатываем поле FILE с одним файлом
if (!empty($_FILES['FILE']['tmp_name'])) {
$arSingleFile = [
'fileData' => [
$_FILES['FILE']['name'], // название файла
base64_encode(file_get_contents($_FILES['FILE']['tmp_name'])) // контент файла, закодированный в base64
]
];
}
// Форматируем телефон и почту для Битрикс24 в формат crm_multifield
$arPhone = (!empty($sPhone)) ? array(array('VALUE' => $sPhone, 'VALUE_TYPE' => 'WORK')) : array();
$arEmail = (!empty($sEmail)) ? array(array('VALUE' => $sEmail, 'VALUE_TYPE' => 'HOME')) : array();
// Формируем заголовок лида из имени и фамилии
$sTitle = 'С сайта: ' . trim($sName . ' ' . $sLastName);
if (!empty($sCompanyTitle)) {
$sTitle .= ' — ' . $sCompanyTitle;
}
// Отправляем данные в Битрикс24
try {
$sb->getCRMScope()->lead()->add([
'TITLE' => $sTitle, // Заголовок лида
'NAME' => $sName, // Имя
'LAST_NAME' => $sLastName, // Фамилия
'COMPANY_TITLE' => $sCompanyTitle, // Название компании
'PHONE' => $arPhone, // Телефон
'EMAIL' => $arEmail, // Email
'UF_CRM_LEAD_FILES' => $arFiles, // Поле для добавления нескольких файлов
'UF_CRM_LEAD_FILE' => $arSingleFile, // Поле для файла
]);
echo json_encode(['message' => 'Лид добавлен успешно']);
} catch (\Throwable $e) {
echo json_encode(['message' => 'Лид не добавлен: ' . $e->getMessage()]);
}
# pip install b24pysdk
import base64
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://
))
@app.route("/form", methods=["POST"])
def handle_form():
# Получаем данные из формы
s_name = request.form.get("NAME", "")
s_last_name = request.form.get("LAST_NAME", "")
s_company_title = request.form.get("COMPANY_TITLE", "")
s_phone = request.form.get("PHONE", "")
s_email = request.form.get("EMAIL", "")
# Создаем переменные для массивов с файлами
ar_files = []
ar_single_file = []
# Обрабатываем поле FILES с несколькими файлами
for file in request.files.getlist("FILES"):
if file and file.filename:
ar_files.append({
"fileData": [
file.filename, # название файла
base64.b64encode(file.read()).decode(), # контент файла, закодированный в base64
]
})
# Обрабатываем поле FILE с одним файлом
single = request.files.get("FILE")
if single and single.filename:
ar_single_file = {
"fileData": [
single.filename, # название файла
base64.b64encode(single.read()).decode(), # контент файла, закодированный в base64
]
}
# Форматируем телефон и почту для Битрикс24 в формат crm_multifield
ar_phone = [{"VALUE": s_phone, "VALUE_TYPE": "WORK"}] if s_phone else []
ar_email = [{"VALUE": s_email, "VALUE_TYPE": "HOME"}] if s_email else []
# Формируем заголовок лида из имени и фамилии
s_title = "С сайта: " + f"{s_name} {s_last_name}".strip()
if s_company_title:
s_title += " — " + s_company_title
# Отправляем данные в Битрикс24
try:
client.crm.lead.add(fields={
"TITLE": s_title, # Заголовок лида
"NAME": s_name, # Имя
"LAST_NAME": s_last_name, # Фамилия
"COMPANY_TITLE": s_company_title, # Название компании
"PHONE": ar_phone, # Телефон
"EMAIL": ar_email, # Email
"UF_CRM_LEAD_FILES": ar_files, # Поле для добавления нескольких файлов
"UF_CRM_LEAD_FILE": ar_single_file, # Поле для файла
})
return jsonify({"message": "Лид добавлен успешно"})
except Exception as e:
return jsonify({"message": f"Лид не добавлен: {e}"})