Integration of 1C-Bitrix with the Mercury system

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

1C-Bitrix Integration with Mercury (Merkury)

Mercury is the Russian federal state veterinary certification information system (FGIS). Businesses handling products of animal origin (meat, fish, dairy, eggs) are required to issue electronic veterinary accompanying documents (eVAD) for every product movement. An online store accepting orders for such goods faces a specific challenge: when goods arrive at the warehouse and when they are dispatched, incoming eVADs must be cancelled and outgoing ones issued through the Mercury system.

Interaction architecture

Mercury provides a REST API (https://api.vetrf.ru/schema/platform/v2/). Authentication uses an API key issued by Rosselkhoznadzor (the Russian agricultural regulator) after the business is registered in the system.

Supplier → ships goods with eVAD in Mercury
  → Store receives goods → cancels incoming eVAD (acceptVetDocument)
    → Warehouse storage: inventory unit with eVAD ID
      → Order placed → sale to an individual
        → Write-off via return transaction (transferReceiptTransaction)

When selling to an end consumer (individual), no new eVAD needs to be issued — it is sufficient to cancel the document for the sold quantity.

PHP client for Mercury API

class MerkuryClient
{
    private string $apiUrl = 'https://api.vetrf.ru/schema/platform/v2';
    private string $apiKey;
    private string $issuerId; // enterprise ID in Mercury

    public function __construct(string $apiKey, string $issuerId)
    {
        $this->apiKey   = $apiKey;
        $this->issuerId = $issuerId;
    }

    public function getIncomingDocuments(string $enterpriseGuid): array
    {
        return $this->request('GET',
            "/enterprises/{$enterpriseGuid}/vetDocuments",
            ['status' => 'CONFIRMED', 'type' => 'INCOMING']
        );
    }

    public function extinguishDocument(
        string $enterpriseGuid,
        string $vetDocId,
        float  $quantity,
        string $unit
    ): string {
        $response = $this->request('POST',
            "/enterprises/{$enterpriseGuid}/vetDocuments/{$vetDocId}/extinguish",
            [
                'returnedQuantity' => $quantity,
                'returnedUnit'     => $unit,
                'operatorId'       => $this->issuerId,
            ]
        );
        return $response['application']['applicationId'];
    }

    public function processTransaction(
        string $enterpriseGuid,
        string $transactionId
    ): array {
        return $this->request('POST',
            "/enterprises/{$enterpriseGuid}/applications/{$transactionId}/process"
        );
    }

    private function request(string $method, string $path, array $params = []): array
    {
        // ... HTTP request with header 'apiKey: {KEY}'
    }
}

Storing eVADs in 1C-Bitrix

Each batch of goods in the warehouse corresponds to one or more eVADs. Table structure:

class VetDocumentTable extends \Bitrix\Main\ORM\Data\DataManager
{
    public static function getTableName(): string { return 'local_merkury_vet_docs'; }

    public static function getMap(): array
    {
        return [
            new \Bitrix\Main\ORM\Fields\IntegerField('ID',          ['primary' => true, 'autocomplete' => true]),
            new \Bitrix\Main\ORM\Fields\IntegerField('PRODUCT_ID'),  // catalog product
            new \Bitrix\Main\ORM\Fields\StringField('VET_DOC_ID'),   // document UUID in Mercury
            new \Bitrix\Main\ORM\Fields\StringField('ENTERPRISE_GUID'), // enterprise GUID
            new \Bitrix\Main\ORM\Fields\FloatField('QUANTITY'),      // remaining stock
            new \Bitrix\Main\ORM\Fields\StringField('UNIT'),         // unit of measure: kg, piece
            new \Bitrix\Main\ORM\Fields\StringField('STATUS'),       // 'active', 'extinguished'
            new \Bitrix\Main\ORM\Fields\DatetimeField('EXPIRE_DATE'), // expiry date
        ];
    }
}

When a batch arrives, a record is created with the eVAD ID and quantity. On sale, the quantity decreases; when exhausted, the status changes to extinguished.

Cancelling eVADs on dispatch

public function handleOrderShipped(\Bitrix\Sale\Order $order): void
{
    $basket = $order->getBasket();
    foreach ($basket as $item) {
        $productId = $item->getProductId();
        $quantity  = $item->getQuantity();

        // Find the active eVAD for the product
        $vetDoc = VetDocumentTable::getList([
            'filter' => ['PRODUCT_ID' => $productId, 'STATUS' => 'active'],
            'order'  => ['EXPIRE_DATE' => 'ASC'], // nearest expiry first
            'limit'  => 1,
        ])->fetch();

        if (!$vetDoc) {
            \Bitrix\Main\Diag\Debug::writeToFile(
                "No eVAD for product {$productId}",
                '[MERKURY ERROR]', '/local/logs/merkury.log'
            );
            continue;
        }

        $appId = $this->merkury->extinguishDocument(
            $vetDoc['ENTERPRISE_GUID'],
            $vetDoc['VET_DOC_ID'],
            $quantity,
            $vetDoc['UNIT']
        );

        // Process the transaction
        $this->merkury->processTransaction($vetDoc['ENTERPRISE_GUID'], $appId);

        // Update the remaining quantity in the local table
        $newQty = $vetDoc['QUANTITY'] - $quantity;
        VetDocumentTable::update($vetDoc['ID'], [
            'QUANTITY' => max(0, $newQty),
            'STATUS'   => $newQty <= 0 ? 'extinguished' : 'active',
        ]);
    }
}

Case study: farm produce store

An online store selling meat and dairy products from farms. Approximately 250 orders per week. Goods arrive from 15 suppliers, each batch with a separate eVAD. The goal: automate receiving (cancelling incoming eVADs) and dispatch (write-off on sale).

Key details:

The Mercury API operates asynchronously: a cancellation request creates an "application" that must be processed with a separate call. Sometimes applications take several minutes to process — the Mercury system experiences significant load.

A two-step model was implemented: on dispatch, an application is created and queued; a cron job runs every 2 minutes and calls processTransaction for pending applications.

Goods receiving: the storekeeper enters the receipt ID from the supplier's delivery note in the 1C-Bitrix admin area → the system automatically retrieves the list of incoming eVADs from that supplier for the past 24 hours → the storekeeper confirms the batch correspondence → Mercury records the receipt.

Metric Before After
Time to process a single batch receipt 15 min (manual entry in Mercury) 3 min (confirmation)
eVAD cancellation on sale Not performed (violation) Automatic
Rosselkhoznadzor inspections Compliance notice issued No findings

Stock synchronisation

Periodic reconciliation: quantities in the local_merkury_vet_docs table are compared with enterprise stock in Mercury (GET /enterprises/{guid}/stockEntries). Discrepancies are logged and the administrator is notified.

Scope of work

  • Mercury registration, obtaining API key (via Rosselkhoznadzor)
  • PHP client development: incoming documents, cancellation, reconciliation
  • eVAD storage table in 1C-Bitrix
  • Receiving interface in the admin area
  • Automatic cancellation on dispatch with retry queue
  • Stock synchronisation (cron), discrepancy monitoring

Timeline: 6–10 weeks depending on the number of suppliers and warehouse management complexity.