BR 2.4 (draft) — PayKeeper: must-have для запуска MVP

Это research / memo для встречи с PayKeeper

Цель — выписать только то, без чего MVP не запустить. Отделить настоящие блокеры от удобств которые мы можем обойти со своей стороны.


1. Контекст

Готовим интеграцию ERP НИРБИ × PayKeeper. Схема b2b (backend-to-backend): наше ПО → API PayKeeper → их касса 3-в-1. Мы — бэк-офис (каталог, склад, сотрудники, заказы). Они — приём платежа, фискализация, кассовое железо.

На встрече со Ренатом (10.04.2026) обсудили разрывы. На слайде 7 презентации собран первичный список. Эта BR — уточнённая версия списка после глубокого ресёрча OpenAPI-спек PayKeeper (_assets/paykeeper/) и сверки с gap-analysis.md.

Главный вывод: большинство каталожных проблем (модификаторы, иерархия, цены по ТТ, стоп-листы) — обходимы на нашей стороне, если mPOS работает как «тонкий терминал» и всё меню/цены приходят в deep-link’е. Настоящие блокеры — вокруг cross-device flow (tablet→terminal), webhook’ов, reconciliation и смен ФН.


2. Hard blockers — без этого не запустимся

Это пункты, которые PayKeeper обязан реализовать до запуска MVP. Обход со стороны НИРБИ невозможен или недопустим (compliance, реальный риск простоя, архитектурная несовместимость).

⛔ 2.1. Cross-device push: внешний планшет → терминал PayKeeper

Контекст: на MVP мы отказываемся от собственного POS-софта и используем готовую кассу PayKeeper 3-в-1 как место где проводится оплата. При этом у нас на прилавке/у официанта стоит отдельный планшет — просто frontend для работы с меню/заказами/клиентами (никаких платежей, никакого PayKeeper-SDK). Заказ собирается на планшете, потом его нужно передать на терминал PayKeeper — кассир там видит готовый заказ, нажимает «Принять оплату», клиент платит.


Что известно из публичных OpenAPI-спек (старый вывод)

Есть только deep-link-модель paykeeper://mobile.app/invoice/ — работает исключительно на одном устройстве (наше приложение и mPOS-app должны быть на одном Android-планшете).

Проверено по всем 10 возможным механизмам — ничего не найдено:

  • ❌ Endpoint для push счёта на конкретный terminal_id (POST /terminals/{id}/invoice)
  • ❌ Очередь «ожидающих оплаты» на экране mPOS
  • ❌ Push-уведомления на терминал (FCM/APNS/свой канал)
  • ❌ QR-сканер на терминале, понимающий deep-link’и
  • ❌ Web-checkout страница (как YooKassa)
  • ❌ Локальный API на самом mPOS-устройстве
  • ❌ WebSocket / long-polling mPOS’а к серверу
  • ❌ ECR/локальный протокол (БП-«планшет»)
  • ❌ SDK / plug-in механизм для их app
  • ❌ Сущность «заказ» в их API вообще

Что известно из бэклога PayKeeper (прислал Ренат, файл доработки кассы 3 в 1.xlsx)

В бэклоге помечены ✓ (реализовано) пункты, которые прямо противоречат выводу выше:

Строка бэклогаФормулировкаЧто подсказывает
58«Подключение сайта или мобильного приложения» ✓Внешняя система (сайт/app) умеет работать с кассой
59«Подключение iiko» ✓iiko — отдельный POS-софт — подключён к PayKeeper
60«Подключение Yclients» ✓Ещё одна внешняя CRM подключается
61«Подключение МойСклад» ✓Внешний учётный сервис
62«Подключение Битрикс24» ✓Внешняя CRM
63«Фискализация чеков по оплатам на сайте» ✓Оплаты с сайта фискализируются через PayKeeper
64«Оплата заказов с сайта или внешней CRM на кассе» ✓Внешний источник → касса — это прямо наш сценарий
83«Создание заказов и отправка на оплату на кассу» ✓ (раздел «Мобильное приложение PayKeeper»)Их мобильное приложение создаёт заказы и отправляет на кассу

