SDK как у Sumsub: ключ, запуск, события
Схема такая же по смыслу: ваш сервер выдает короткий accessToken, приложение передает его в SDK, SDK открывает проверку документа и лица, а результат возвращается в callback и webhook.
Без выдумок
Сейчас SDK отдаем как готовые файлы Swift и Kotlin: скачали, положили в проект, вызвали `SNSMobileSDK`. CocoaPods, SPM и Maven можно публиковать отдельно после регистрации пакетов.
Совместимость
Публичные серверные пути и подпись сделаны под поддержанные Sumsub-compatible методы. Секретный ключ остается только на вашем сервере.
Создайте accessToken перед запуском SDK
Мобильное приложение не хранит секрет. Оно спрашивает ваш бэкенд, а бэкенд подписывает запрос и получает временный ключ проверки.
import crypto from "node:crypto";
async function signedPost(path, payload) {
const body = JSON.stringify(payload);
const ts = Math.floor(Date.now() / 1000).toString();
const sig = crypto
.createHmac("sha256", SUMSUB_COMPAT_SECRET)
.update(ts + "POST" + path + body)
.digest("hex");
const response = await fetch("https://verify.umbrellax.io" + path, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-App-Token": SUMSUB_COMPAT_TOKEN,
"X-App-Access-Ts": ts,
"X-App-Access-Sig": sig
},
body
});
return response.json();
}
await signedPost("/resources/applicants", {
externalUserId: "user_123",
email: "user@example.com",
fixedInfo: {
firstName: "Ivan",
lastName: "Ivanov",
dob: "1990-01-01",
country: "KZ",
idDocType: "PASSPORT"
}
});
const { token } = await signedPost("/resources/accessTokens/sdk", {
userId: "user_123",
ttlInSecs: 600
});Один файл в проект
Добавьте `UmbrellaXVerifySDK.swift`, разрешения камеры и микрофона, затем запускайте проверку из вашего экрана.
let sdk = SNSMobileSDK(accessToken: accessToken)
.withLocale(Locale(identifier: "ru"))
.withConf(SNSInitConfig(email: "user@example.com"))
.withAutoCloseOnApprove(0)
.tokenExpirationHandler { finish in
finish(fetchFreshAccessToken())
}
guard sdk.isReady else {
print(sdk.verboseStatus)
return
}
sdk.onStatusDidChange = { status in print(status) }
sdk.onComplete = { result in
print(result.status, result.verificationId ?? "")
print(result.faceSimilarity ?? 0, result.reasons)
result.evidence.forEach { item in
print(item.id, item.status, item.value)
}
}
sdk.onError = { error in print(error) }
sdk.launch(from: self)Info.plist:
<key>NSCameraUsageDescription</key>
<string>Камера нужна для съемки документа и живого лица</string>
<key>NSMicrophoneUsageDescription</key>
<string>Микрофон нужен для защищенной живой проверки</string>Один файл в приложение
Добавьте `UmbrellaXVerifySDK.kt`, объявите Activity и разрешения, затем вызовите builder из вашей Activity.
val tokenExpirationHandler = object : TokenExpirationHandler {
override fun onTokenExpired(): String? {
return fetchFreshAccessToken()
}
}
val snsSdk = SNSMobileSDK.Builder(this)
.withAccessToken(accessToken, onTokenExpiration = tokenExpirationHandler)
.withLocale(Locale("ru"))
.withConf(SNSInitConfig(email = "user@example.com"))
.withAutoCloseOnApprove(0)
.withHandlers(
onStatusDidChange = { status -> println(status) },
onComplete = { result ->
println(result.status + " " + result.verificationId)
println("${result.faceSimilarity} " + result.reasons.joinToString(","))
result.evidence.forEach { item ->
println("${item.id} ${item.status} ${item.value}")
}
},
onError = { error -> println(error) }
)
.build()
snsSdk.launch()AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<activity
android:name="io.umbrellax.verify.UmbrellaXVerifyActivity"
android:screenOrientation="portrait"
android:exported="false" />Виджет для сайта
Для сайтов и личных кабинетов: вставьте скрипт, передайте accessToken, получите результат.
<script src="https://verify.umbrellax.io/sdk/faces.js" defer></script>
<div id="faces"></div>
<script>
Faces.mount("#faces", {
token: "faces_sdk_live_...", // accessToken с вашего сервера
locale: "ru",
onStatusDidChange: (status) => console.log(status),
onComplete: (result) => { // accepted | retry | rejected
console.log(result.status, result.verificationId);
console.log(result.faceSimilarity, result.reasons);
console.table(result.evidence); // документ, лицо, живая проверка
}
});
</script>Совместимые серверные методы
Можно подключаться через REST без SDK и проверять статус по заявке.
POST https://verify.umbrellax.io/resources/applicants
POST https://verify.umbrellax.io/resources/accessTokens/sdk
GET https://verify.umbrellax.io/resources/applicants/{id}/status
POST https://verify.umbrellax.io/resources/applicants/{id}/info/idDoc
# Заголовки такие же:
# X-App-Token, X-App-Access-Ts, X-App-Access-SigЧто возвращает SDK
`onStatusDidChange` показывает готовность потока. `onComplete` возвращает `accepted`, `retry` или `rejected`, номер проверки, риск, причины решения, процент совпадения лица и краткий журнал доказательств.
Что делает сервер
Сервер хранит секрет, выпускает короткие токены, принимает документы, пишет журнал доказательств и отправляет итог через webhook.