Реалізація імпорту товарів з 1С (CommerceML/XML)
Обмін даними між 1С і сайтом — одна з найбільш затребуваних і технічно неоднозначних задач у веб-розробці. Стандарт CommerceML існує з 2000-х років, але кожна конфігурація 1С реалізує його по-своєму: структура XML, наповнення полів, логіка виповугрузки категорій і характеристик різняться. Універсального рішення не має — потрібна інтеграція під конкретну конфігурацію.
Стандарт CommerceML
1С выгружає дані в ZIP-архівах з XML-файлами:
import.zip
├── import.xml — каталог товарів, категорії, властивості
├── offers.xml — склади, ціни, залишки
└── import0.xml — продовження каталогу (при розбивці на файли)
Приклад структури:
<?xml version="1.0" encoding="UTF-8"?>
<КоммерческаяИнформация ВерсияСхемы="2.10">
<Каталог>
<Группы>
<Группа>
<Ид>f47ac10b-58cc-4372-a567-0e02b2c3d479</Ід>
<Наименование>Електроніка</Наименование>
</Группа>
</Группы>
<Товары>
<Товар>
<Ід>550e8400-e29b-41d4-a716-446655440000</Ід>
<Артикул>IPH-15-PRO-256</Артикул>
<Наименование>iPhone 15 Pro 256GB</Наименование>
</Товар>
</Товары>
</Каталог>
</КоммерческаяИнформация>
Протокол обміну
1С ініціює обмін через HTTP-запити до сайту. Сайт реалізує обробник на певних URL:
GET /1c-exchange/?type=catalog&mode=checkauth
GET /1c-exchange/?type=catalog&mode=init
POST /1c-exchange/?type=catalog&mode=file&filename=import.zip
GET /1c-exchange/?type=catalog&mode=import&filename=import.xml
Послідовність:
-
checkauth— 1С перевіряє авторизацію -
init— отримує ліміти (максимальний розмір файлу, zip або ні) -
file— завантажує XML-файли -
import— запрошує імпорт конкретного файлу
Реалізація обробника (PHP/Laravel)
class OnecExchangeController extends Controller
{
public function handle(Request $request)
{
$mode = $request->query('mode');
return match($mode) {
'checkauth' => $this->checkAuth($request),
'init' => $this->init(),
'file' => $this->uploadFile($request),
'import' => $this->importFile($request),
default => response('failure', 400),
};
}
private function checkAuth(Request $request): Response
{
if (!$this->validateCredentials($request)) {
return response("failure\nНеверний логін або пароль");
}
$cookie = Str::random(32);
Cache::put("1c_session_{$cookie}", true, 600);
return response("success\nCOOKIE\n1c_session={$cookie}");
}
private function init(): Response
{
return response(implode("\n", [
'zip=yes',
'file_limit=' . (32 * 1024 * 1024),
]));
}
private function uploadFile(Request $request): Response
{
$filename = $request->query('filename');
$request->file('file')->storeAs('1c-exchange', $filename);
return response('success');
}
private function importFile(Request $request): Response
{
$filename = $request->query('filename');
ImportFrom1cJob::dispatch($filename);
return response('success');
}
}
Парсинг XML
class CommerceMLParser
{
public function parseImport(string $xmlPath): void
{
$xml = simplexml_load_file($xmlPath, 'SimpleXMLElement', LIBXML_NOCDATA);
foreach ($xml->Каталог->Товары->Товар as $item) {
$guid = (string) $item->Ід;
$sku = (string) $item->Артикул;
$name = (string) $item->Наименование;
Product::updateOrCreate(
['onec_guid' => $guid],
['sku' => $sku, 'name' => $name]
);
}
}
}
Обробка offers.xml (ціни та залишки)
public function parseOffers(string $xmlPath): void
{
$xml = simplexml_load_file($xmlPath);
foreach ($xml->ПакетПредложений->Предложения->Предложение as $offer) {
$guid = (string) $offer->Ід;
$price = (float) $offer->Цены->Цена->ЦенаЗаЕдиницу;
$stock = (int) $offer->Количество;
Product::where('onec_guid', $guid)->update([
'price' => $price,
'stock' => $stock,
]);
}
}
Асинхронний імпорт
Великі каталоги (10 000+ товарів) не можна обробляти синхронно — 1С очікує відповіді впродовж кількох секунд. Рішення:
- Файл зберігається відразу (
uploadFile) -
importFileповертаєsuccessнегайно - Обробка запускається в фоні через Laravel Queue
- Прогрес доступний через окремий endpoint
Лінія часу
Імпорт товарів з однієї конфігурації 1С (каталог + ціни + залишки): 8–12 робочих днів. Включає тестування на реальних даних клієнта та відладку edge-cases конкретної конфігурації 1С.







