← Статьи

Как проверить код «Честного знака»: три уровня проверки

«Проверить код» означает три разные вещи: что код читается, что его содержимое собрано по правилам и что система маркировки его знает. Покупателю хватает приложения; производителю нужны все три уровня, и второй — прямо на линии, до того как коробка уедет на склад.

Уровень 1. Проверка покупателя

Наведите камеру телефона на код в приложении «Честный ЗНАК». Приложение покажет товар, производителя и статус кода, а если кода нет в системе или товар уже выбыл из оборота — предупредит. Обычный сканер QR-кодов тут не поможет: он покажет строку символов, но не скажет, зарегистрирован ли код.

Для производства этот способ годится для выборочной проверки первой партии, но не для потока: тысячи упаковок в час телефоном не проверить.

Уровень 2. Проверка структуры — на линии

Код считан — теперь надо убедиться, что внутри именно то, что требует оператор. Это делается локально, без сети, за микросекунды, и ловит большую часть ошибок печати и настройки принтера. Проверяйте пять вещей:

  1. Символика GS1. Код должен быть GS1 DataMatrix, то есть начинаться с FNC1. Обычный DataMatrix с тем же текстом — брак, даже если строка совпадает символ в символ.
  2. Набор и порядок идентификаторов применения. Для лекарств — 01, 21, 91, 92; для молока — 01, 21, 93 и при необходимости 3103. Подробно — в статье про Application Identifiers.
  3. Длины полей. GTIN — ровно 14 цифр. Серийный номер зависит от товарной группы: 13 символов у лекарств и БАД, 6 — у молочной продукции и косметики. Ключ проверки (91) — 4 символа, код проверки (92) — 44, короткий код проверки (93) — 4.
  4. Разделители GS. После серийного номера и после ключа 91 должен стоять символ с кодом 29. Без него касса или учётная система не разберёт, где кончается серийный номер — самая частая ошибка, ей посвящена отдельная статья.
  5. Контрольная цифра GTIN. Последняя цифра GTIN вычисляется из первых 13: цифры справа налево умножаются поочередно на 3 и 1, сумма дополняется до кратного 10. Несовпадение означает опечатку в данных задания на печать.

Минимальный разбор на Python — строка приходит от сканера или декодера, GS — это \x1d:

GS = "\x1d"
FIXED = {"01": 14, "17": 6, "91": 4, "93": 4, "3103": 6}
KNOWN = ("3103", "01", "17", "21", "91", "92", "93")

def gtin_ok(gtin: str) -> bool:
    if len(gtin) != 14 or not gtin.isdigit():
        return False
    s = sum(int(d) * (3 if i % 2 == 0 else 1)
            for i, d in enumerate(reversed(gtin[:-1])))
    return (10 - s % 10) % 10 == int(gtin[-1])

def parse(code: str) -> dict:
    code = code.lstrip(GS)   # ведущий FNC1 иногда приходит как GS
    out = {}
    while code:
        ai = next((a for a in KNOWN if code.startswith(a)), None)
        if ai is None:
            raise ValueError(f"неизвестный AI: {code[:4]!r}")
        code = code[len(ai):]
        if ai in FIXED:
            n = FIXED[ai]
            out[ai], code = code[:n], code[n:]
        else:                # переменная длина — до GS или до конца
            out[ai], _, code = code.partition(GS)
        code = code.lstrip(GS)
    return out

c = "0104601234567893" "215Ab3dE7fGh9kL" + GS + "93Xy1Z"
p = parse(c)
print(p, gtin_ok(p["01"]))
# {'01': '04601234567893', '21': '5Ab3dE7fGh9kL', '93': 'Xy1Z'} True

Дальше сравните длины полей с правилами своей товарной группы и сверьте серийный номер с списком кодов, полученных из системы маркировки для этого задания. Так ловятся повторная печать одного кода и коды чужого заказа.

Уровень 3. Проверка статуса в системе маркировки

Структурно верный код ещё не означает, что его можно продать: его должны ввести в оборот, и он не должен быть уже продан или списан. Это знает только система маркировки, поэтому проверка статуса всегда идёт через оператора: в личном кабинете участника оборота, через API для учётных систем или на кассе при продаже.

Здесь важна разница между длинным и коротким кодом. Код с полями 91 и 92 касса может проверить офлайн, а код с полем 93 — только онлайн, запросом к серверу оператора (состав кода, БАД). На линии проверку статуса обычно делают пакетно — при вводе в оборот за смену, а не на каждой коробке.

Частые ошибки

СимптомПричинаГде искать
Касса не принимает код, телефон читаетНет GS после серийного номера или нет ведущего FNC1Шаблон принтера, драйвер
Код читается, но «не найден»Код не введён в оборот или напечатан из чужого заказаУчётная система, отчёт о нанесении
Один код на двух упаковкахПовторная печать после сбоя или остановки линииКонтроль дублей на выходе принтера
Неверная контрольная цифра GTINОпечатка в данных заданияСправочник товаров
Код читается через разНизкое качество печати или недостаточное разрешение камерыСм. статью про разрешение камеры

Попробовать

Проверить, как читается ваш код с фотографии, можно в онлайн-сканере на libscanner.com. Библиотеки чтения и генерации DataMatrix для встраивания в линию — на GitHub.

«Честный знак» — товарный знак ООО «Оператор-ЦРПТ», «GS1» — GS1 AISBL; продукт не связан с их владельцами и ими не сертифицирован.