Реализация KYC/AML верификации в мобильном криптоприложении
KYC в крипто-приложении — это не просто сканирование паспорта. Это комбинация документальной верификации, liveness detection, проверки по санкционным спискам OFAC/EU и интеграция с провайдером, у которого есть лицензия на работу с финансовыми данными в нужной юрисдикции. Выбор SDK влияет на UX, конверсию и соответствие регуляторным требованиям.
Выбор провайдера KYC
На рынке несколько устоявшихся решений: Sumsub, Onfido, Jumio, Persona, Veriff. Для крипто-приложений чаще всего выбирают Sumsub или Onfido — у обоих есть готовые Mobile SDK и опыт работы с криптовалютными платформами.
Sumsub SDK (iOS и Android) работает через applicant ID, который создаётся на backend:
// Android — инициализация Sumsub SDK
val snsMobileSDK = SNSMobileSDK.Builder(this, accessToken)
.withHandlers(
onStatusChanged = { newStatus, prevStatus ->
when (newStatus) {
SNSSDKState.Ready -> Log.d("KYC", "SDK ready")
SNSSDKState.Failed.Unauthorized -> refreshToken()
SNSSDKState.FinallyRejected -> showRejectedScreen()
SNSSDKState.ApplicantSubmitted -> navigateToWaitingScreen()
else -> {}
}
},
onError = { error ->
Sentry.captureException(RuntimeException("KYC error: ${error.description}"))
}
)
.build()
snsMobileSDK.launch()
Токен доступа живёт 60 секунд — нужен endpoint на backend для обновления (/kyc/token/refresh). Если пользователь долго заполнял форму и токен протух — SDK вызовет Unauthorized, и нужно незаметно для пользователя обновить токен и продолжить сессию.
Liveness Detection
Это ключевой момент для прохождения AML-аудита. Провайдеры требуют подтверждение, что перед камерой живой человек, а не фотография или дипфейк. Sumsub использует серию случайных жестов (поворот головы, моргание). Onfido — пассивный liveness (анализ текстуры кожи и микродвижений).
На практике: пользователи с плохим освещением или старыми камерами (Android-девайсы ниже mid-range) часто не проходят liveness с первого раза. Конверсия падает на 15-25% на бюджетных устройствах. Решение — добавлять подсказки по освещению до запуска liveness-шага и давать 3 попытки с объяснением причины отказа.
AML-проверки
После верификации личности — проверка по санкционным спискам. Это либо встроено в KYC-провайдера (Sumsub включает AML-скрининг в свои тарифы), либо подключается отдельно через Chainalysis, Elliptic или TRM Labs.
Chainalysis Reactor API позволяет проверить адрес кошелька на связи с darknet-маркетплейсами, mixing-сервисами и известными хакерскими адресами:
suspend fun checkWalletRisk(address: String): RiskScore {
val response = chainalysisApi.getAddressRisk(
address = address,
outputType = "SUMMARY"
)
return RiskScore(
score = response.risk,
category = response.cluster?.category,
isSanctioned = response.identifications
.any { it.category == "sanctions" }
)
}
Если isSanctioned == true — блокируем транзакцию и логируем для compliance-отчётности. Это не UX-решение, это юридическое требование.
Хранение статуса верификации
Статус KYC (pending / approved / rejected / recheck_needed) хранится на backend. Мобильное приложение кэширует его локально, но проверяет актуальность при каждом запуске и после вывода приложения из фона (через applicationWillEnterForeground / onResume).
Переход по экранам зависит от статуса. Пользователь без верификации видит ограниченный функционал — просмотр курсов, но не транзакции. После подачи документов — waiting screen с реалтайм-обновлением статуса через WebSocket или polling каждые 30 секунд.
Типичные ошибки
Самая частая — запускать KYC SDK без проверки доступности камеры и разрешений. На Android CAMERA permission может быть отозвана пользователем после первого запуска. Нужна явная проверка перед стартом SDK, иначе краш в недрах нативного кода провайдера.
Вторая — не обрабатывать FinallyRejected отдельно от Declined. FinallyRejected означает, что попытки исчерпаны и пользователь должен обратиться в поддержку. Declined — можно попробовать снова.
Интеграция KYC SDK + AML-проверки + UI для всех статусов — 2-4 недели. Стоимость рассчитывается индивидуально после выбора провайдера и анализа требований юрисдикции.