Плюс цитата из vision-pos-platform.md:

«Paykeeper — ровно то же, чем сейчас являются Ingenico или АТОЛ Ф для iiko: умная железка без своего интеллекта»

Сама эта аналогия намекает на ECR-стиль интеграции (iikoFront → Ingenico по USB/Ethernet посылает команду «оплатить N₽»). Если так — у PayKeeper должен быть аналог такого интерфейса.


Три возможных сценария как это устроено

СценарийОписаниеПодходит нам?
А. Same-deviceiiko-приложение ставится на кассу PayKeeper 3-в-1 как сторонний app, использует внутренний deep-link paykeeper://mobile.app/invoice/. Два приложения на одном устройстве.❌ Нет — у нас планшет отдельный
Б. ECR/cross-device APIPayKeeper-касса поддерживает режим «сторонний POS» — слушает команды по локальной сети (или через backend-API) от внешней системы. Именно так iiko работает с Ingenico/АТОЛ.Да — идеально нам подходит, просим документацию
В. Online-оплата (remote fiscalization)«Оплата с сайта» — это когда клиент платит на веб-странице, PayKeeper фискализирует у себя в облаке, выдаёт электронный чек. Физического терминала в процессе нет.⚠ Частично — подходит только для online-заказов (доставка/самовывоз с предоплатой), не для работы за прилавком

По публичным документам ECR / serial / WebSocket / local APIне упоминается. Это может значить:

  • Их нет (тогда iiko = Сценарий А или В)
  • Они есть, но оформлены отдельным «интеграционным договором» вне публичного API-пакета (как часто бывает для премиум-партнёров)

Диагностические вопросы на встречу с Ренатом (приоритет)

Эти 5 вопросов должны окончательно определить какой из сценариев работает:

  1. «iiko.Waiter или iiko.Kiosk устанавливается на вашу кассу 3-в-1, или это отдельное устройство iiko подключается к вашей кассе через сеть/кабель?» → отличает Сценарий А от Б
  2. «Какой конкретно протокол/API используется при подключении iiko? Это deep-link внутри одного Android’а, ECR по USB/Ethernet, или REST API на их backend?» → получаем конкретику
  3. «Строка 64 бэклога “Оплата заказов с сайта или внешней CRM на кассе” — это про оплату на сайте (клиент платит онлайн), или физическая касса принимает заказы от внешней CRM?» → отличает Сценарий В от Б
  4. «Если бы мы хотели подключить НАШ POS-софт аналогично iiko — по какой документации это делать? Есть ли открытая инструкция, или это индивидуальная интеграция по договору?» → прямой вопрос на применимость
  5. «Поддерживает ли ваша касса 3-в-1 ECR-интерфейс (как у Ingenico/АТОЛ) для сторонних POS-систем?» → если да, это готовое решение

Что нужно от PayKeeper (если окажется Сценарий А или «ничего нет»)

Если после встречи станет ясно что cross-device push действительно нужно разрабатывать — запрашиваем:

  1. POST /api/v1/invoices/push — наш backend пушит готовый счёт с указанием terminal_id:
    {
      "terminal_id": "...",
      "cart": [...],
      "pay_amount": 550,
      "external_order_id": "nirbi-4281",
      "callback_url": "https://..."
    }
  2. UI на терминале — экран «ожидают оплаты», где кассир видит поступившие счета и нажимает «Принять оплату»
  3. Push-уведомление на терминал (FCM / long-polling / WebSocket)
  4. Lifecycle webhook’иinvoice.delivered / accepted / expired / rejected

Обход (если ни ECR ни push недоступны)

  • Single-device (наше app на тех же кассах PayKeeper) — теряем разделение ролей
  • Ручной ввод суммы на терминале — нарушает 54-ФЗ (позиции чека должны быть)
  • Mock-товары в IMS-каталоге под каждый заказ — тоже нарушает 54-ФЗ

