Про эталонный справочник, JWT-авторизацию, требования КИИ и почему 1С-Битрикс вместо Laravel
В 2022 году мы получили задачу: автоматизировать заказы запчастей для 40+ дилеров. Вызов был не в объёме данных (50,000 SKU), а в разнородности систем дилеров и требованиях безопасности КИИ.
Через 18 месяцев 65% заказов пошли через портал без участия операторов. REST API интегрирован с 28 дилерами (70% сети). Время оформления заказа сократилось с 45 минут до 7.
Под катом — архитектурные решения, почему эталонный справочник важнее REST API, и как обойти ограничения КИИ.
Техническое задание в двух абзацах
Задача: веб-портал для заказа запчастей с интеграцией в 1С дилеров.
Контекст: Сельхозпроизводитель из Ростова-на-Дону — группа из 13 предприятий на 11 производственных площадках в 5 странах. Продуктовая линейка: 150+ моделей и модификаций, 24 типа техники. Дилерская сеть: 40+ партнеров на территории РФ (по данным из ТЗ).
Целевая аудитория: две группы клиентов — небольшие сельхозкомпании (до 30 единиц техники) и крупные агрохолдинги (свыше 30 единиц техники).
Бизнес-проблемы из ТЗ:
Отсутствие веб-каталога запчастей
Нет удобного поиска для 50,000 SKU
Невозможнос��ь быстро сформировать заказ
Нет отслеживания статусов заказов
Ограничения КИИ: запрещены западные фреймворки, облачные сервисы за пределами РФ, npm-пакеты без аудита.
Требования: визуализация каталога, поиск по артикулу/модели/серийному номеру, REST API для real-time остатков, автоматическая передача заказов в 1С, личный кабинет для управления парком техники. Оформление заказа без регистрации (гостевой checkout).
Архитектура: шесть уровней интеграции
┌─────────────────────────────────────────────────────────┐ │ Уровень 1: Корпоративные системы завода │ │ ┌──────────┐ ┌──────────┐ │ │ │ SEARCH │ │ SAP CRM │ │ │ │(составы) │ │(дилеры) │ │ │ └────┬─────┘ └────┬─────┘ │ │ │ │ │ └──────┼─────────────┼────────────────────────────────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────────────────────┐ │ Уровень 2: Интеграционный мост │ │ ┌──────────────────────────────────────┐ │ │ │ PPM (сельхозпроизводитель) │ │ │ │ API Workbench (Docware) │ │ │ └──────────────────┬───────────────────┘ │ └────────────────────┼────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ Уровень 3: Электронный каталог │ │ ┌──────────────────────────────────────┐ │ │ │ PartsPublisher (Docware) │ │ │ │ БД запчастей + визуализация │ │ │ └──────────────────┬───────────────────┘ │ └────────────────────┼────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ Уровень 4: CMS портала │ │ ┌──────────────────────────────────────┐ │ │ │ 1С-Битрикс │ │ │ │ + Эталонный справочник запчастей │ │ │ └──────────────────┬───────────────────┘ │ └────────────────────┼────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ Уровень 5: REST API │ │ ┌──────────────────────────────────────┐ │ │ │ JWT auth + 5 методов │ │ │ └──────────────────┬───────────────────┘ │ └────────────────────┼────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ Уровень 6: Системы ди��еров │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 1С:УТ 11 │ │ 1С:ERP │ │ Custom │ │ │ │ (60%) │ │ (25%) │ │ (15%) │ │ │ └──────────┘ └──────────┘ └──────────┘ │ └─────────────────────────────────────────────────────────┘
Уровень 1-2: От завода к PartsPublisher
SEARCH — внутренняя система завода. Хранит составы изделий (какие детали в каких узлах), групповые замены, иллюстрации с хотспотами, привязку к серийным номерам. Выгружает файлы раз в сутки:
SOSTAV.txt — составы изделий. Структура: Module (модуль), Part (деталь), RU_number (российский номер), RU_name (название на русском), Quantity (количество), MU (единица измерения), Pos (позиция), STARTDATE/ENDDATE (даты начала/окончания использования), FE/BF (флаги), EN_number/EN_name (английские версии), плюс 46 полей для опций (Option1...Option46) для привязки к модификациям техники.
MATERIAL.txt — материалы и детали с атрибутами.
SUBS.txt — замены деталей (групповые, локальные, глобальные).
IMAGES.txt — список иллюстраций с хотспотами для визуализации узлов.
SERNUM.txt — серийные номера техники с привязкой к модификациям.
SAP CRM — данные о дилерах. Интеграция через SOAP Web Service (метод ZwsPartners). Возвращает структуру EtPartner с полями:
Partner (номер партнёра), Crdat (дата создания), Addrnumber (номер адреса), NameOrg1/NameOrg2 (названия организации), Country (код страны), Landx (название страны), Subject (регион), Region (область/край), City (город), PostlCod1 (индекс), Street (улица), HouseNo (номер дома), ClientTel (телефон), SmtpAddr (email), UriSrch (сайт), Zzzlongitude/Zzzlatitude (GPS-координаты склада).
GPS-координаты критичны для функции "определение ближайшего дилера по геопозиции клиента".
PPM — интеграционный мост от производителя. Забирает файлы из SEARCH и данные из SAP, трансформирует в формат PartsPublisher, вызывает API Workbench (библиотека Docware) для импорта. Автозапуск раз в сутки, есть ручной режим.
Уровень 3: PartsPublisher
PartsPublisher (Docware) — не просто БД, а специализированная система для автокаталогов. Умеет:
Работать с разными типами замен — групповые (деталь А → деталь Б для всех моделей), локальные (только для конкретной модификации), глобальные (на всю линейку), односторонние/двухсторонние.
Визуализировать узлы с хотспотами — клик на деталь на схеме → карточка детали с артикулом, названием, ценой, сроками доставки.
Фильтровать по серийным номерам — вводишь номер машины → система определяет модификацию → показывает только совместимые детали (критично для снижения ошибок подбора).
Функциональность из ТЗ: общий фильтр по узлам, поиск по названию узла, выбор версии узла (принадлежность к конкретной технике), масштабирование изображений, печать схемы узла, добавление в корзину прямо со схемы.
Это готовая система с логикой, которую иначе пришлось бы писать руками.
Уровень 4: 1С-Битрикс и эталонный справочник
Выбор CMS был ограничен требованиями КИИ. Западные фреймворки запрещены. Рассматривали российские решения: 1С-Битрикс, ModX, собственную разработку на чистом PHP.
Выбрали 1С-Битрикс по причинам:
Соответствие требованиям КИИ (российское ПО, сертификат ФСТЭК). Готовый REST API framework — не нужно писать с нуля. Документация на русском, большое комьюнити. Критично для дилеров — много 1С-программистов знают Битрикс.
Минусы есть — легаси в ядре, странные архитектурные решения, нет нормального DI. Но плюсы перевесили.
Эталонный справочник — ключевой элемент интеграции. У 40+ дилеров разная структура БД в 1С. Одна запчасть у всех записана по-разному. Нельзя заставить дилеров унифицировать базы — политически невозможно. Нельзя использовать AI/ML для сопоставления — 10-15% ошибок неприемлемы в B2B.
Решение: единая номенклатура в Битрикс с уникальными кодами rsm_id. Дилер один раз сопоставляет свои позиции с эталоном. При передаче остатков отправляет только rsm_id + quantity. Битрикс сопоставляет с эталоном и обновляет остаток. Если rsm_id нет в справочнике — игнорируется.
Сопоставление — разовая работа на 2-3 дня программиста 1С. Дальше всё автоматом.
Уровень 5-6: REST API и 1С дилеров
У дилеров три типа конфигураций: 1С:Управление торговлей 11 (60%), 1С:ERP 2.0 (25%), кастомные на базе 8.3 (15%). API должен работать со всеми.
Принцип — минимализм. Пять методов закрыли 95% задач.
REST API: пять методов
1. Авторизация JWT
POST /api/token/get/ Content-Type: application/json { "login": "dealer_krasnodar", "password": "secret" }
Ответ:
json
{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6ImFjY2VzcyJ9...", "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InJlZnJlc2gifQ..." }
access_token живёт 24 часа, refresh_token — 60 дней. Обновление через POST /api/token/refresh/ с refresh_token в заголовке.
2. Передача остатков
POST /api/remains/?store_id=23 Authorization: Bearer {access_token} Content-Type: application/json [ { "rsm_id": "101054915", "quantity": 100 }, { "rsm_id": "101054916", "quantity": 0 } ]
Критично: передаётся свободный остаток (физический минус резерв). Если остаток стал 0 — ноль тоже передать, иначе висит старое значение.
Лимиты из документации API:
Минимум: 1 запись за запрос (иначе ошибка "Too small request: min 1 record per request")
Максимум: 1000 записей за запрос (иначе "Too big request: max 1000 records per request")
store_id — обязательный параметр (без него ошибка "Необходимо явно указать ID склада")
Частота обновления: минимум раз в день, оптимально каждый час.
Формат ответа при успехе:
json
{ "result": "updated 1 records", "skipped": ["101054916"] }
Массив skipped содержит коды rsm_id, которые не были обновлены (нет в эталонном справочнике).
3. Получение заказов
GET /api/orders/?datetimeFrom=2023-06-01T09:12:33&skip=0&limit=100 Authorization: Bearer {access_token}
Параметры запроса (все опциональные):
datetimeFrom— дата начала выборки (формат: 2023-06-01T09:12:33)skip— количество заказов для пропуска (для пагинации, по умолчанию 0)limit— лимит заказов (по умолчанию 100, максимум 100)
Без параметров возвращает последние 100 заказов.
Структура ответа:
json
[ { "id": "1", "type": "CLIENT", "is_order": true, "is_bid": false, "is_paid": false, "items": [ { "rsm_id": "102897669", "quantity": 1, "price": 100000, "total_price": 100000, "status": "NEW", "quantity_from_home": 1, "quantity_from_other_dealer": 0, "target_dealer": null } ], "client_inn": "123456789200", "delivery_type": "DELIVERY", "delivery_address": "г Краснодар, ул Северная, д 125", "status": "N", "service_text": "Заявка на сервис", "total_price": 100000, "bill_requested": true, "specification_requested": true } ]
Важные поля:
type— тип заказа:CLIENT(от конечного клиента) илиDEALER(от другого дилера)is_order— полноценный заказ с оплатой (true) или заявка без оплаты (false)items.quantity_from_home— доступно на вашем складеitems.quantity_from_other_dealer— нужно заказать у другого дилераitems.target_dealer— у какого дилера заказано недостающее количествоЦены в копейках (100000 = 1000 рублей)
Статусы позиций в заказе:
NEW— ожидает обработкиRESERV— зарезервированTRANSIT— в транзитеDELIVERED— готов к выдачеREJECTED— отменёнISSUED— выдан
Статусы заказа:
N— в обработкеA— принятC— подтверждён (и далее по цепочке)
1С забирает заказы каждый час, создаёт документ "Заказ покупателя", резервирует товар.
4. Обновление статусов и данных заказа
POST /api/orders/ Authorization: Bearer {access_token} Content-Type: application/json [ { "id": "1", "is_paid": true, "items": [ { "rsm_id": "101400963", "quantity": 7, "price": 100000, "status": "RESERV" } ], "delivery_type": "DELIVERY", "delivery_address": "г Краснодар, ул Северная, д 321", "service_text": "Комментарий дилера" } ]
Можно изменить:
Статусы позиций (
items[].status)Цены (
items[].price)Количество (
items[].quantity)Флаг оплаты (
is_paid)Адрес доставки (
delivery_address)Комментарий (
service_text)
Нельзя изменить:
id(но нужно передавать для идентификации заказа)type(CLIENT/DEALER)client_inntotal_price(считается автоматически)
Общий статус заказа выставляется автоматически на основе статусов всех позиций.
Ответ при успехе:
json
{ "result": "order updated" }
5. Передача документов
Загрузка счетов:
POST /api/bills/ Authorization: Bearer {access_token} Content-Type: multipart/form-data id: 125 file_1: test.pdf file_2: sample.pdf
Загрузка спецификаций:
POST /api/specifications/ Authorization: Bearer {access_token} Content-Type: multipart/form-data id: 125 file_1: specification.pdf
Можно загрузить несколько файлов сразу. Старые файлы перезаписываются.
Ответ: {"result": "Сохранено файлов: 2"}
Получение списка документов: GET /api/bills/?id=125
Клиент видит документы только после запроса (флаги bill_requested/specification_requested).
Технические решения
Почему не использовали стандартные библиотеки JWT
В 1С-Битрикс нет встроенной поддержки JWT. Рассматривали варианты:
Вариант 1: Библиотека firebase/php-jwt через Composer. Проблема — внешняя зависимость, нужен аудит по КИИ.
Вариант 2: Собственная реализация JWT. Плюсы — полный контроль, нет зависимостей. Минусы — нужно тщательно тестировать криптографию.
Выбрали вариант 2. Реализовали базовый JWT (HS256) без лишних фич. Прошли аудит безопасности.
Обработка ошибок в API
Примеры реальных ошибок из документации:
Неверный токен:
json
{ "error": "Invalid JWT Token" }
Слишком мало записей:
json
{ "error": "Too small request: min 1 record per request" }
Слишком много записей:
json
{ "error": "Too big request: max 1000 records per request" }
Не указан store_id:
json
{ "error": "Необходимо явно указать ID склада (store_id)" }
Все ошибки возвращаются в JSON с полем error. Коды ошибок документированы в 35-страничном руководстве для программистов 1С.
Сложности интеграции с 1С
Проблема кодировок
1С работает в Windows-1251. API ждёт UTF-8. Первые выгрузки пришли с кракозябрами.
Решение: проверка кодировки в API + инструкция для 1С-программистов добавить Content-Type: application/json; charset=utf-8 в запрос.
Проблема с резервом
Первая версия: дилеры передавали физические остатки. Проблема: клиент заказал → резерв в 1С → на сайте остаток не изменился → двойное резервирование.
Решение: передавать свободный остаток (физический минус резерв).
Проблема с нулевыми остатками
Дилер настроил выгрузку: передавать только изменения. Если остаток стал 0, он не попадает в выгрузку (значение пустое). На сайте висит старый остаток.
Решение: требование в API передавать изменения даже при quantity = 0.
Мониторинг активности
Интеграция настроена, но остатки не обновляются. Причина: программист забыл включить автозапуск в 1С.
Решение: если дилер не передавал остатки 3 дня — автописьмо на email. Мониторинг активности API обязателен.
Результаты
Метрики внедрения
Разработка велась по трёхверсионной модели из ТЗ: 18 месяцев (Q3 2022 — Q4 2023).
Версия 1 (Q3-Q4 2022): MVP — каталог, гостевой checkout, email дилерам
Версия 2 (Q1-Q2 2023): REST API, личные кабинеты, статусы
Версия 3 (Q3-Q4 2023): Полная автоматизация — CRM интеграция, документы через API
Подключено дилеров: 28 из 40+ (70%) через API, остальные через email.
Качественные изменения
Для клиентов:
Самостоятельное оформление заказов через веб-интерфейс
Отслеживание статусов в реальном времени
Управление парком техники в личном кабинете
Проверка совместимости по серийному номеру (снижение ошибок)
Для дилеров:
Автоматическая передача заказов в 1С без ручного ввода
Real-time актуализация остатков (вместо 1-2 недель)
Снижение нагрузки на операторов call-центра
Централизованная работа с документами через API
Для завода:
Централизованная аналитика по всей дилерской сети
Контроль качества обслуживания клиентов
Унификация процессов заказа запчастей
Выводы
Требования КИИ — это не ограничение. Нельзя Laravel — берём Битрикс. Нельзя npm-пакеты — пишем свою реализацию JWT. Ограничения заставляют искать решения, иногда более простые.
Данные важнее технологий. API спроектировали за 2 недели. Эталонный справочник делали 3 месяца. Без справочника интеграция не сработала бы. В B2B 80% проблем — это структура данных.
Минимализм в API упрощает внедрение. Пять методов вместо 15. Остальное — потом или вообще не нужно. Чем проще API, тем быстрее дилеры внедряют.
Документация критична. 35-страничное руководство с примерами кода. Программисты дилеров внедряют за 3-5 дней без нашей помощи. Хорошая документация = масштабируемость.
Мониторинг обязателен. Нельзя полагаться, что всё настроили правильно. Автопроверка активности API — must have в B2B.
Теги: #api #restapi #integration #1c #bitrix #b2b #jwt #ecommerce
Автор: Олег Линьков, CEO & Tech Lead Webformula
Мы переводим агромаркетинг с «интуиции» на рельсы Data-Driven & AI. Разрабатываем и внедряем федеративные архитектуры данных и методологию DSAC (Dynamic Seasonally-Adaptive Content).
