Разработка промежуточного сервиса обмена 1С и 1С-Битрикс
Прямая интеграция 1С и Битрикс работает до тех пор, пока систем две. Как только появляется третья — CRM, складская программа, маркетплейс — прямые связи превращаются в паутину. Промежуточный сервис (middleware) решает это архитектурно: каждая система общается только с ним.
Когда нужен промежуточный сервис
- Несколько сайтов на Битрикс подключены к одной 1С
- 1С + Битрикс + CRM (AmoCRM, Bitrix24) — данные нужно синхронизировать между всеми
- Нестандартная конфигурация 1С без HTTP-сервисов — нужен адаптер
- Требования к трансформации данных сложнее, чем можно реализовать в CommerceML-маппинге
- Бизнес-логика обмена должна быть изолирована и тестируема отдельно от 1С и Битрикс
Архитектура middleware
[1С] ←→ [Middleware] ←→ [Битрикс]
←→ [CRM]
←→ [Маркетплейс]
Middleware — отдельное приложение (PHP, Node.js, Python, Go — по стеку команды). Функции:
- Адаптеры подключения: умеет читать/писать в каждую систему через её API
- Маппинг данных: преобразует объекты из формата одной системы в формат другой
- Очередь задач: хранит задачи на синхронизацию, обеспечивает повторы при сбоях
- Журнал обмена: история всех операций с результатами
- Конфигурация правил: какие поля синхронизировать, в каком направлении, с какими преобразованиями
Технический стек для middleware на PHP
Laravel (или Symfony) + PostgreSQL + Redis (очередь) + Horizon (мониторинг очередей)
Структура приложения:
app/
Adapters/
OneCAdapter.php # Читает/пишет в 1С через HTTP-сервисы
BitrixAdapter.php # Читает/пишет в Битрикс через REST API
CrmAdapter.php # AmoCRM / Bitrix24
Mappers/
ProductMapper.php # 1С Номенклатура → Битрикс элемент инфоблока
OrderMapper.php # Битрикс заказ → 1С документ
Jobs/
SyncProductsJob.php # Задача синхронизации товаров
SyncOrdersJob.php # Задача синхронизации заказов
Models/
SyncLog.php # Модель журнала обмена
SyncQueue.php # Таблица очереди задач
Адаптер Битрикс REST API
class BitrixAdapter
{
private string $webhookUrl;
public function getOrders(array $filter = []): array
{
$response = $this->call('crm.deal.list', [
'filter' => $filter,
'select' => ['ID', 'TITLE', 'STAGE_ID', 'OPPORTUNITY', 'UF_ORDER_ID'],
]);
return $response['result'] ?? [];
}
public function updateProductStock(int $productId, int $quantity): bool
{
$response = $this->call('catalog.storeProduct.update', [
'id' => $productId,
'fields' => ['AMOUNT' => $quantity],
]);
return $response['result'] ?? false;
}
public function createOrder(array $fields): int
{
$response = $this->call('sale.order.add', ['fields' => $fields]);
return $response['result']['order']['id'] ?? 0;
}
private function call(string $method, array $params = []): array
{
$response = file_get_contents(
$this->webhookUrl . $method . '.json?' . http_build_query($params)
);
return json_decode($response, true);
}
}
Маппер с правилами трансформации
class ProductMapper
{
private array $categoryMapping; // 1С группа → Битрикс секция
private array $propertyMapping; // 1С реквизит → Битрикс свойство
public function oneCToBitrix(array $oneCProduct): array
{
return [
'IBLOCK_ID' => config('bitrix.catalog_iblock_id'),
'XML_ID' => $oneCProduct['Ref_Key'],
'NAME' => $oneCProduct['Description'],
'ACTIVE' => $oneCProduct['DeletionMark'] ? 'N' : 'Y',
'DETAIL_TEXT' => $oneCProduct['КомментарийДляСайта'],
'IBLOCK_SECTION_ID' => $this->mapCategory($oneCProduct['ОсновнаяТоварнаяГруппа_Key']),
'PROPERTY_ARTICLE' => $oneCProduct['Артикул'],
'PROPERTY_WEIGHT' => $oneCProduct['Вес'] * 1000, // кг → г
'PROPERTY_BRAND' => $this->resolveBrand($oneCProduct['Производитель_Key']),
];
}
private function mapCategory(string $oneCGroupGuid): int
{
return $this->categoryMapping[$oneCGroupGuid] ?? config('bitrix.default_section_id');
}
}
Очередь и надёжность
class SyncProductsJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3;
public int $backoff = 300; // 5 минут между попытками
public function handle(OneCAdapter $oneC, BitrixAdapter $bitrix, ProductMapper $mapper): void
{
$products = $oneC->getModifiedProducts($this->sinceDate);
foreach ($products as $oneCProduct) {
try {
$bitrixFields = $mapper->oneCToBitrix($oneCProduct);
$bitrix->upsertProduct($bitrixFields);
SyncLog::create([
'entity' => 'product',
'external_id' => $oneCProduct['Ref_Key'],
'status' => 'success',
]);
} catch (\Exception $e) {
SyncLog::create([
'entity' => 'product',
'external_id' => $oneCProduct['Ref_Key'],
'status' => 'error',
'message' => $e->getMessage(),
]);
// Не останавливаем всю партию из-за одного элемента
}
}
}
}
Мониторинг и операционный интерфейс
Middleware без интерфейса управления — чёрный ящик. Минимальный dashboard:
- Статус последних сеансов обмена (успех / ошибка / время)
- Список ошибок с возможностью повторного запуска
- Статистика: сколько объектов синхронизировано за сутки/неделю
- Ручной запуск синхронизации для отдельного объекта или типа данных
Реализуется как простой Laravel/Symfony веб-интерфейс или через Laravel Horizon (мониторинг очередей).
Сроки разработки
| Объём middleware | Срок |
|---|---|
| Два адаптера (1С + Битрикс) + 2–3 маппера + очередь | 3–5 недель |
| + 3-я система (CRM) + расширенный маппинг | +2–3 недели |
| + Dashboard мониторинга + ручное управление | +1–2 недели |
| Полная система для 5+ систем | 3–6 месяцев |







