Розробка кастомного обміну 1С і 1С-Бітрікс
Стандартний CommerceML закриває типові завдання: товари, ціни, залишки, замовлення. Коли вимоги виходять за цей периметр — кастомна розробка обміну. Приводів достатньо: нестандартна структура документів у 1С, кілька джерел даних, бізнес-логіка, яку не можна виразити в XML.
Коли стандартний обмін не підходить
- Нестандартна конфігурація 1С без підтримки CommerceML (галузеві рішення, кастомні конфігурації)
- Передача даних, яких немає в CommerceML: заявки, тендери, сервісні звернення
- Вимоги до реального часу: оновлення залишків негайно при зміні в 1С
- Складна трансформація даних: дані з кількох довідників 1С збираються в один об'єкт Бітрікс
- Інтеграція кількох систем: 1С + CRM + Бітрікс через єдиний шлюз
Архітектурні варіанти кастомного обміну
Варіант 1: HTTP-сервіси 1С (REST API)
Сучасні конфігурації (УТ 11.4+, ERP 2.5+, КА 2.5+) підтримують публікацію HTTP-сервісів. 1С публікується на веб-сервері (Apache/nginx), Бітрікс звертається до endpoint'ів по REST.
class OneCApiClient
{
private string $baseUrl;
private string $token;
public function getProducts(array $filters = [], int $limit = 100, int $offset = 0): array
{
return $this->request('GET', '/hs/exchange/products', [
'modified_since' => $filters['modified_since'] ?? null,
'limit' => $limit,
'offset' => $offset,
]);
}
public function createOrder(array $orderData): array
{
return $this->request('POST', '/hs/exchange/orders', $orderData);
}
public function updateOrderStatus(string $orderId, string $status): bool
{
$result = $this->request('PUT', "/hs/exchange/orders/{$orderId}/status", [
'status' => $status,
]);
return $result['success'] ?? false;
}
private function request(string $method, string $path, array $data = []): array
{
$ch = curl_init();
$url = $this->baseUrl . $path;
if ($method === 'GET' && $data) {
$url .= '?' . http_build_query($data);
}
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $this->token,
'Content-Type: application/json',
],
CURLOPT_CUSTOMREQUEST => $method,
]);
if ($method !== 'GET') {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200 && $httpCode !== 201) {
throw new \RuntimeException("1C API error: HTTP {$httpCode}. Response: {$response}");
}
return json_decode($response, true);
}
}
Варіант 2: Подієвий обмін (webhooks із 1С)
1С при зміні даних надсилає HTTP-запит на Бітрікс. Для цього в конфігурації 1С додається підписка на події (зміна залишків, зміна статусу замовлення) і HTTP-запит при спрацюванні.
На стороні Бітрікс — endpoint для прийому подій:
// /local/api/1c/webhook.php
$payload = json_decode(file_get_contents('php://input'), true);
$eventType = $payload['event_type'] ?? '';
switch ($eventType) {
case 'stock_changed':
StockSyncHandler::handle($payload['products']);
break;
case 'order_status_changed':
OrderStatusHandler::handle($payload['order_id'], $payload['status']);
break;
case 'price_changed':
PriceSyncHandler::handle($payload['prices']);
break;
}
http_response_code(200);
echo json_encode(['ok' => true]);
Подієвий обмін дає актуальність даних у реальному часі — без опитування за розкладом.
Трансформація даних
Кастомний обмін вимагає явної логіки маппінгу. Типовий складний кейс: у 1С товар зберігається в трьох пов'язаних довідниках (Номенклатура, Характеристики, Серії), у Бітрікс це має бути один елемент інфоблоку з торговими пропозиціями.
class ProductTransformer
{
public function transform(array $oneCNomenclature): array
{
$product = [
'NAME' => $oneCNomenclature['name'],
'CODE' => \CUtil::translit($oneCNomenclature['name'], 'ru'),
'XML_ID' => $oneCNomenclature['guid'],
'ACTIVE' => $oneCNomenclature['active'] ? 'Y' : 'N',
'DETAIL_TEXT' => $oneCNomenclature['description'],
'PROPERTY_ARTICLE' => $oneCNomenclature['article'],
'PROPERTY_BRAND' => $this->getBrandId($oneCNomenclature['manufacturer_guid']),
];
// Збираємо торгові пропозиції з характеристик
$offers = [];
foreach ($oneCNomenclature['characteristics'] as $char) {
$offers[] = [
'XML_ID' => $char['guid'],
'NAME' => $oneCNomenclature['name'] . ' / ' . $char['value'],
'PROPERTY_COLOR' => $this->getColorId($char['color_guid']),
'PROPERTY_SIZE' => $char['size'],
'CATALOG_PRICE_1' => $char['price'],
'CATALOG_QUANTITY' => $char['stock'],
];
}
$product['OFFERS'] = $offers;
return $product;
}
}
Черги для надійної доставки
Прямий синхронний обмін ламається при недоступності однієї із систем. Надійна схема — через чергу:
// При зміні замовлення в Бітрікс — додати завдання в чергу
\Bitrix\Main\EventManager::getInstance()->addEventHandler(
'sale',
'OnSaleOrderSaved',
function(\Bitrix\Main\Event $event) {
$order = $event->getParameter('ENTITY');
if ($order->isNew() || $order->getFields()->isChanged('STATUS_ID')) {
// Додати в чергу на передачу в 1С
\MyProject\Queue\ExchangeQueue::push([
'type' => 'order_sync',
'order_id' => $order->getId(),
'created_at' => time(),
]);
}
}
);
Воркер обробляє чергу та повторює спроби при тимчасовій недоступності 1С.
Версіонування та зворотна сумісність
Кастомний обмін живе роками. Оновлення 1С змінюють структуру API. Правильний підхід — версіоновані endpoint'и (/hs/exchange/v2/products) та явна документація контракту обміну. При зміні API на стороні 1С — нова версія endpoint'у, стара працює до узгодженого терміну відключення.
Терміни розробки
| Складність | Приклади | Термін |
|---|---|---|
| Простий REST-клієнт для стандартних об'єктів | Синхронізація 1–2 довідників | 3–5 днів |
| Двосторонній обмін із трансформацією | Нестандартна структура номенклатури | 2–4 тижні |
| Подієвий обмін + черги | Реальний час, висока надійність | 3–6 тижнів |
| Повноцінний інтеграційний шлюз | Кілька систем, складна бізнес-логіка | 1–3 місяці |







