Development of an intermediate service for exchanging 1C and 1C-Bitrix data

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
    1175
  • 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
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • 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

Developing a Middleware Exchange Service for 1C and 1C-Bitrix

A direct 1C and 1C-Bitrix integration works fine as long as there are only two systems. The moment a third one appears — a CRM, a warehouse system, a marketplace — direct connections turn into a tangled web. A middleware service resolves this architecturally: each system communicates only with the middleware.

When a Middleware Service Is Needed

  • Multiple 1C-Bitrix websites connected to a single 1C instance
  • 1C + 1C-Bitrix + CRM (AmoCRM, Bitrix24) — data must be synchronized across all systems
  • Non-standard 1C configuration without HTTP services — an adapter is required
  • Data transformation requirements too complex to handle in a CommerceML mapping
  • Exchange business logic must be isolated and testable independently of 1C and 1C-Bitrix

Middleware Architecture

[1C] ←→ [Middleware] ←→ [1C-Bitrix]
                     ←→ [CRM]
                     ←→ [Marketplace]

Middleware is a standalone application (PHP, Node.js, Python, Go — depending on the team's stack). Its functions:

  1. Connection adapters: reads from and writes to each system via its API
  2. Data mapping: transforms objects from one system's format into another's
  3. Task queue: stores synchronization tasks and ensures retries on failure
  4. Exchange log: a history of all operations with their results
  5. Rule configuration: which fields to sync, in which direction, with what transformations

PHP Middleware Tech Stack

Laravel (or Symfony) + PostgreSQL + Redis (queue) + Horizon (queue monitoring)

Application structure:

app/
  Adapters/
    OneCAdapter.php        # Reads/writes to 1C via HTTP services
    BitrixAdapter.php      # Reads/writes to 1C-Bitrix via REST API
    CrmAdapter.php         # AmoCRM / Bitrix24
  Mappers/
    ProductMapper.php      # 1C Item → 1C-Bitrix infoblock element
    OrderMapper.php        # 1C-Bitrix order → 1C document
  Jobs/
    SyncProductsJob.php    # Product sync job
    SyncOrdersJob.php      # Order sync job
  Models/
    SyncLog.php            # Exchange log model
    SyncQueue.php          # Task queue table

1C-Bitrix REST API Adapter

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);
    }
}

Mapper with Transformation Rules

class ProductMapper
{
    private array $categoryMapping; // 1C group → 1C-Bitrix section
    private array $propertyMapping; // 1C attribute → 1C-Bitrix property

    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, // kg → g
            'PROPERTY_BRAND' => $this->resolveBrand($oneCProduct['Производитель_Key']),
        ];
    }

    private function mapCategory(string $oneCGroupGuid): int
    {
        return $this->categoryMapping[$oneCGroupGuid] ?? config('bitrix.default_section_id');
    }
}

Queue and Reliability

class SyncProductsJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public int $backoff = 300; // 5 minutes between retries

    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(),
                ]);
                // Do not halt the entire batch because of one item
            }
        }
    }
}

Monitoring and Operational Interface

A middleware without a management interface is a black box. Minimum dashboard requirements:

  • Status of the latest exchange sessions (success / error / duration)
  • Error list with the ability to retry individual items
  • Statistics: how many objects were synchronized over the past day/week
  • Manual trigger for synchronizing a specific object or data type

Implemented as a simple Laravel/Symfony web interface or via Laravel Horizon (queue monitoring).

Development Timelines

Middleware Scope Duration
Two adapters (1C + 1C-Bitrix) + 2–3 mappers + queue 3–5 weeks
+ 3rd system (CRM) + extended mapping +2–3 weeks
+ Monitoring dashboard + manual controls +1–2 weeks
Full system for 5+ systems 3–6 months