Все обходы нарушают либо UX, либо compliance. Работающего в рамках текущего PayKeeper пути (по публичным спекам) — нет.


⛔ 2.2. Webhook на возврат / отмену / чек коррекции

🟡 По бэклогу PayKeeper — частично покрыто (UI-уровень)

В бэклоге помечены ✓:

  • «Возвраты из ЛК», «Чеки коррекции из ЛК»
  • «Автоматическая массовая коррекция»

Но это UI-операции в ЛК. Нужно уточнить: есть ли webhook/callback когда оператор/кассир провёл возврат. Если нет — сохраняется блокер.

Что есть сейчас: только webhook «успешная оплата» (POST /{path_success}).

Что нужно добавить:

  • refund_success — возврат проведён (с указанием amount, items, фискальных реквизитов)
  • refund_failed — возврат не удался
  • payment_cancelled — клиент закрыл экран оплаты, не оплатив
  • correction — выпущен чек коррекции (по инициативе ФНС или кассира)

Почему блокер: без этих webhook’ов мы узнаём о возвратах только вручную (CSV-экспорт из ЛК). Учёт в Order Service расходится с реальностью. Бухгалтерия не может свести день.

Обход: только daily reconciliation — не real-time, не годится для MVP.


⛔ 2.3. API списка платежей (reconciliation)

🟡 По бэклогу PayKeeper — скорее всего уже есть

В бэклоге помечены ✓:

  • «Realtime данные об операциях оплаты и чеков»
  • «Экспорт операций и чеков»
  • «Выгрузка в Excel»

Уточнить: «Realtime данные» — это публичный API для партнёров? Если да — блокер снимается.

Что нужно: GET /api/payments?from={ts}&to={ts}&status=success + filter по mpos_terminal_id.

Почему блокер: это fallback когда webhook потерялся. Network outage, рестарт нашего сервиса в часы работы — сейчас нечем проверить «а пришёл ли платёж». Текущий единственный способ — вручную выгружать CSV.

Обход: нет. Без этого API мы всегда не уверены в полноте данных.


⛔ 2.4. Фискальные реквизиты в webhook

⚠ По бэклогу PayKeeper — фискализация есть, состав payload webhook'а не ясен

В бэклоге помечены ✓:

  • «Чеки окончательного расчёта»
  • «Фискализация чеков по оплатам на сайте»

Фискализация как процесс работает. Вопрос: отдаются ли ФН/ФД/ФП в текущем payload webhook’а? Нужно уточнить — возможно поля уже есть, просто не в публичной документации.

Что есть сейчас: в webhook приходит payment_id + fop_receipt_key (ссылка на чек).

Что нужно добавить в payload:

  • fn_number — фискальный накопитель
  • fd_number — фискальный документ (номер)
  • fp_sign — фискальный признак
  • shift_number — номер смены
  • receipt_number_in_shift — порядковый номер чека в смене

Почему блокер: без этих полей наш журнал транзакций не матчится с ОФД. Бухгалтерия не может проверить что выручка сходится. В случае налоговой проверки — нечем показать «этот чек в нашей системе — вот этот ФД у ФНС».

Обход: теоретически можно загружать чек по fop_receipt_key и парсить, но это нестабильно и нелегально.


⛔ 2.5. API смен ФН

⚠ По бэклогу PayKeeper — отчёты есть, API программного доступа не вижу

В бэклоге помечены ✓:

  • «Х- Z- отчёты», «Сверка итогов»
  • «Дистанционная настройка»

Но это всё на уровне UI (касса + ЛК). Программный API для получения статуса смены + webhook’ов не видно. Блокер скорее всего сохраняется — уточнить у Рената.

Что есть сейчас: нет документированного API для смен.

