Подготавливаем страницу…
Подготавливаем страницу…
Основной путь — серверный обработчик события веб-формы: согласие уходит после того, как Битрикс сохранил результат. Для форм Битрикс24 и облачного портала — свои варианты ниже.
onAfterResultAdd: Битрикс сохранил результат веб-формы — обработчик отправил согласие. Ключ sk_ остаётся на сервере, защита списком IP. Работает с любой темой и не зависит от браузера посетителя.form.result.new) и встроенных форм Битрикс24. Ключ pk_, защита списком доменов.Формы Битрикс24 в iframe — отдельный случай. Всплывающая форма или форма по ссылке открывается в iframe домена портала: её полей со страницы не видит никакой код — ни наш, ни ваш. Согласие с такой формы собирается только на сервере, а галочку и ссылки на документы добавляют средствами конструктора в самом Битрикс24. Встроенную форму, которая рисуется прямо на странице, браузерный код видит как обычную.
Кабинет → «Интеграция» → карточка сайта, тип ключа — sk_. Внешний адрес сервера — curl ifconfig.me по SSH; без SSH адрес виден в админке (Настройки → Инструменты → Проверка системы) или у хостинг-провайдера. Запишите и form_id форм согласия.
Админка → Сервисы → Веб-формы → Список: у каждой формы свой ID. Не путайте его с form_id из кабинета — в обработчике они стоят по разные стороны сопоставления.
Вопрос типа «Флажок»: основное согласие — обязательное, согласие на рассылку — отдельный необязательный флажок (обязательная галочка на рекламу добровольным согласием не считается). В тексте флажка — ссылки на политику и текст согласия; Битрикс допускает HTML в названиях полей, готовый блок со ссылками лежит в кабинете.
В /local/php_interface/init.php (создайте файл, если его нет, начав с <?php). Перед правкой сохраните копию: синтаксическая ошибка в этом файле кладёт весь сайт.
<?php
// Обработчик события веб-формы. Класть в /local/php_interface/init.php —
// Битрикс подхватывает его сам, и обновление ядра файл не затирает.
// (Правка /bitrix/php_interface/init.php тоже работает, но живёт в ядре.)
use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler(
'form',
'onAfterResultAdd',
function ($webFormId, $resultId) {
// ── Настройки ───────────────────────────────────────────────────
$api_key = 'sk_ваш_ключ';
// ID веб-формы Битрикса → form_id формы согласия в 1ОПД.
// ID своих форм смотрите в админке: Сервисы → Веб-формы → Список.
$form_id_map = [
7 => 1,
12 => 2,
];
// Необязательные чекбоксы (например, согласие на рассылку):
// код вопроса в форме Битрикса → form_id согласия на рассылку.
// Согласие по ним уходит только когда галочка отмечена.
$optional_checkbox_map = [
// 'OPD_CONSENT_MARKETING' => 2,
];
// ────────────────────────────────────────────────────────────────
$form_id = $form_id_map[(int) $webFormId] ?? null;
if (!$form_id) return; // эту форму в 1ОПД не пишем
CFormResult::GetDataByID($resultId, [], $arRes, $arRes2);
$fields = [];
$email = '';
$checked = [];
foreach ($arRes as $code => $info) {
$value = is_array($info) ? (string) (reset($info)['USER_TEXT'] ?? '') : (string) $info;
if ($value !== '') $checked[$code] = true;
if (isset($optional_checkbox_map[$code])) continue; // сами галочки — не данные
$fields[] = ['field' => $code, 'value' => $value];
if (stripos($code, 'email') !== false) $email = $value;
}
if ($email === '') return; // без идентификатора субъекта согласие не пишем
$send = function (int $fid) use ($api_key, $email, $fields) {
$payload = json_encode([
'form_id' => $fid,
'hash_field' => $email,
// Чекбокс согласия в форме обязателен: результат без него
// Битрикс не сохранит, значит отметка была.
'consent_given' => true,
'fields' => $fields,
], JSON_UNESCAPED_UNICODE);
$ch = curl_init('https://v2.1opd.ru/api/v2/create-agreement');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'API-KEY: ' . $api_key,
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
curl_exec($ch);
curl_close($ch);
};
$send($form_id);
foreach ($optional_checkbox_map as $code => $fid) {
if (!empty($checked[$code])) $send($fid); // только за отмеченную галочку
}
}
);Отправьте тестовую заявку с реальной почтой и найдите запись: кабинет → «Согласия». Упавший хук виден в Журнале событий Битрикса. Пока записи в реестре нет, интеграция не работает.
Коробочный — обычный сервер: тот же init.php, только событие CRM (OnAfterCrmLeadAdd) вместо события веб-формы.
Облачный — своего PHP нет. Исходящий вебхук портала зовёт страницу на вашем сайте, она забирает поля лида и отправляет согласие:
<?php
// /opd-b24-hook.php на ВАШЕМ сайте — принимает исходящий вебхук облачного
// Битрикс24 (Настройки → Разработчикам → Исходящий вебхук, событие
// ONCRMLEADADD) и пересылает согласие в 1ОПД.
if (($_GET['secret'] ?? '') !== 'ПОСТАВЬТЕ_СВОЙ_СЕКРЕТ') { http_response_code(403); exit; }
$leadId = (int) ($_POST['data']['FIELDS']['ID'] ?? 0);
if (!$leadId) exit;
// Поля лида забираем входящим вебхуком портала (право crm).
$rest = 'https://ВАШ-ПОРТАЛ.bitrix24.ru/rest/1/ВАШ_ТОКЕН/crm.lead.get.json?id=' . $leadId;
$lead = json_decode(file_get_contents($rest), true)['result'] ?? [];
$email = $lead['EMAIL'][0]['VALUE'] ?? '';
if ($email === '') exit;
$payload = json_encode([
'form_id' => 1,
'hash_field' => $email,
'fields' => [
['field' => 'email', 'value' => $email],
['field' => 'first_name', 'value' => (string) ($lead['NAME'] ?? '')],
],
], JSON_UNESCAPED_UNICODE);
$ch = curl_init('https://v2.1opd.ru/api/v2/create-agreement');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['API-KEY: sk_ваш_ключ', 'Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
curl_exec($ch);
curl_close($ch);Обратите внимание: здесь нет consent_given — CRM-событие само по себе не подтверждает, что человек отметил галочку. Если в форме, из которой создан лид, галочка обязательна, добавьте 'consent_given' => true; если нет — не добавляйте: лучше «неизвестно», чем ложное подтверждение.
Синтаксическая ошибка кладёт весь сайт — поэтому копию файла делают до правки. Восстановите файл по FTP, проверьте синтаксис php -l init.php и вставьте код заново. Правило на будущее: используйте /local/php_interface/init.php, а не файл в ядре.
Проверьте, что в $form_id_map слева стоит ID веб-формы Битрикса (Сервисы → Веб-формы → Список), а справа — form_id из кабинета: их регулярно путают местами. Упавший хук оставляет след в журнале: Настройки → Инструменты → Журнал событий. Для отладки добавьте перед curl_exec строку error_log('1opd: ' . $payload);.
Адрес сервера Битрикса не в IP-списке ключа. curl ifconfig.me по SSH покажет исходящий адрес; внесите его в кабинете на карточке ключа. Коробочный Битрикс24 живёт как обычный VPS; адрес облачного инстанса скажет поддержка Битрикса.
Обработчик объявлен дважды — например, после повторной вставки. Найдите все упоминания onAfterResultAdd и оставьте одно; проверьте оба файла: /local/php_interface/init.php и /bitrix/php_interface/init.php. Точный дубль в пределах 5 минут платформа погасит сама, но чинить причину всё равно нужно.
Некуда — своего PHP на облачном портале нет. Заведите исходящий вебхук на событие создания лида и страницу-приёмник на своём сайте (пример выше). Второй путь — шаг «HTTP-запрос» в бизнес-процессе или триггере CRM с телом в формате 1ОПД.