REST
Входящие вебхуки
Серверный POST-запрос с обработкой транспорта, HTTP-статуса, JSON и ошибки REST.
Из чего состоит адрес
Базовый URL входящего вебхука имеет вид https://example.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE/. Хук работает с правами владельца и выданными скоупами. Код в пути — секрет; его нельзя публиковать в исходниках приложения или логах.
Для примера сохраните базовый URL в серверной переменной окружения BITRIX24_WEBHOOK_BASE. Адрес берётся из вашей конфигурации, а не из запроса посетителя.
Минимальный серверный клиент
Требуется PHP 7.3+ с cURL. Функция возвращает весь ответ, поэтому рядом с result доступны данные пагинации. Пустые параметры отправляются JSON-объектом.
<?php
function callWebhook(string $webhook_base, string $method, array $parameters): array {
if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+$/D', $method)) {
throw new InvalidArgumentException('Некорректное имя метода');
}
$url_parts = parse_url($webhook_base);
if (!is_array($url_parts) || ($url_parts['scheme'] ?? '') !== 'https'
|| empty($url_parts['host']) || isset($url_parts['query'])
|| isset($url_parts['fragment']) || isset($url_parts['user'])
) {
throw new InvalidArgumentException('Нужен HTTPS URL вебхука из закрытой конфигурации');
}
$handle = curl_init(rtrim($webhook_base, '/') . '/' . $method . '.json');
curl_setopt_array($handle, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
CURLOPT_POSTFIELDS => json_encode((object) $parameters, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
]);
$body = curl_exec($handle);
$errno = curl_errno($handle);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($body === false) {
throw new RuntimeException('Ошибка транспорта cURL: ' . $errno);
}
if ($status < 200 || $status >= 300) {
throw new RuntimeException('REST вернул HTTP ' . $status);
}
$response = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if (!is_array($response)) {
throw new RuntimeException('Ожидался JSON-объект');
}
if (array_key_exists('error', $response)) {
throw new RuntimeException('REST: ' . (string) $response['error']);
}
if (!array_key_exists('result', $response)) {
throw new RuntimeException('В ответе нет result');
}
return $response;
}
$webhook_base = (string) getenv('BITRIX24_WEBHOOK_BASE');
$response = callWebhook($webhook_base, 'user.current', []);
$user_id = (int) ($response['result']['ID'] ?? 0);Клиент не записывает ответ или URL в журнал. На ошибке HTTP он сообщает статус; тело для дополнительной диагностики следует разбирать отдельно в закрытом обработчике, без токенов и персональных данных.
Что означает успешный HTTP-ответ
HTTP 200 ещё не означает успех метода. Нужно разобрать JSON и проверить error; неверный JSON нельзя превращать в пустой успешный результат. Значение result: false допустимо для некоторых методов и не равно отсутствию ключа.
После таймаута операция записи могла выполниться на портале. Не повторяйте создание вслепую: сначала найдите результат по внешнему ключу. Код выше намеренно не делает автоматических повторов.
Границы примера
Это клиент классического REST. REST 3.0 имеет отдельный маршрут и контракт ответа. Доступность метода также зависит от скоупа, пользователя, тарифа и версии коробки.