Что нужно:

  • GET /api/mpos/shift/{terminal_id} — статус смены + сколько осталось до 24h блокировки ФН
  • POST /api/mpos/shift/close — программное закрытие смены
  • Webhook shift_expiring — предупреждение за 1ч до 24h
  • Webhook shift_opened / shift_closed — с Z-отчётом в payload

Почему блокер: ФН автоматически блокирует кассу через 24h без закрытия смены. Без API смен мы узнаём об этом когда касса уже упала в часы пик. Это прямой риск потери выручки и клиентов.

Обход: нет. Мониторить вручную через ЛК — не масштабируется.


⛔ 2.6. Обратная синхронизация каталога (PayKeeper → ERP)

Контекст: каталог товаров в PayKeeper — редактируемый. Владелец мерчанта или администратор могут через ЛК:

  • добавлять новые товары
  • менять цены
  • редактировать категории (теги)
  • массово импортировать из внешних систем (1С, Yclients, МойСклад, Битрикс24 — все эти коннекторы у PayKeeper есть)

Что нам сейчас приходит о таких изменениях: ничего. Webhook’ов нет, timestamp’ов updated_at на товарах нет, эндпоинта GET /products?modified_since=... нет. Про действия в ЛК мы узнаём только если сами полезем смотреть.

Почему блокер:

  • Если владелец в ЛК поменяет цену с 300 на 350 — наш ERP не узнает, при следующем нашем push’е каталога мы его правку перезатрём
  • Если кто-то залил в PayKeeper товары через 1С-коннектор — в нашем ERP их нет, а в чеке они появятся → расхождение отчётности
  • Бухгалтерия видит что на кассе продали «Торт» за 450₽, а в нашем каталоге такого товара нет — компланс-проблема

Что нужно от PayKeeper:

  1. Webhook product.changed / category.changed с payload { event, product_id, updated_fields, timestamp, changed_by_user }
  2. ИЛИ GET /products?modified_since={ISO} — для periodic polling
  3. ИЛИ механизм «catalog lock» — флаг в ЛК или API POST /catalog/lock который делает каталог read-only для UI, только API-запись разрешена

Обход на нашей стороне:

  • Контрактно запретить правки в ЛК PayKeeper (SLA с франшизами)
  • Nightly reconciliation: GET /products/ (весь каталог) + diff с нашим + алерт
  • Минусы обхода: ручная работа + лаг до суток + не решает проблему перезатирания правок

⛔ 2.7. Автоматизация онбординга ЛК (новая точка)

Контекст: когда мы регистрируем новую ТТ у PayKeeper (POST /client/add), сразу ЛК мерчанта не готов. Он создаётся в фоне — PayKeeper провижинит отдельный хост (типа myshop.server.paykeeper.ru), настраивает ОФД, отправляет железку-терминал. Через какое-то время ЛК активируется и мерчант получает доступ.

Три ручных шага в текущем flow:

  1. Нет webhook’а «ЛК готов» — узнать готовность можно только polling’ом GET /api/requests каждые N секунд. Неудобно, но работает.

  2. Webhook URL прописывается вручную — чтобы к нам приходили webhook’и об оплатах, мерчант должен руками открыть ЛК → Настройки → вбить наш callback URL. API чтобы сделать это программно — нет. Если мерчант забыл — мы не получаем ни одного webhook’а об оплате, хотя касса работает.

  3. HMAC-secret копируется вручную — PayKeeper генерирует секретное слово для подписи webhook’ов у себя, показывает мерчанту в ЛК. Чтобы проверять подпись — мерчант должен скопировать secret из ЛК и вставить в нашу админку. API для программного получения секрета — нет.

Почему блокер: при массовом онбординге (подключаем 20-30 ТТ подряд для сети франшизы) каждая ТТ — минимум 2 ручных шага от человека. Легко забыть. Забыли — касса вроде работает, а у нас в ERP ни одного платежа.

