Integration of 1C-Bitrix with the Honest Sign 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 Honest Sign (Chestny Znak)

Honest Sign is Russia's mandatory product labeling system. Since 2020–2024, labeling requirements have expanded to footwear, clothing, dairy products, tobacco, water, perfumery, dietary supplements, antiseptics, and several other categories. Any online store selling labeled goods is required to retire Data Matrix codes from circulation at the point of sale. Without integration with Honest Sign, the business faces administrative fines and potential blocking.

How labeling works in e-commerce

When goods arrive at the warehouse, labeling codes are registered in Honest Sign (entered into circulation). When sold, they are retired from circulation (recording the fact of sale to the end consumer). Retirement happens either through a fiscal receipt via an OFD (fiscal data operator) or directly through the Honest Sign API.

For an online store, the flow is:

  1. Goods arrive at the warehouse → codes are scanned → entered into circulation via the Honest Sign API
  2. Order is placed → at dispatch/handover, a receipt is generated via OFD containing the labeling code → OFD automatically retires the code from circulation

If OFD is not used (click-and-collect without a cash register receipt, courier delivery with an electronic receipt) — codes are retired directly via the Honest Sign API.

Honest Sign API (GIS MT)

The API is available at https://ismp.crpt.ru/api/v3/. Authentication uses a JWT token obtained with a qualified electronic signature (QES):

class ChestnyZnakClient
{
    private string $baseUrl = 'https://ismp.crpt.ru/api/v3';
    private string $token;

    public function __construct(private string $inn, private string $certSerial)
    {
        $this->token = $this->authenticate();
    }

    private function authenticate(): string
    {
        // Step 1: request data to sign
        $authData = $this->httpGet('/auth/cert/key');
        $uuid = $authData['uuid'];
        $data = $authData['data'];

        // Step 2: sign data with QES
        $signature = $this->signWithCert($data, $this->certSerial);

        // Step 3: obtain token
        $tokenResponse = $this->httpPost('/auth/cert/', [
            'uuid'      => $uuid,
            'data'      => $data,
            'signature' => base64_encode($signature),
        ]);

        return $tokenResponse['token'];
    }

    public function withdrawCodes(array $codes, string $docType = 'SELL'): string
    {
        $documents = [];
        foreach ($codes as $code) {
            $documents[] = [
                'certificateDocument'    => '',
                'certificateDocumentDate' => '',
                'certificateDocumentNumber' => '',
                'tnvedCode'              => '',
                'uitCode'                => $code,
                'uituCode'               => '',
            ];
        }

        $response = $this->httpPost('/lk/documents/create', [
            'document_format' => 'MANUAL',
            'product_document' => base64_encode(json_encode([
                'participantInn' => $this->inn,
                'documentFormat' => 'MANUAL',
                'type'           => $docType, // SELL, RETURN, LOSS
                'transferDate'   => date('Y-m-d'),
                'products'       => $documents,
            ])),
            'signature' => $this->signPayload(...),
            'type'      => $docType,
        ]);

        return $response['documentId'];
    }
}

Storing labeling codes in 1C-Bitrix

Data Matrix codes are stored in a custom table linked to order line items:

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

    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 ID
            new \Bitrix\Main\ORM\Fields\StringField('CODE'),         // Data Matrix code
            new \Bitrix\Main\ORM\Fields\StringField('STATUS'),       // 'in_stock', 'in_order', 'sold'
            new \Bitrix\Main\ORM\Fields\IntegerField('ORDER_ID'),    // null until assigned to an order
            new \Bitrix\Main\ORM\Fields\IntegerField('BASKET_ITEM_ID'),
            new \Bitrix\Main\ORM\Fields\DatetimeField('WITHDRAWAL_DATE'),
        ];
    }
}

When a product is added to an order, a specific labeling code is reserved for that line item. If the order is cancelled, the code is released back to in_stock status.

Retiring codes at dispatch

// Order shipment event handler
public function handleOrderShipped(\Bitrix\Sale\Order $order): void
{
    $markedItems = $this->getMarkedItemsFromOrder($order);
    if (empty($markedItems)) return;

    $codes = array_column($markedItems, 'CODE');
    $chestnyZnak = new ChestnyZnakClient(CZ_INN, CZ_CERT_SERIAL);
    $documentId  = $chestnyZnak->withdrawCodes($codes, 'SELL');

    // Update code statuses
    foreach ($markedItems as $item) {
        MarkingCodeTable::update($item['ID'], [
            'STATUS'          => 'sold',
            'ORDER_ID'        => $order->getId(),
            'WITHDRAWAL_DATE' => new \Bitrix\Main\Type\DateTime(),
            'CZ_DOCUMENT_ID'  => $documentId,
        ]);
    }
}

Case study: clothing store with mandatory labeling

A women's clothing store processing approximately 1,500 orders per month. Products are labeled light-industry garments. The requirement: automatically retire codes from circulation on every dispatch, and return codes to circulation on returns.

Implementation details:

Labeling codes arrive from suppliers in Excel files. An importer was developed: Excel is uploaded via a handler in the 1C-Bitrix admin area → parsed → codes are added to local_marking_codes with status in_stock.

During warehouse picking, a storekeeper scans the code on each item. A mobile application (React Native, WebView with 1C-Bitrix) sends the scan results to the server, which binds specific codes to order line items.

On dispatch — codes are automatically retired from circulation. On return — POST /api/v3/lk/documents/create with type RETURN, and the code reverts to in_stock status.

Metric Before After
Manual code retirement 1.5–2 hours/day Automatic
Retirement errors (wrong code) ~3%/month < 0.3%
Returns to Honest Sign Skipped Automatic on return processing

Code verification before sale

Before dispatch, the code status in Honest Sign is verified (to confirm it has not already been retired through another channel):

$codeInfo = $chestnyZnak->httpGet("/facade/identificationtools?uitCode={$code}");
if ($codeInfo['status'] !== 'IN_CIRCULATION') {
    throw new \Exception("Code {$code} is not in circulation: {$codeInfo['status']}");
}

Scope of work

  • Registration with Honest Sign, API connection, QES certificate
  • PHP client development: authentication, code retirement, returns
  • Labeling code storage table in 1C-Bitrix
  • Code import from suppliers
  • Warehouse inventory integration: code reservation on order
  • Automatic retirement on dispatch, reinstatement on order return
  • Monitoring: Honest Sign document statuses, retirement errors

Timeline: basic integration (sale retirement, returns) — 4–6 weeks. With code import, warehouse management, and mobile scanning — 10–16 weeks.