1C-Bitrix Integration with 1C:Enterprise
CommerceML: Why the Standard Exchange Is Both a Lifesaver and a Trap
The CommerceML 2.0 exchange module is the first thing everyone connects — and rightly so. With a standard Trade Management or Integrated Automation configuration, it can be up and running in a day or two. Products, prices, stock levels, orders — everything via XML files on a schedule. For a store with 3,000 SKUs and a couple of updates per day, this is more than enough.
Problems begin when the catalog exceeds 30,000 SKUs.
bitrix_1c_exchange.php generates XML on the Bitrix side, 1C fetches and parses it. On large catalogs, the parser starts writing heavily to the temporary table b_xml_tree — and that's where MySQL can grind to a halt. We've seen a project where standard exchange of 180,000 products took 6 hours and completely locked the server: neither the admin panel nor the frontend would load.
The solution is incremental exchange. In the exchange node settings on the 1C side, we enable "Export only modified items" and split the export into batches of 500–1,000 elements. On the Bitrix side — a custom handler that doesn't recreate b_xml_tree every time, but instead works through CIBlockXMLFile::ReadXMLToDatabase() with controlled batching. A catalog of 200,000 SKUs then updates in 8–12 minutes.
Another classic pitfall is EXTERNAL_ID. During re-import, Bitrix matches infoblock elements by external code. If a product was deleted and recreated in 1C with a new GUID, a duplicate appears on the site — with old reviews on one product card and zero on the other. The fix is strict matching by article number via a custom OnBeforeIBlockElementAdd event handler.
When CommerceML Is No Longer Enough
A heavily customized 1C setup isn't the exception — it's the norm. "We have a standard configuration," says every other client, and then we open the database to find 200 custom handlers, renamed attributes, and homegrown sales documents.
CommerceML works with a fixed XML structure. If 1C has modified the product attribute set or added a non-standard document, the exchange silently skips that data. Or it crashes with an obscure error in the 1C event log, while Bitrix logs nothing at all.
In such cases, we build a custom export. On the 1C side, we write a handler that generates JSON (not XML — faster to parse, easier to debug) and sends it via the Bitrix REST API. Full control: which fields we pull, how we transform them, what we do on conflict. For the heaviest cases — D7 API with direct operations through \Bitrix\Catalog\ProductTable and \Bitrix\Sale\Order.
Prices, Stock, and Multi-Warehouse
The standard exchange handles a single price type. In reality, there can be 15: retail, wholesale, dealer, promotional, regional, currency-based. Plus each has its own customer group and priority. Mapping between 1C price groups and Bitrix user groups is an engineering challenge in itself. It gets especially interesting when discounts overlap and you need to determine which price wins.
Multi-warehouse adds another layer: a product is in stock in one city, out of stock in another, and "available to order" in a third. The site needs to display availability per location, enable pickup point selection, and calculate shipping from the nearest warehouse that physically has the item. The standard Bitrix warehouse module (catalog.store) handles the display, but the "where to ship from" logic is custom.
Orders and Document Flow
An order from the site goes to 1C, a shipment document is created, inventory is reserved. Statuses come back. On paper — simple. In practice — nuances.
The main one: partial shipment. A customer ordered 5 items, 3 are in stock, 2 will arrive in a week. 1C creates two shipment documents. Out of the box, Bitrix can't split a single order into multiple shipments — so we customize the OnSaleOrderSaved handler to create child orders and synchronize statuses for each.
Documents in the customer portal — invoices, reconciliation acts, waybills from 1C — are served via REST, PDFs are generated on the 1C side and cached on CDN. The buyer downloads from the cache, not directly from 1C (which would kill the server).
Monitoring: Not "Set and Forget"
The exchange can break silently. The script ran, no errors in the log, but 200 products didn't update because of invalid UTF-8 in a product name. Or 1C changed the date format in an update, and all prices came through as zero.
The minimum monitoring stack we deploy on every project:
- Telegram alert if exchange time exceeds 3x the average
- Stock discrepancy check: a script compares
b_catalog_product.QUANTITYwith what 1C reports, and raises an alarm when the delta exceeds 5% - Dashboard: last sync time, number of processed items, queue, errors
For high-load projects, we add asynchronous queues via Redis or RabbitMQ. The exchange doesn't block the web server, and data isn't lost during brief 1C downtime.
Bitrix24 Integration
If there's a Bitrix24 corporate portal alongside the site, we connect that too. CRM counterparties flow into 1C, invoices from 1C appear in the deal card. The manager sees receivables and settlements without switching windows. Deal closed — documents are generated automatically.
Payment received in 1C → the logistics team gets a shipment task in Bitrix24. Item shipped → the manager sees a notification. Automated tasks triggered by 1C events — via Bitrix24 REST API webhooks.
Pricing
Standard catalog and order exchange via CommerceML starts at 50,000 RUB, delivered in 1–2 weeks. Extended exchange with multi-warehouse, price types, and counterparties — from 120,000 RUB. Full custom integration of 1C + website + Bitrix24 — from 250,000 RUB, timeline 1–2 months. Pays for itself in 2–6 months: a store with 5,000 products saves 40–80 hours of manual operator work per month, and automatic stock synchronization eliminates "ordered but out of stock" situations.