Что нужно от PayKeeper:

  1. Расширить POST /client/add чтобы передавать webhook_url + external_id:
    {
      "legal_name": "...",
      "webhook_url": "https://nirbi.ru/webhooks/paykeeper",
      "external_id": "store_uuid"
    }
    → Response: {
      "paykeeper_id": "...",
      "webhook_secret": "auto-generated-value",
      "webhook_url_set": true
    }
  2. Webhook lk.created или onboarding.completed — когда ЛК готов: { paykeeper_id, hostname, created_at }. Избавляет нас от polling.
  3. GET /api/secret (или similar) — программное получение webhook-секрета на случай rotation или повторного чтения.

Обход на нашей стороне (для MVP без доработок PayKeeper):

  • В админке НИРБИ пошаговая инструкция для оператора франшизы после создания ТТ:
    • Шаг 1: «Ждём готовности ЛК» (спиннер + polling)
    • Шаг 2: «Откройте ЛК, пропишите URL: [copyable block]»
    • Шаг 3: «Скопируйте secret из ЛК, вставьте сюда: [input]»
  • Проверка: smoke-транзакция сразу после настройки (если не пришёл webhook за 30с — блок с инструкцией что пошло не так)
  • Мониторинг: «По этой ТТ нет webhook’ов 24ч» → алерт

3. Workaroundable — обходимо, терпим

Эти пункты мы закрываем на своей стороне. Неидеально, но для MVP — ок.

⚠ 3.1. Модификаторы товаров

Их ограничение: IMS-каталог плоский, модификаторов нет.

Наш обход: всё меню и финальный состав заказа собирается в ERP. В deep-link в mPOS уходит уже собранная позиция — «Капучино M + сироп карамель» как один SKU в cart. mPOS не видит модификаторов, он получает готовый item + сумму.

Цена: mPOS нельзя использовать как standalone кассу. Кассир всегда работает в нашем приложении сначала, потом deep-link в mPOS для оплаты.

Принятое ограничение: standalone mPOS не поддерживается в MVP. Явно документируем.


⚠ 3.2. Иерархия категорий

Их ограничение: плоские теги без parent_id.

Наш обход: в POST /products/import передаём путь как строку: "Напитки / Кофе / Эспрессо". Некрасиво, но читаемо в ЛК PayKeeper если кто-то туда полезет.

Цена: визуально уродливо, но на оплату не влияет.


⚠ 3.3. Цены по ТТ (прейскуранты)

Их ограничение: одна цена на товар per ТСП.

Наш обход: при отправке в deep-link передаём конкретную цену из нашего прейскуранта. mPOS эту цену и использует, не заглядывая в свой каталог. То же что у iiko.

Цена: IMS-каталог в ЛК PayKeeper содержит «номинальную» цену, не отражающую реальность. Но для аналитики ЛК это не критично.


⚠ 3.4. Стоп-листы по ТТ

Их ограничение: только глобальный is_visible.

Наш обход: фильтрация идёт в нашем POS до того, как кассир увидит меню. В deep-link уходят только доступные позиции.

Цена: если кассир попытается продать позицию «в обход» ERP — она ему недоступна (потому что в нашем приложении её нет).


⚠ 3.5. Роли кассиров (плоские флаги)

Их ограничение: admin / refund_allow / view_only_owned_payments — 3-4 boolean-флага.

Наш обход: маппим наши роли в флаги. customers.create_quickadmin=false, refund_allow=false. Наш владелец франшизы → admin=true, refund_allow=true.

Цена: нельзя сделать роль «может возврат до 1000₽ — да, больше — эскалация». Для MVP ок.


⚠ 3.6. Error details в bulk import

Их ограничение: POST /products/import возвращает только счётчики успех/ошибка, без списка failed items.

Наш обход: импортируем мелкими батчами (по 50 товаров), ошибки ловим по rerun’у.


⚠ 3.7. Привязка terminal_id → store_id

Их ограничение: в webhook приходит их mpos_merchant_id + mpos_terminal_id, но не наш store_id.

