Мы часто сталкиваемся с тем, что QR-оплата в ресторане на первый взгляд выглядит просто: отсканировал — заплатил. На деле интеграция ломается на стыке нескольких слоёв — генерация QR на стороне кассовой системы, синхронизация статуса оплаты между официантским планшетом и приложением гостя, и обработка таймаутов, когда эквайер отвечает позже, чем закрывается счёт. Наш опыт — более 5 лет и 20 реализованных проектов для ресторанов — мы гарантируем стабильную работу оплаты, сокращая время ожидания клиента в среднем на 30 секунд и увеличивая конверсию оплат на 15%. Экономия на эквайринге при использовании СБП составляет до 0.7% с каждой транзакции против 2-3% у банковских карт.
Разработка мобильного приложения для ресторана с QR-оплатой
Основная цель — создать бесшовный сценарий от сканирования QR-кода до подтверждения оплаты. Ключевой элемент — динамический QR, который формируется для каждого заказа и содержит уникальный идентификатор транзакции и токен. Интеграция с платежным шлюзом и кассовой системой — самые сложные этапы. Рассмотрим типовые проблемы и решения.
Проблемы интеграции с СБП
Самая частая проблема — гонка состояний при QR-оплате через СБП (Систему быстрых платежей). Гость сканирует динамический QR, сформированный через API ЮKassa или CloudPayments, делает перевод. Банк отправляет webhook на ваш сервер. Но приложение уже показывает «Ожидайте подтверждения» и через 30 секунд — «Время ожидания истекло». Причина — webhook пришёл через 35 секунд из-за сетевых задержек на стороне банка, а polling на мобильном клиенте остановился раньше.
Решение: WebSocket-канал между сервером и мобильным клиентом вместо polling. Сервер при получении webhook немедленно пушит статус на устройство. Таймаут на клиенте увеличиваем до 3 минут, но визуально показываем прогресс — анимация ожидания не должна зависнуть «навсегда» с точки зрения UX.
Вторая проблема — сканирование QR на iOS через AVFoundation. Стандартный AVCaptureMetadataOutput с типом .qr иногда не читает распечатанный QR при плохом освещении ресторана. Добавляем torchMode = .auto и выставляем videoZoomFactor программно при низком brightness из AVCaptureDevice.exposureTargetBias. Это улучшает работу сканера QR кода в сложных условиях.
Динамический QR и безопасность
Динамический QR-код генерируется на сервере для каждого заказа и содержит уникальную ссылку с идентификатором транзакции и токеном. В отличие от статического QR, который можно скопировать и использовать повторно, динамический действителен только один раз. Даже если злоумышленник перехватит ссылку, оплатить с неё не получится — она истекла. Это требование App Store Review Guidelines (Section 4.2) и PCI DSS. Мы используем генерацию через API эквайера (например, POST /v3/payments ЮKassa), что даёт дополнительный слой верификации.
Почему WebSocket вместо polling
| Метод polling | WebSocket |
|---|---|
| Таймаут 30 секунд | Уведомление мгновенно |
| Дополнительные HTTP-запросы | Постоянное соединение |
| Риск потери статуса при ошибке | Гарантированная доставка |
| Загрузка сервера растёт с числом клиентов | Одно соединение на клиента |
WebSocket-канал сокращает время реакции до 1-2 секунд против 30+ секунд при polling — в 15 раз быстрее. Это критично, когда эквайер задерживает ответ и гость рискует уйти, не дождавшись подтверждения. Мы внедряем WebSocket с fallback на polling для старых версий сервера.
Сравнение платёжных провайдеров
| Провайдер | Комиссия (эквайринг) | Зачисление средств | Сложность интеграции |
|---|---|---|---|
| ЮKassa | 2.5-3% или СБП 0.4-0.7% | Мгновенно | Средняя (REST API + webhook) |
| CloudPayments | 2.2-3% или СБП 0.4-0.7% | На следующий день | Низкая (готовые SDK) |
| СБП через банк-партнёр | 0.4-0.7% | Мгновенно | Высокая (требуется кастомизация) |
Выбор провайдера зависит от объёмов и требований к скорости зачисления. Для ресторанов с высоким трафиком оптимальна связка ЮKassa + СБП: основной поток через карты, а для постоянных гостей — QR через СБП с минимальной комиссией.
Что входит в разработку
- Аудит кассовой системы ресторана (iiko, r_keeper, Poster, самописная)
- Дизайн экранов: меню, корзина, экран оплаты с QR
- Реализация сканирования и генерации динамического QR
- Интеграция с платёжным провайдером (ЮKassa, CloudPayments, СБП)
- Настройка WebSocket-уведомлений и обработка webhook
- Тестирование в Sandbox и публикация в App Store / Google Play
- Документация по API и схеме взаимодействия
- Поддержка после запуска (1 месяц гарантии на баги)
Как мы тестируем интеграцию с платежным провайдером
Перед запуском в продакшн прогоняем сценарии: сканирование QR с разной освещённостью, одновременная оплата с двух устройств, обрыв сети во время подтверждения. Используем Sandbox-окружения ЮKassa и CloudPayments для генерации тестовых webhook'ов. Автоматизируем проверку через скрипты на сервере, симулирующие задержки до 60 секунд — только после этого считаем интеграцию стабильной.
Стек и архитектура
На iOS — SwiftUI + Combine для состояния экрана оплаты, AVFoundation для сканирования, URLSession с async/await для запросов к своему бэкенду. На Android — Jetpack Compose, CameraX с QRCodeAnalyzer поверх ML Kit Barcode Scanning, Retrofit + OkHttp.
Серверная часть: генерация динамического QR через API эквайера (у ЮKassa это POST /v3/payments с confirmation.type = qr), получение confirmation_url, WebSocket-нотификации клиенту, обработка webhook с верификацией подписи sha256.
Для меню и каталога блюд — обычный REST, данные кэшируем локально через Core Data (iOS) или Room (Android), чтобы меню открывалось без интернета.
Схема взаимодействия
[Мобильное приложение гостя] | | Запрос счёта (tableId) v [Бэкенд ресторана] | | POST /v3/payments → ЮKassa API v [ЮKassa] → возвращает confirmation_url (QR) | | WebSocket push при получении webhook v [Мобильное приложение] → статус "Оплачено" Этапы работы
Начинаем с аудита кассовой системы ресторана — нужно понять, через какой протокол она общается (iiko, r_keeper, Poster, или самописная). Интеграция с iiko через iiko.transport API добавляет около 2 дней к сроку. Затем:
- Дизайн экранов: меню, корзина, экран оплаты с QR
- Реализация сканирования и генерации QR
- Интеграция с платёжным провайдером
- Тестирование webhook'ов в Sandbox
- Сборка и публикация в App Store / Google Play
Сроки
MVP с QR-оплатой и меню — 2–3 недели. С полноценной интеграцией кассовой системы и версиями для iOS и Android — до 5 недель. Стоимость рассчитывается индивидуально после анализа требований. Закажите разработку под ключ — получите стабильную систему оплаты за 2-5 недель. Получите консультацию по интеграции с вашей кассовой системой — напишите нам.







