KYC Widget
Браузерный флоу верификации личности: съёмка документа, селфи и liveness-проверка (антиспуфинг). Есть четыре способа интеграции:
- Тег
<script>в обычном JavaScript-приложении —window.KYCWidget.setupKYC({...}) - npm-пакет kyc-widget-nv в React-приложении —
<KycWidget ... /> - Тег
<script>в React-приложении - Прямая ссылка (без интеграции) — https://kyc.neuro-vision.ru
Перед запуском
❗ Не рекомендуется встраивать Web SDK в
<iframe>. Подключайте виджет только в основную страницу сайта — как элемент корневого DOM-документа.
- Добавьте домен сайта в разрешённые. В личном кабинете откройте «Доступ» → «Разрешённые домены» и добавьте домены, на которых встраиваете виджет. Виджет работает только на доменах из этого списка и только на сайтах с https. Маска
*.example.comразрешает все поддоменыexample.com, но не самexample.com. Изменения вступают в силу в течение двух минут. Менять список может владелец аккаунта или пользователь с правом делегирования. - Откройте страницу по HTTPS. Браузер даёт доступ к камере только на защищённых страницах.
- Не встраивайте виджет в
<iframe>(см. предупреждение выше). Если обойтись без фрейма нельзя, разрешите ему камеру:<iframe src="..." allow="camera">. Без этого браузер не даст камеру. Инлайн-режим (mountElementId) внутри iframe не работает — см. таблицу параметров. - Мобильное приложение. Для запуска внутри WebView нужны отдельные настройки приложения — см. Мобильные приложения и WebView.
Язык интерфейса
Параметра языка у виджета нет. Язык выбирается так: сохранённый выбор пользователя в этом браузере → язык браузера → английский. Список ограничен языками, включёнными в сценарии; пользователь может переключить язык в виджете. Всего доступно 29 языков.
Экраны окружения
Если устройство или браузер не подходят, виджет показывает пользователю экран с подсказкой, а не ошибку:
| Ситуация | Что видит пользователь |
|---|---|
| Доступ к камере запрещён | Просьба разрешить доступ к камере на этом устройстве |
| Камера не поддерживает нужное разрешение | Просьба повторить попытку с более современного устройства |
| Сценарий не разрешает камеру компьютера | QR-код и ссылка, чтобы продолжить проверку на смартфоне |
| Устройство в горизонтальной ориентации | Просьба повернуть устройство в портретный режим |
| Нет интернет-соединения | Сообщение об отсутствии соединения |
| Неверные дата или время на устройстве | Просьба исправить дату и время |
| Браузер блокирует проверку | Просьба открыть ссылку в другом браузере или на другом устройстве |
Параметры конфигурации
| Параметр | Тип | Обязательный | По умолчанию | Описание |
|---|---|---|---|---|
| scenarioId | string | Да* | — | Уникальный идентификатор сценария из раздела «KYC/AML» личного кабинета (*не требуется при использовании taskId) |
| clientKey | string | Да* | — | Уникальная строка (максимум 36 символов), которая передаётся в зашифрованном виде; пример кода шифрования доступен в личном кабинете в разделе «KYC/AML» (*не требуется при использовании taskId) |
| clientUser | string | Нет | — | Идентификатор пользователя на стороне клиента, максимум 36 символов. Не обязан быть уникальным: передавайте одно и то же значение в разных сессиях, чтобы потом поиском по нему найти все сессии (попытки) этого пользователя |
| taskId | string | Нет | — | Идентификатор задачи верификации. Нужен, только если вам выдали ссылку на задачу вида https://kyc.neuro-vision.ru/<taskId>: виджет открывает эту задачу, а scenarioId/clientKey не нужны. При обычной интеграции и для одноразовых ссылок из раздела «KYC Ссылки» используются scenarioId и clientKey |
| isOpen | boolean | Да* | — | Видимость виджета (*обязателен только для React-компонента) |
| theme | string | Нет | из настроек сценария | Тема оформления: light или dark |
| stickySession | boolean | Нет | false | «Липкие» сессии: виджет запоминает clientKey для сценария (в localStorage, на 15 минут). Повторное открытие в этом окне продолжает предыдущую сессию, даже если передан другой clientKey |
| closeCb | function | Нет | — | Вызывается при закрытии виджета: кнопкой ×, кнопкой возврата на экране результата (при любом итоге) или при сбое виджета. Не вызывается при повторном setupKYC (прежний экземпляр заменяется без колбэка) и если элемента с mountElementId нет на странице |
| successCb | function | Нет | — | Вызывается один раз и только при итоге success, когда виджет показывает экран результата: окно в этот момент ещё открыто. Получает результат сессии в виде JSON-строки. Про остальные итоги — раздел «Как получить итог проверки» |
| finalizedCb | function | Нет | — | Колбэк при открытии виджета для сессии, которая уже была финализирована ранее. Получает { status } |
| topOffset | number | Нет | 0 | Отступ сверху в пикселях |
| bottomOffset | number | Нет | 0 | Отступ снизу в пикселях |
| blurHost | boolean | Нет | false | Если true, фон виджета рендерится как «матовое стекло» поверх страницы хоста (без фоновой картинки и правой blur-панели) — страница хоста просвечивает через полупрозрачный размытый слой |
| mountElementId | string | Нет | — | Только для интеграции через script-тег (widget-lib.js). Если задан, виджет монтируется инлайн внутрь элемента с этим id, а не поверх всей страницы. Виджет заполняет хост-элемент (width/height: 100%), поэтому задайте элементу явные размеры. См. пример ниже. Не поддерживается внутри cross-origin iframe — браузер заблокирует камеру; в этом случае вызывается closeCb, чтобы хост мог сбросить своё состояние. Не вызывайте setupKYC внутри closeCb — повторные детекты iframe зациклятся. Если элемента с таким id нет в DOM, виджет молча не запускается: окна нет, closeCb не вызывается |
Payload колбэка successCb
successCb получает результат верификации в виде JSON-строки. Точный набор полей зависит от шагов сценария (шаг с документом приходит как "type": "document", liveness — как "type": "liveness" и т.д.). Поле schemaId в результате — идентификатор сценария, тот же, что scenarioId. Сокращённый пример:
{
"sessionId": "098d57-...",
"status": "success",
"errors": [],
"results": [
{
"type": "liveness",
"status": "success",
"errors": [],
"tries": 1,
"startedAt": "2026-07-19T09:41:37.590Z",
"faces": ["https://..."],
"video": "https://..."
}
],
"schemaId": "3676-...",
"clientKey": "46d1c-...",
"clientUser": "",
"createdAt": "2026-07-19T09:41:37.000Z",
"secondsToLive": 0
} Жизненный цикл виджета
- Функции закрытия или уничтожения виджета нет: пользователь закрывает его сам — кнопкой × или кнопкой возврата на экране результата.
- Повторный вызов
setupKYC, пока виджет открыт, заменяет открытый экземпляр новым;closeCbу прежнего не вызывается. Не вызывайтеsetupKYCповторно, пока виджет открыт. - Если виджет монтировался в элемент (
mountElementId), содержимое элемента очищается при закрытии.
Как получить итог проверки
successCbприходит только при итогеsuccess. Он не означает, что окно закрыто: пользователь ещё видит экран результата.- Любой другой итог (отказ, ошибка, пользователь закрыл виджет) колбэком не приходит: срабатывает только
closeCb, без статуса. Итог сессии в этом случае берите из вебхука или запросом статуса сессии. - Решение о прохождении проверки принимайте на сервере по вебхуку или статусу сессии, а не по колбэкам в браузере.
1. Пример интеграции в JavaScript-приложение через script-тег (index.html)
- Создайте кнопку с начальным состоянием загрузки.
- Загрузите скрипт динамически и активируйте кнопку по готовности.
- Вызовите
window.KYCWidget.setupKYC()по клику на кнопку.
Файл: index.html
<body>
<button id="btn" disabled>Загрузка...</button>
<script>
const btn = document.getElementById("btn");
const script = document.createElement("script");
script.src = "https://kyc.neuro-vision.ru/lib/widget-lib.js";
script.onload = () => {
btn.disabled = false;
btn.textContent = "Открыть KYC-виджет";
};
script.onerror = () => {
btn.textContent = "Не удалось загрузить KYC-виджет";
};
document.body.appendChild(script);
const openWidget = () => {
window.KYCWidget.setupKYC({
scenarioId: "scenarioId",
clientKey: "clientKey",
clientUser: "clientUser",
theme: "light",
stickySession: true,
topOffset: 0,
bottomOffset: 0,
// Необязательный. Если задан, виджет монтируется ВНУТРЬ элемента
// с этим id (инлайн-блок), а не поверх всей страницы. Элемент
// должен существовать в DOM. При закрытии элемент очищается.
// ⚠️ Не открывайте страницу хоста внутри cross-origin <iframe> —
// браузер заблокирует getUserMedia, и камера не запустится.
// mountElementId: "kyc-here",
closeCb: () => console.log("CLOSE CALLBACK"),
successCb: (sessionJson) => console.log("SUCCESS CALLBACK", sessionJson),
finalizedCb: ({ status }) => console.log("FINALIZED CALLBACK", status),
});
};
btn.addEventListener("click", openWidget);
</script>
</body> 2. Пример интеграции в React-приложение через npm-пакет
- Установите npm-пакет kyc-widget-nv:
npm i kyc-widget-nv. - Импортируйте в приложение:
import { KycWidget } from "kyc-widget-nv". - Заведите переменную состояния для управления видимостью виджета.
- Передайте пропсы компоненту
KycWidget(см. «Параметры конфигурации» выше).
Пакет не включает React в бандл — react и react-dom должны быть установлены в вашем приложении.
Файл: App.js
import { useState } from "react";
import { KycWidget } from "kyc-widget-nv";
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>Открыть</button>
<KycWidget
scenarioId="scenarioId"
clientKey="clientKey"
clientUser="clientUser"
isOpen={isOpen}
stickySession={true}
theme="light"
topOffset={0}
bottomOffset={0}
closeCb={() => setIsOpen(false)}
successCb={(sessionJson) => console.log("SUCCESS CALLBACK", sessionJson)}
finalizedCb={({ status }) => console.log("FINALIZED CALLBACK", status)}
/>
</>
);
}
export default App; 3. Пример интеграции в React-приложение через script-тег
Используйте этот способ, если не можете установить npm-пакет и нужно загрузить виджет через script-тег.
- Загрузите скрипт виджета динамически в
useEffect. - Отслеживайте состояние загрузки через
useState. - Показывайте кнопку только после загрузки скрипта.
- Вызовите
window.KYCWidget.setupKYC()по клику на кнопку.
Файл: App.js
import { useState, useEffect, useCallback } from "react";
function App() {
const [widgetLoaded, setWidgetLoaded] = useState(false);
const openWidgetHandler = () => {
window.KYCWidget.setupKYC({
scenarioId: "scenarioId",
clientKey: "clientKey",
clientUser: "clientUser",
theme: "light",
topOffset: 0,
bottomOffset: 0,
// Необязательный. Если задан, виджет монтируется ВНУТРЬ элемента
// с этим id (инлайн-блок), а не поверх всей страницы. Элемент
// должен существовать в DOM. При закрытии элемент очищается.
// ⚠️ Не открывайте страницу хоста внутри cross-origin <iframe> —
// браузер заблокирует getUserMedia, и камера не запустится.
// mountElementId: "kyc-here",
closeCb: () => console.log("CLOSE CALLBACK"),
successCb: (sessionJson) => console.log("SUCCESS CALLBACK", sessionJson),
finalizedCb: ({ status }) => console.log("FINALIZED CALLBACK", status),
});
};
const loadWidgetScript = useCallback(() => {
const widgetScript = document.getElementById("kyc-widget-script");
if (widgetScript) return;
const script = document.createElement("script");
script.id = "kyc-widget-script";
script.src = 'https://kyc.neuro-vision.ru/lib/widget-lib.js';
script.defer = true;
script.crossOrigin = "anonymous";
script.onload = () => {
setWidgetLoaded(true);
};
script.onerror = () => {
console.error("Не удалось загрузить скрипт KYC-виджета");
};
document.head.appendChild(script);
}, []);
useEffect(() => {
if (window.KYCWidget) {
setWidgetLoaded(true);
return;
}
loadWidgetScript();
}, [loadWidgetScript]);
return (
<>
{widgetLoaded && (
<button onClick={openWidgetHandler}>Открыть KYC-виджет</button>
)}
</>
);
}
export default App; 4. Верификация по ссылке
Для прохождения верификации можно воспользоваться сервисом https://kyc.neuro-vision.ru напрямую.
Переход по ссылке следующего вида создаёт сессию:
https://kyc.neuro-vision.ru/scenarioId/encrypted(clientKey)
https://kyc.neuro-vision.ru/scenarioId/encrypted(clientKey)/clientUser - scenarioId: уникальный идентификатор сценария, его нужно получить в личном кабинете в разделе «KYC/AML».
- clientKey: уникальная строка (максимум 36 символов), которая передаётся в зашифрованном виде; пример кода шифрования доступен в личном кабинете в разделе «KYC/AML». Зашифрованный ключ — это base64 (может содержать
/и+), поэтому при построении ссылки его нужно URL-энкодить. - clientUser: необязательный. Идентификатор пользователя на стороне клиента, максимум 36 символов. Не обязан быть уникальным — передавайте одно значение в разных сессиях, чтобы потом найти все сессии (попытки) этого пользователя.
Одноразовые ссылки с ограниченным сроком и числом переходов создаются в личном кабинете, раздел «KYC Ссылки».
Возврат на сайт после проверки
Если в основных настройках сценария задан «URL-адрес мобильного перенаправления в случае успеха», виджет, открытый по прямой ссылке, возвращает пользователя на этот адрес и дописывает параметры ?sessionId=<id сессии>&status=<итоговый статус>:
- при итоге
success— автоматически через 5 секунд; - при любом итоге — по кнопке возврата на экране результата.
При встраивании на ваш сайт (setupKYC, npm-пакет) перенаправления нет: кнопка возврата закрывает виджет и вызывает closeCb. Статус из адреса возврата служит подсказкой для интерфейса; итог проверяйте на сервере.
Ссылка на задачу
Если вам выдали ссылку на задачу верификации, она имеет вид:
https://kyc.neuro-vision.ru/taskId
https://kyc.neuro-vision.ru/taskId/cu/clientUser