Оплата картой, события и сбои
Оплата картой
Укажите в оплате "type": "2", без rrn. POSfix открывает платёжный экран банка поверх вашего приложения, клиент прикладывает карту, а после ответа экран закрывается, и вы возвращаетесь в своё приложение.
Экран POSfix не появляется.
| Терминал | Приложение банка |
|---|---|
| PAX с SPS (MICB, VICB) | сервис SPS терминала |
| Sunmi с Ashburn SmartPOS (MAIB, VICB) | SmartPOS |
| Телефон с TapXphone | TapXphone |
На Sunmi и TapXphone POSfix открывает приложение банка при оплате картой, при card.void, card.refund и при закрытии банковского дня после report.z. Android разрешает это, только пока ваше приложение на экране и привязано к POSfix; флаг, которого требует Android 14+, SDK ставит сам. Если ваше приложение отправляет команды из фона, дайте POSfix разрешение «Поверх других приложений».
На PAX с SPS ничего из этого не нужно. Если Android не позволит открыть приложение банка, оплата вернёт CARD_PAYMENT_DECLINED.
Если продажа не завершилась после того, как карта была одобрена, POSfix сам пытается отменить оплату в банке. Это происходит, когда другая карта в той же продаже отклонена, когда чек не доходит до SFS или когда другая фискальная операция держит терминал занятым.
MIA QR
На Sunmi со SmartPOS Victoriabank и на TapXphone, если банк предлагает MIA QR, клиент может выбрать его прямо на экране банка вместо карты.
Вы всё равно передаёте "type": "2". POSfix фискализирует оплату как «другой платёжный инструмент» (ACPS 7), а в ответе cardPaymentResult.isMiaQr равно true.
События
Через setEventListener вы получаете этапы команд, чтобы показывать их на своём экране. У каждого события есть type, requestId и data. События приходят во все подключённые приложения, поэтому фильтруйте их по requestId.
// sent = то, что вернул posfix.execute(...) для текущей продажи
posfix.setEventListener { event ->
if (event.optString("requestId") != sent.requestId) return@setEventListener
when (event.getString("type")) {
"cardPaymentStarted" -> showMessage("Приложите карту")
"fiscalizing" -> showMessage("Выдаётся чек…")
"printFailed" -> showMessage("Чек не напечатан — проверьте бумагу")
}
}
type | Что произошло |
|---|---|
commandStarted / commandFinished | Команда началась / завершилась. data.success показывает, с каким результатом. |
cardPaymentStarted | Открылся экран банка, ожидается карта. |
cardPaymentApproved / cardPaymentDeclined | Ответ банка. |
fiscalizing | Чек отправляется в SFS. |
mevRetry | SFS не ответила. POSfix повторяет попытку: attempt, maxAttempts, secondsLeft. |
fiscalized | Чек выдан: receiptNumber, fiscalCode. |
saleFailed | Чек не был выдан в SFS. POSfix попытался отменить одобренные оплаты картой. |
printing / printed / printFailed | Печать чека. Идёт отдельно от ответа; printed или printFailed обычно приходят после него. |
cancelRequested | POSfix получил запрос на остановку. |
Не ждите бумагу, чтобы закрыть продажу на своём экране. При printFailed, когда исправите принтер, отправьте sale.reprint с saleId: выйдет оригинал, а не дубликат.
Остановка продажи
posfix.cancel(sent.requestId) останавливает продажу, пока это ещё возможно:
- До оплаты картой: продажа уже не запустится.
- Пока клиент на экране банка: приложение банка нельзя закрыть извне, но клиент может отказаться от оплаты в нём. Если карта всё же будет одобрена, POSfix сразу отменит оплату.
- Пока POSfix повторяет запросы к SFS: ожидание прерывается, и продажа останавливается.
- После выдачи фискального чека: остановка уже не действует. Чек нельзя отозвать.
Остановленная продажа возвращает SALE_CANCELLED. Остановить её может только приложение, которое отправило команду.
Сбои и возобновление
Ваше приложение падает посреди продажи. POSfix всё равно завершает продажу. После перезапуска отправьте request.result с ключом продажи и узнайте результат. См. Ключ идемпотентности.
POSfix останавливается посреди продажи. SDK сразу завершает выполняемые команды с POSFIX_DISCONNECTED и вызывает onDisconnected. Когда POSfix снова запускается, в том числе после обновления, SDK сам восстанавливает привязку и вызывает onConnected. Затем проверьте результат через request.result.
Терминал перезагружается. POSfix запускается сам после загрузки, без экрана.
Первая команда после холодного старта занимает несколько секунд. POSfix запускает свои сервисы, а ваши запросы ждут в очереди и не теряются. Если он не запустится за 45 с, вы получите ENGINE_NOT_READY.
Фискальный день
Фискальный день длится 24 часа с момента первого чека. Когда он истекает, продажи возвращают FISCAL_DAY_EXPIRED, пока вы не отправите report.z.
Если на терминале включён автоматический Z-отчёт, POSfix сам выдаёт его в заданное время, даже при закрытом экране. На Sunmi следующее за ним закрытие банковского дня открывает SmartPOS, поэтому ему нужно разрешение «Поверх других приложений».