Наш обход: при онбординге новой ТТ через Partner API (POST /client/addPOST /device/installGET /device/status) сохраняем соответствие ID PayKeeper ↔ наш store_id в таблице store_paykeeper_mapping (Store Service). В webhook-handler’е — lookup по (merchant_id, terminal_id)store_id.

Цена: +1 таблица + индекс (paykeeper_merchant_id, paykeeper_terminal_id) + логика в онбординг-флоу регистрации ТТ.

Что остаётся уточнить у PayKeeper (не запрос на разработку, а вопросы):

  1. Стабильность ID. Меняется ли mpos_terminal_id при замене/ремонте железа? Или он логический и остаётся прежним?
  2. Связь paykeeper_id (из Partner API) ↔ mpos_merchant_id (из webhook). Это один и тот же ID или разные сущности? Если разные — нужен endpoint «список merchant’ов для client’а».

4. Out of scope для MVP

Явно не делаем сейчас:

  • Standalone mPOS-режим — касса без нашего приложения. Решение: «не поддерживаем». Cashier всегда через ERP → deep-link.
  • API выплат самозанятым (api-vyplat.yaml) — есть у PayKeeper, но не нужен в фазе 1.
  • Тикет-система поддержки (support-api.yaml) — можно в фазу 2, пока звонки/мессенджер.
  • Multi-FN per store (несколько касс на одну ТТ) — предполагаем 1 ФН = 1 ТТ. Если у них можно > 1 — уточняем, но сейчас не проектируем.
  • X-отчёты в API — в MVP только Z (по факту закрытия смены). X в ЛК вручную.
  • Rate limits — не документированы, но для MVP нагрузка небольшая, не уперёмся.

5. Сверка со слайдом 7 презентации

Слайд 7ПриоритетУточнение после ресёрча
Модификаторы товаровP0⚠ Обходимо — deep-link с финальным cart (если касса одна с нашим приложением); без обхода если планшет отдельный — см. п.2.1
Иерархия категорийP0⚠ Обходимо — flatten-string в path
Цены по ТТP0⚠ Обходимо — цена приходит в deep-link
Стоп-листы по ТТP0⚠ Обходимо — фильтр в нашем POS
Webhook возвратов/коррекцийP0⛔ Hard blocker (п.2.2)
API списка платежейP0⛔ Hard blocker (п.2.3)
Роли кассиров + привязка к терминаламP1→ ⚠ Обходимо (роли) + ⚠ mapping-таблица у нас (§3.7)
Смены ФНP1⛔ Hard blocker (п.2.5) — повышаем до P0
Фискальный набор в webhookP1⛔ Hard blocker (п.2.4) — повышаем до P0
GET каталога из PayKeeperP1⛔ Hard blocker (п.2.6) — повышено до P0: обратная синхронизация нужна т.к. ЛК редактируемый

Изменения vs слайд 7:

  • Добавлен блокер 2.1 — cross-device push (отдельный планшет → терминал PayKeeper). На слайде 7 не было, всплыло при обсуждении архитектуры MVP.
  • Добавлен блокер 2.6 — обратная синхронизация каталога (webhook/polling на изменения в ЛК). На слайде 7 было как P1 «GET каталога», повышено до P0.
  • Добавлен блокер 2.7 — автоматизация онбординга ЛК (webhook URL вручную, secret copy-paste). На слайде 7 не было, всплыло при разборе lifecycle.
  • Каталожные гэпы понижены с P0 до ⚠ workaroundable (при условии что касса и наш tablet — одно устройство; если отдельные — смотри п.2.1)
  • Смены ФН и фиск-поля повышены с P1 до ⛔ hard blocker (прямой риск простоя и compliance)
  • Привязка terminal→store — решается нашей mapping-таблицей (§3.7), не требует разработки на стороне PayKeeper. Только 2 уточнения по стабильности ID.
  • Sandbox — убран из hard-блокеров (принято что тестируем на dev-окружении PayKeeper по договорённости, без compliance-блокеров).

6. Что сказать PayKeeper на следующей встрече

