Реализация NFC-оплаты (HCE) через Android-приложение
Host-based Card Emulation — технология, которая позволяет Android-приложению прикидываться бесконтактной картой без физического SE (Secure Element). Звучит просто. На деле — это реализация ISO/IEC 7816-4 поверх NFC с APDU-командами, управление жизненным циклом сервиса, регистрация AID и прохождение сертификации платёжной системы. Большинство команд типа SELECT AID и GET PROCESSING OPTIONS нужно реализовывать вручную.
Главная сложность: APDU-диалог с терминалом
Когда терминал POS «видит» телефон, он отправляет серию APDU-команд. Стандартный сценарий EMV Contactless начинается с:
00 A4 04 00 07 A0 00 00 00 03 10 10 — SELECT PPSE
Приложение должно ответить корректным FCI с именем AID. Дальше терминал выберет конкретное приложение (SELECT AID), запросит параметры транзакции через GET PROCESSING OPTIONS, прочитает записи через READ RECORD. Каждый ответ — строго по EMV Book 3 и Book C-2.
Ошибка в одном байте TLV-структуры — терминал выдаёт «Карта не принята» без каких-либо подробностей в логах приложения. Отлаживать приходится через NFC-снифер (например, ACR122U + libnfc + Wireshark) или аппаратный анализатор протокола.
Регистрация AID и конфликты
Каждое HCE-приложение регистрирует AID в AndroidManifest.xml через <host-apdu-service>. Если на устройстве несколько приложений с одним AID — Android показывает disambiguation dialog. Для проприетарных AID это управляемо. Для стандартных (Visa: A0000000031010, Mastercard: A0000000041010) возникает конфликт с банковскими приложениями — пользователю придётся выбирать каждый раз.
Решение — регистрировать собственный проприетарный AID в диапазоне F0xx..., согласовывать его с процессором и настраивать терминальную сторону на приём. Либо использовать HCE_PAYMENT category с предустановленным AID и корректно обрабатывать конфликты через CardEmulation.setPreferredService().
Архитектура HCE-сервиса
HostApduService — это Service, который Android запускает при появлении NFC-поля. Главный метод — processCommandApdu(), который вызывается в основном потоке. Блокировать его нельзя: если ответ не придёт за ~500 мс, терминал разрывает соединение.
Типичная структура:
class PaymentHceService : HostApduService() {
private val apduProcessor = ApduProcessor()
override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray {
return apduProcessor.process(commandApdu)
}
override fun onDeactivated(reason: Int) {
apduProcessor.reset()
// reason: DEACTIVATION_LINK_LOSS или DEACTIVATION_DESELECTED
}
}
ApduProcessor — конечный автомат, который держит состояние текущей транзакции: выбран ли PPSE, выбран ли AID, в каком состоянии GPO. Состояние сбрасывается в onDeactivated. Это критично: если не сбросить после DEACTIVATION_LINK_LOSS, следующая транзакция начнётся с неправильного состояния.
Безопасность токенов
Реальные PAN-данные хранить в приложении нельзя. Современная схема — динамические токены: сервер выдаёт single-use cryptogram для каждой транзакции. Приложение запрашивает токен заранее (при открытии платёжного экрана), хранит в зашифрованном виде в EncryptedSharedPreferences или Android Keystore, передаёт терминалу в ответе на READ RECORD.
Срок жизни токена — обычно 30–60 минут или одна транзакция. При истечении — приложение запрашивает новый до начала следующей транзакции, а не в момент processCommandApdu (там нет времени на сетевой запрос).
Тестирование без реального POS-терминала
Для разработки и CI используем:
- ACR122U + PC/SC — USB NFC-ридер, эмулирует терминал на ПК, можно скриптовать APDU-последовательности
- Mastercard PayPass Test Tool — официальный инструмент для валидации EMV-ответов
- EMV-Co contactless test cases — набор сценариев для сертификации
Без прохождения тест-кейсов EMV-Co получить допуск к реальным терминалам Visa/Mastercard не получится. Это отдельный этап проекта.
Процесс и сроки
Работа разбивается на несколько фаз: проектирование APDU-диалога под конкретный процессинг → реализация HCE-сервиса → интеграция с бэкендом токенизации → тестирование на реальных терминалах → подготовка документации для сертификации.
Минимальный PoC с кастомным AID — 2–3 недели. Полноценная интеграция с EMV-сертификацией — от 2 месяцев. Точные сроки после изучения требований процессинга и схемы токенизации.







