Development of a B2B portal on 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1167
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    563
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    743
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

1C-Bitrix B2B Portal Development

A standard Bitrix-based online store is not suitable for wholesale sales: it has a single price for all customers, a public catalog, lacks credit limits, and has no order approval workflow. When a sales manager spends 40 minutes manually processing each order through the CRM, and distributors call to check inventory levels—these are symptoms of a missing B2B portal, not staffing problems.

How a B2B Portal Differs Fundamentally from a Public Store

Architecturally, it has a different authorization logic, a different pricing model, and a different order workflow.

Authorization and user groups. In bitrix:sale, a user is tied to a single group. In B2B, you need a hierarchy: company → contact person → role (buyer, accountant, director). Standard Bitrix user groups don't work for this—they are flat. It's implemented via a custom module with a company_user linking table and an intermediate entity through D7 ORM (Bitrix\Main\ORM\Data\DataManager). Action permissions (create order, view debt, change delivery address) are set via a bitmask in the Highload block for roles.

Price types. The catalog module supports multiple price types: CATALOG_GROUP_ID in the b_catalog_price table. For B2B, this is essential mechanics—each user group is assigned its own price type. However, individual contract prices are more complex: you need a separate table of contract items with priority higher than the base type. It's implemented via the OnSaleOrderBeforeSaved event handler or via a custom price provider implementing Bitrix\Catalog\v2\Price\BasePriceProvider.

Catalog with real-time inventory. B2B buyers order in bulk and check availability before checkout. Inventory data in b_catalog_store_product is updated during 1C synchronization via CommerceML 2.10. If synchronization runs once per hour, clients see outdated data. Solution: 1C REST API + a change handler on the Bitrix side that updates inventory incrementally via CCatalogStoreProduct::Update().

Key Modules and Components

The sale module—the foundation for cart and orders. In B2B, it's enhanced: add statuses (Pending Approval, Approved, Rejected), configure business processes via the bizproc module to route orders to responsible parties.

The catalog module—pricing, trade offers (SKU), warehouse management. For B2B, CatalogGroup (price types) and DiscountCoupon for one-time promotions are mandatory.

The crm module (if using Bitrix24 integration)—syncs portal orders with CRM deals. The dependency is bidirectional: an order from the portal creates a deal, a status change in the deal changes the order status. Via REST API crm.deal.add / crm.deal.update with a webhook back.

Personal account—minimal set: order history with repeat functionality, current active orders, debt by reconciliation statements, documents (invoices, shipping papers in PDF), management of company contact persons.

1C Integration

This is typically the most labor-intensive part. Standard CommerceML exchange covers products, prices, warehouses, and orders. But it doesn't cover:

  • Credit limits and debt—exported separately as XML or via 1C REST service. On the Bitrix side—a custom Highload block b2b_credit_limits with fields: UF_COMPANY_ID, UF_CREDIT_LIMIT, UF_CURRENT_DEBT, UF_OVERDUE_DEBT, UF_UPDATED_AT
  • Documents—invoices and shipping papers are stored in 1C. The portal requests them via REST, receives PDF links or binary data. Cache in /upload/b2b/docs/ with a 24-hour TTL
  • Specifications—individual contract items not in the general price list. Synced via a separate format, stored in a Highload block linked to COMPANY_ID

Critically important: don't break the standard CommerceML exchange. Custom fields and logic go through events OnBeforeCatalogImport1C, OnSuccessCatalogImport1C, separate tables. Don't touch the core exchange.

Performance Under Load

A B2B portal with 500+ active companies and peak loads at the start of the workday has different requirements than a retail store.

  • Catalog cache—tagged, tag bound to IBLOCK_ID. CIBlock::clearIblockTagCache($iblockId) when updating inventory from 1C clears only needed pages
  • Prices—not cached at the component level if personal. Alternative: cache by key user_group_price_{groupId}_{productId}, invalidated when price changes
  • Sessions—with a load balancer across servers, sessions move to Redis, configured via \Bitrix\Main\Application::getInstance()->getSession()
  • Catalog search—the search module doesn't handle B2B filters well. Elasticsearch is connected via a custom indexer that bypasses CIBlockElement::GetList and directly forms documents for the index

Development Stages

Stage Content Duration
Analysis Role scheme, order workflows, 1C integration map 2-3 weeks
Database Design Highload blocks, D7 entities, pricing scheme 1-2 weeks
Backend Authorization module, pricing, 1C integration 4-8 weeks
Personal Account Orders, documents, company management 3-5 weeks
Order Approval bizproc business processes, notifications 1-3 weeks
Testing Load testing, acceptance, integration testing 2-3 weeks

Total: 12-22 weeks depending on the depth of 1C integration and the number of custom business rules.

Common Pitfalls

Storing personal prices in a session. Works until PHP-FPM restarts; with load balancing—lost. Prices are stored in the database or Redis, not in a session.

1C synchronization blocks the site. A full CommerceML import of 50K products takes 20-40 minutes and locks tables. Switch to incremental exchange: only changed items since the last sync.

Order approval logic written in init.php. 300 lines of order approval logic in init.php is technical debt that will need rewriting on any rule change. Move it to a separate module with configurable rules.