Разработка модуля интеграции с внешним API 1С-Битрикс
Интеграция «через пять строк cURL в каком-то файле» — классическая техническая задолженность в Битрикс-проектах. Такой код не логируется, не обрабатывает ошибки, не поддерживает ретраи и разлетается при смене API-ключа. Полноценный модуль интеграции решает эти проблемы системно.
Принципы архитектуры интеграционного модуля
Хороший модуль интеграции состоит из нескольких слоёв:
- HTTP-клиент — абстракция над транспортом (cURL/Guzzle), управление аутентификацией, таймаутами, ретраями
- API Gateway — методы, соответствующие конкретным эндпоинтам внешнего API
- Mapper/DTO — преобразование данных между форматом API и форматом Битрикс
- Queue/Retry — очередь для асинхронных запросов и повторных попыток при ошибках
- Logger — журнал всех запросов/ответов для диагностики
- Admin UI — настройки подключения, мониторинг, ручной запуск синхронизации
HTTP-клиент с retry-логикой
namespace Vendor\Integration\Http;
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\HttpHeaders;
class ApiClient
{
private HttpClient $http;
private string $baseUrl;
private string $apiKey;
private int $maxRetries = 3;
public function request(string $method, string $endpoint, array $data = []): array
{
$attempt = 0;
$lastException = null;
while ($attempt < $this->maxRetries) {
try {
$response = $this->doRequest($method, $endpoint, $data);
$this->logRequest($method, $endpoint, $data, $response);
return $response;
} catch (RateLimitException $e) {
sleep(pow(2, $attempt)); // Экспоненциальный бэкофф
$attempt++;
$lastException = $e;
} catch (ApiException $e) {
$this->logError($method, $endpoint, $e);
throw $e; // Не ретраим бизнес-ошибки
}
}
throw $lastException;
}
}
Логирование запросов
Журнал запросов — обязательная часть продуктового модуля. Без него поддержка превращается в угадывание. ORM-таблица для логов:
// lib/Orm/ApiLogTable.php
class ApiLogTable extends DataManager
{
public static function getTableName(): string { return 'vendor_integration_log'; }
public static function getMap(): array
{
return [
new IntegerField('ID', ['primary' => true, 'autocomplete' => true]),
new StringField('METHOD'), // GET/POST/PUT
new StringField('ENDPOINT'),
new TextField('REQUEST_BODY'),
new IntegerField('STATUS_CODE'),
new TextField('RESPONSE_BODY'),
new FloatField('DURATION_MS'), // время выполнения
new StringField('ERROR'),
new DatetimeField('CREATED_AT'),
];
}
}
В административном разделе реализуется список запросов с фильтрацией по статусу, дате, эндпоинту. Это первое место, куда смотрит разработчик при диагностике.
Очередь для асинхронной синхронизации
Синхронные вызовы внешних API во время пользовательского запроса — антипаттерн: внешний сервис может быть медленным или недоступным. Тяжёлые операции (обновление каталога из 1С, синхронизация заказов) выносятся в очередь.
Реализация через агенты Битрикс:
// Агент запускается по cron каждые N минут
public static function processSyncQueue(): string
{
$items = SyncQueueTable::getList([
'filter' => ['STATUS' => 'pending', '<ATTEMPTS' => 3],
'limit' => 50,
'order' => ['CREATED_AT' => 'ASC'],
]);
foreach ($items as $item) {
try {
static::processItem($item);
SyncQueueTable::update($item['ID'], ['STATUS' => 'done']);
} catch (\Exception $e) {
SyncQueueTable::update($item['ID'], [
'STATUS' => $item['ATTEMPTS'] >= 2 ? 'failed' : 'pending',
'ATTEMPTS' => $item['ATTEMPTS'] + 1,
'LAST_ERROR' => $e->getMessage(),
'NEXT_ATTEMPT' => (new \Bitrix\Main\Type\DateTime())->add('PT' . pow(2, $item['ATTEMPTS']) . 'M'),
]);
}
}
return '\Vendor\Integration\SyncAgent::processSyncQueue();'; // Возврат для повторного запуска
}
Webhook-обработчик
Если внешняя система отправляет события (webhook), модуль регистрирует публичный URL для приёма:
// Публичный обработчик: /local/api/integration/webhook.php
use Bitrix\Main\Application;
$request = Application::getInstance()->getContext()->getRequest();
$payload = json_decode($request->getInput(), true);
// Проверка подписи
$signature = $request->getHeader('X-Signature');
if (!WebhookSecurity::verify($payload, $signature)) {
http_response_code(401);
exit;
}
// Постановка в очередь обработки
SyncQueueTable::add([
'TYPE' => 'webhook_' . ($payload['event'] ?? 'unknown'),
'PAYLOAD' => json_encode($payload),
'STATUS' => 'pending',
]);
http_response_code(200);
echo json_encode(['ok' => true]);
Настройки модуля
Настройки (URL API, ключи, режим работы) хранятся через \Bitrix\Main\Config\Option:
// Запись настройки
Option::set('vendor.integration', 'api_key', $encryptedKey);
Option::set('vendor.integration', 'api_url', 'https://api.service.com/v2');
// Чтение
$apiKey = Option::get('vendor.integration', 'api_key');
Чувствительные данные (API-ключи, пароли) шифруются перед сохранением через \Bitrix\Main\Security\Sign\Signer или стандартную функцию \Bitrix\Main\Crypt.
Типичные сроки разработки
| Конфигурация | Срок |
|---|---|
| Простая интеграция: 3–5 методов, без очереди | 1–2 недели |
| Двусторонняя синхронизация, очередь, логи | 3–5 недель |
| Сложная интеграция: webhook, маппинг, UI | 6–10 недель |
| Интеграция с 1С через CommerceML/REST | 4–8 недель |
Модуль документируется на уровне архитектуры (диаграмма потоков данных) и на уровне эксплуатации (инструкция для администратора с описанием настроек и интерпретацией ошибок).