Уточнения по бэклогу (первым делом — может снять половину блокеров):

  1. Как работает «Оплата заказов с сайта или внешней CRM на кассе» / «Создание заказов и отправка на оплату на кассу» / «Подключение iiko» (строки 64, 83, 59 бэклога)? Какой API за этим стоит? Можем ли мы использовать тот же механизм для нашего сценария «планшет → терминал» (блокер 2.1)?
  2. «Realtime данные об операциях оплаты и чеков» (строка 46) — это публичный API для партнёров? Есть ли документация? Покрывает ли наш кейс reconciliation (блокер 2.3)?
  3. Есть ли webhook/callback когда оператор провёл возврат через ЛК или чек коррекции (блокер 2.2)?
  4. Текущий payload webhook payment_success — содержит ли fn_number, fd_number, fp_sign, shift_number (блокер 2.4)?
  5. Есть ли уведомления об изменениях в каталоге (когда в ЛК поменяли цену / добавили товар)? Есть ли GET /products?modified_since=... или timestamp’ы на товарах (блокер 2.6)?

Если после уточнений остались блокеры — запросы на разработку:

  1. Cross-device push — если механизма из п.1 нет или его нельзя использовать нам — готовы ли разрабатывать POST /invoices/push + экран «ожидают оплаты» в mPOS?
  2. Webhook’и на возврат/отмену/коррекцию — готовы добавить если сейчас нет?
  3. API смен ФН (GET /shift/{terminal_id} + POST /shift/close + webhook shift_expiring) — как приоритезировано у них?
  4. Фискальные поля в webhook — расширить payload если сейчас их нет.
  5. Catalog-change webhook или modified_since-эндпоинт — блокер 2.6.
  6. Автоматизация онбординга ЛК (блокер 2.7): расширение POST /client/add чтобы передавать webhook_url и external_id, возврат webhook_secret в ответе, webhook lk.created когда ЛК готов. Это снимает 3 ручных шага с оператора при каждой новой ТТ.

Уточнения по mapping (не разработка):

  1. Стабильность mpos_terminal_id — меняется ли он при замене железа? Это логический или физический идентификатор?
  2. paykeeper_id (из Partner API /client/add) vs mpos_merchant_id (в webhook) — это один и тот же ID или разные сущности? Если разные — есть ли endpoint «список merchant’ов для client’а»?

7. Если PayKeeper не успеет

Если ключевых API (особенно блокера 2.1 — cross-device push) не будет к запуску — активируем Plan B (см. ADR-016 Переход на PayKeeper): интеграция по iiko-схеме через iiko API, PayKeeper откладывается.

Особенно критично: если PayKeeper не готов делать cross-device push и строки 64/83/59 бэклога нам не подходят (п.2.1) — это архитектурная блокировка. Либо уходим на single-device модель (наш софт на их кассе), либо на другого эквайера.


8. Риск-оценка MVP при текущем состоянии PayKeeper

РискВероятностьImpactМитигация
Нет cross-device push → отдельный планшет не работаетСредняя (бэклог намекает что есть, но не точно)Архитектурный фейл MVPBlocker 2.1
ФН блокируется в часы пикВысокаяПростой ТТ, потеря выручкиBlocker 2.5
Потерян webhook — не знаем о платежеСредняяРасхождение журналаBlocker 2.3
Возврат не отображён в ERP вовремяВысокаяРасхождение с бухучётомBlocker 2.2
Налоговая не может сопоставить чекНизкая, высокий ущербCompliance failBlocker 2.4
Правки в ЛК перезатираются нашим push’ем каталогаСредняяКонфликт данных, жалобы мерчантовBlocker 2.6
Оператор забыл настроить webhook URL при новой ТТВысокая при массовом онбордингеКасса работает, в ERP платежей нетBlocker 2.7

Без закрытия блокеров 2.1–2.7 — не запускаем в текущей архитектуре. Это объективные compliance/uptime/архитектурные/операционные риски, не технические удобства.


9. Ссылки