Интеграция 1С-Битрикс с системой Честный Знак
Честный Знак — система обязательной маркировки товаров. С 2020–2024 годов маркировка распространилась на обувь, одежду, молочную продукцию, табак, воду, парфюмерию, БАД, антисептики и ряд других категорий. Интернет-магазин, торгующий маркированными товарами, обязан при продаже выводить коды Data Matrix из оборота. Без интеграции с Честным Знаком — административные штрафы и блокировка.
Принцип работы маркировки в e-commerce
При получении товара на склад — коды маркировки принимаются в Честный Знак (ввод в оборот). При продаже — выводятся из оборота (признаётся факт продажи конечному потребителю). Вывод из оборота происходит через чек ОФД или напрямую через API Честного Знака.
Для интернет-магазина схема:
- Товар поступил на склад → сканирование кодов → ввод в оборот через API ЧЗ
- Заказ оформлен → при отгрузке/выдаче — формируется чек через ОФД с кодом маркировки → ОФД автоматически выводит код из оборота
Если ОФД не используется (самовывоз без чека через кассу, доставка курьером с электронным чеком) — прямой вывод через API Честного Знака.
API Честного Знака (ГИС МТ)
API доступен по адресу https://ismp.crpt.ru/api/v3/. Авторизация — через JWT-токен, получаемый с использованием КЭП:
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
{
// Шаг 1: получаем данные для подписи
$authData = $this->httpGet('/auth/cert/key');
$uuid = $authData['uuid'];
$data = $authData['data'];
// Шаг 2: подписываем данные КЭП
$signature = $this->signWithCert($data, $this->certSerial);
// Шаг 3: получаем токен
$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'];
}
}
Хранение кодов маркировки в Битрикс
Коды Data Matrix хранятся в кастомной таблице, связанной с позициями заказа:
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'), // ID товара в каталоге
new \Bitrix\Main\ORM\Fields\StringField('CODE'), // Data Matrix код
new \Bitrix\Main\ORM\Fields\StringField('STATUS'), // 'in_stock', 'in_order', 'sold'
new \Bitrix\Main\ORM\Fields\IntegerField('ORDER_ID'), // null пока не в заказе
new \Bitrix\Main\ORM\Fields\IntegerField('BASKET_ITEM_ID'),
new \Bitrix\Main\ORM\Fields\DatetimeField('WITHDRAWAL_DATE'),
];
}
}
При добавлении товара в заказ — резервируется конкретный код маркировки для данной позиции. При отмене заказа — код освобождается обратно в статус in_stock.
Вывод из оборота при отгрузке
// Обработчик события отгрузки заказа
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');
// Обновляем статус кодов
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,
]);
}
}
Кейс: магазин одежды с обязательной маркировкой
Магазин женской одежды, ~1 500 заказов/месяц. Товары — маркированные изделия лёгкой промышленности. Задача: при каждой отгрузке автоматически выводить коды из оборота, при возврате — возвращать в оборот.
Особенности реализации:
Коды маркировки поступают от поставщиков в Excel. Написан импортёр: загрузка Excel через обработчик в административном разделе Битрикс → парсинг → добавление кодов в local_marking_codes со статусом in_stock.
При комплектации заказа на складе — кладовщик сканирует коды каждого товара. Мобильное приложение (React Native, WebView с Битрикс) отправляет результат сканирования на сервер → привязывает конкретные коды к позициям заказа.
При отгрузке — автоматический вывод из оборота. При возврате — POST /api/v3/lk/documents/create с типом RETURN, код возвращается в статус in_stock.
| Показатель | До | После |
|---|---|---|
| Ручной вывод из оборота | 1.5–2 часа/день | Автоматически |
| Ошибки вывода (неверный код) | ~3%/мес | < 0.3% |
| Возвраты в Честный Знак | Пропускались | Автоматически при оформлении возврата |
Проверка кода перед продажей
Перед отгрузкой — проверка статуса кода в ЧЗ (не выведен ли уже из оборота другим путём):
$codeInfo = $chestnyZnak->httpGet("/facade/identificationtools?uitCode={$code}");
if ($codeInfo['status'] !== 'IN_CIRCULATION') {
throw new \Exception("Код {$code} не находится в обороте: {$codeInfo['status']}");
}
Состав работ
- Регистрация в Честном Знаке, подключение к API, сертификат КЭП
- Разработка PHP-клиента: аутентификация, вывод из оборота, возвраты
- Таблица хранения кодов маркировки в Битрикс
- Импорт кодов от поставщиков
- Интеграция со складским учётом: резервирование кодов при заказе
- Автовывод при отгрузке, возврат при возврате заказа
- Мониторинг: статусы документов ЧЗ, ошибки вывода
Сроки: базовая интеграция (вывод при продаже, возврат) — 4–6 недель. С импортом кодов, складским учётом, мобильным сканированием — 10–16 недель.







