Мини-приложение для заказа в двух мессенджерах
Проект показываем обезличенно: без названия, отрасли и ссылок
Заказчик продавал товар по каталогу, а заявки принимал в переписке: клиент присылал фотографию документа на изделие, менеджер вручную искал позиции и вручную заводил заказ в учётную систему. Мы собрали мини-приложение, которое живёт внутри двух мессенджеров одновременно и делает то же самое само: распознаёт документ, подбирает позиции, оформляет заказ и отдаёт его в CRM и в учётную систему.

Задача
- Подбор по фотографии документа занимал у менеджера минуты на каждую заявку, а пик приходился на часы, когда менеджеров меньше всего. Заявки жили в трёх мессенджерах и в голове у сотрудника, остатки сверялись руками, оплата собиралась переводами. Нужен был один вход, который работает круглосуточно и сам кладёт заказ туда, где он должен оказаться.
Что сделали
- Мини-приложение на одной кодовой базе для двух мессенджеров: общий фронтенд, разные слои авторизации и разные способы открытия
- Распознавание документа по фотографии с камеры: подготовка снимка, извлечение полей, оценка уверенности по каждому полю
- Подбор позиций по распознанным данным с ручным подтверждением там, где система не уверена
- Обмен с CRM: заявка создаётся сразу, с источником и историей обращения, и попадает в общую воронку
- Обмен с учётной системой: остатки и цены тянутся из неё, заказ уходит обратно, справочники сверяются по одному ключу
- Подключение онлайн-оплаты и рассрочки через сторонние сервисы, с раздельной обработкой подтверждений
- Работа в стране, где прямой доступ к API мессенджера с сервера закрыт: доставка обновлений через прокси и опрос вместо вебхуков
Результат
- Заказ оформляется целиком внутри мессенджера — без перехода на сайт и без установки приложения
- Заявка попадает в CRM в момент отправки, а не после того, как менеджер её перепишет
- Подбор по фотографии занимает у клиента секунды и не зависит от рабочего времени
- Одна кодовая база обслуживает обе площадки: правка интерфейса выкатывается сразу в оба мессенджера
Почему два мессенджера, а не один
Аудитория заказчика делилась между двумя площадками, и выбрать одну означало отрезать половину. Отдельная разработка под каждую удвоила бы и срок, и стоимость поддержки, поэтому мы развели проект на три слоя: общий интерфейс, общая бизнес-логика и тонкий слой платформы, где живут различия — способ авторизации, формат открытия приложения и правила отправки уведомлений.
Практический выигрыш проявился не на запуске, а через месяц. Любая правка витрины, каталога или сценария заказа делается один раз и выкатывается сразу в обе площадки, а платформенные различия остаются в изолированных файлах, которые почти не меняются.
Распознавание, которое не притворяется идеальным
Первая версия подбора по фотографии показывала хороший результат на аккуратных снимках и разваливалась на реальных: документ снимали вечером, под углом, через плёнку. Мы добавили подготовку изображения перед распознаванием — поиск документа в кадре, выравнивание перспективы, обрезку и вытягивание контраста, — и это дало больше прироста качества, чем любые настройки самой модели.
Второе решение было продуктовым, а не техническим. Система перестала притворяться, что уверена во всём: каждому полю приписывается оценка уверенности, уверенные подставляются молча, сомнительные подсвечиваются и требуют подтверждения одним касанием. Пользователь проверяет два-три поля вместо того, чтобы вводить десяток, и при этом видит, что именно система прочитала неуверенно.
Обмен с внешними системами и сбои
У каждой сущности в проекте один хозяин: цены и остатки живут в учётной системе, клиент и сделка — в CRM, платёж — на стороне провайдера. Мини-приложение не хранит собственных справочников, поэтому расхождений между двумя реальностями просто не возникает. Каждый обмен идёт с ключом идемпотентности: повтор с тем же ключом ничего не создаёт, и двойное нажатие кнопки не превращается в два заказа.
Отдельно проектировалось поведение при недоступности внешней системы. Заказ принимается всегда: он ставится в очередь, пользователь получает подтверждение, а обмен повторяется по нарастающей задержке. Если и это не помогло, обмен попадает на экран ручного разбора, где его повторяют кнопкой. Примерно четверть времени интеграции ушла именно на сценарии, где что-то пошло не так, и это нормальная пропорция.
Ограничение, которое всплыло на боевом контуре
На сервере в стране заказчика прямой доступ к API мессенджера оказался закрыт — выяснилось это при переносе на боевой контур, когда всё уже работало на тестовом. Архитектура выдержала: обмен с платформой был вынесен в отдельный слой, поэтому переключение на прокси и на опрос вместо вебхуков затронуло один модуль, а не весь проект.
Вывод, который мы теперь применяем по умолчанию: способ доставки обновлений от мессенджера закладывается сменным с самого начала. Поддерживать оба режима стоит несколько часов на старте и спасает недели переделки на финише.
