Розробка системи верифікації гравців крипто-казино
Крипто-казино працюють під подвійним тиском: з одного боку — користувачі, що цінують анонімність та прийшли в Web3 саме за нею; з іншого — регулятори та платіжні партнери, що вимагають KYC, AML-скринінг та перевірку віку. Знайти баланс між цими вимогами — архітектурна задача, не просто юридична.
Рівні верифікації
Не всі користувачі вимагають однакової верифікації. Tiered підхід — стандарт для gambling платформ:
Tier 0 — мінімальний (до $500/місяць): електронна пошта, wallet підключення, auto AML скринінг адреси (Chainalysis або Elliptic). Ніяких документів, миттєва відповідь.
Tier 1 — базовий (до $5,000/місяць): ім'я + дата народження + країна проживання. Автоматична перевірка через sanctions lists. Підтвердження акаунту по email або SMS.
Tier 2 — розширений (до $50,000/місяць): Government ID (паспорт, Driver's License), liveness check (selfie з документом), адреса проживання (utility bill). Верифікатор: Sumsub, Onfido, чи аналог.
Tier 3 — enhanced due diligence (> $50,000/місяць або VIP): Source of Funds (звідки гроші), Source of Wealth, розширена PEP/Sanctions перевірка, ручна перевірка compliance офіцером.
Технічна інтеграція KYC
Sumsub — стандартний вибір для gambling
Sumsub надає SDK для web та mobile, WebSDK для embedded flow:
// Генерація SDK token на бекенді
async function getSumsubToken(applicantId: string): Promise<string> {
const timestamp = Math.floor(Date.now() / 1000);
const method = 'POST';
const url = `/resources/accessTokens?userId=${applicantId}&levelName=basic-kyc-level`;
const signature = crypto
.createHmac('sha256', SUMSUB_SECRET_KEY)
.update(timestamp + method + url)
.digest('hex');
const response = await axios.post(
`https://api.sumsub.com${url}`,
{},
{
headers: {
'X-App-Token': SUMSUB_APP_TOKEN,
'X-App-Access-Sig': signature,
'X-App-Access-Ts': timestamp,
}
}
);
return response.data.token;
}
// Frontend ініціалізація SDK
import SumsubWebSdk from "@sumsub/websdk";
const sdk = SumsubWebSdk.init(
accessToken,
() => refreshToken(), // callback для оновлення токена
{
lang: "uk",
onMessage: (type, payload) => {
if (type === "idCheck.onApplicantStatusChanged") {
if (payload.reviewResult?.reviewAnswer === "GREEN") {
handleKYCApproved(payload.applicantId);
}
}
},
onError: (error) => console.error("Sumsub error:", error),
}
);
sdk.launch("#sumsub-container");
Webhook обробка результатів
Sumsub присилає webhook при зміні статусу. Важливо — перевірити підпис webhook, щоб не прийняти поддельний callback:
function verifySumsubWebhook(req: Request): boolean {
const signature = req.headers['x-payload-digest'];
const secret = process.env.SUMSUB_WEBHOOK_SECRET;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(req.rawBody) // raw body, не parsed JSON
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
async function handleSumsubWebhook(payload: SumsubWebhookPayload) {
const { applicantId, reviewResult, type } = payload;
if (type === "applicantReviewed") {
if (reviewResult.reviewAnswer === "GREEN") {
await db.updateUserKYCStatus(applicantId, "APPROVED", reviewResult.reviewRejectType);
await updateUserTier(applicantId);
} else if (reviewResult.reviewAnswer === "RED") {
await db.updateUserKYCStatus(applicantId, "REJECTED", reviewResult.moderationComment);
await notifyUser(applicantId, "kyc_rejected");
}
}
}
AML скринінг крипто-транзакцій
Особливо критично для казино: гроші з darknet markets, украдені фонди — пряма відповідальність платформи.
Chainalysis KYT (Know Your Transaction) інтеграція
async function screenAddress(address: string, asset: string): Promise<RiskScore> {
const response = await chainalysisClient.post('/v1/users', {
userId: address,
});
const transferResponse = await chainalysisClient.post('/v1/transfers', {
network: asset,
asset: asset,
transferReference: address,
direction: 'received',
});
return {
riskScore: transferResponse.data.riskScore,
cluster: transferResponse.data.cluster?.name,
category: transferResponse.data.cluster?.category,
};
}
Risk категорії для автоматичного блокування: darknet market, stolen funds, ransomware, sanctions. Для таких адрес — автоматичне відхилення депозиту та заморозка акаунту без ручної перевірки.
Grey zone категорії (gambling, P2P exchange, mixing): вимагають ручної перевірки compliance офіцером, не автоматичного блока.
OFAC Sanctions Screening
Окремо від крипто-скринінгу — перевірка wallet адрес у OFAC SDN List. Chainalysis це робить автоматично, але для додаткової захисту:
// Періодично оновлюваний список OFAC адрес
const ofacAddresses = new Set(await fetchOFACList());
function isOFACSanctioned(address: string): boolean {
return ofacAddresses.has(address.toLowerCase());
}
Верифікація віку без документів
Для ринків де документальний KYC неприйнятний (або до KYC tier), але потрібна перевірка віку:
Yoti Age Verification — сервіс, що верифікує вік без передачі document details казино. Користувач проходить верифікацію у Yoti, отримує signed age token. Казино бачить тільки "старший 18" — без імені, фото, номера документа.
AgeID (UK стандарт) — аналогічний підхід, використовується британськими gambling операторами.
Інтеграція: OAuth 2.0 flow, Yoti виступає identity provider. Казино отримує ID Token з клеймом over_18: true, без PII.
Геоблокування та IP верифікація
KYC не замінює геоблокування. Обов'язкові перевірки:
async function checkPlayerEligibility(ip: string, walletAddress: string): Promise<EligibilityResult> {
// IP геолокація
const geoResult = await maxmindClient.country(ip);
const country = geoResult.country.isoCode;
if (BLOCKED_COUNTRIES.includes(country)) {
return { allowed: false, reason: 'geo_blocked', country };
}
// VPN/Proxy виявлення
const ipRisk = await ipqualityscore.check(ip);
if (ipRisk.vpn || ipRisk.proxy || ipRisk.tor) {
return { allowed: false, reason: 'vpn_detected' };
}
return { allowed: true, country };
}
Списки заблокованих країн визначаються лицензією: Кюрасао, Мальта, Естонія — кожна ліцензія має свій список restricted jurisdictions.
Responsible Gambling функції
Ліцензовані казино повинні реалізовувати:
- Self-exclusion: користувач може заблокувати свій акаунт на період (1 день до перманентного). Після активації — миттєвий logout, блок на re-registration.
- Deposit limits: денні/тижневі/місячні лімити. Зменшити можна відразу, збільшити — тільки через cooling-off період (24-72 години).
- Reality check: всплувне повідомлення про час та суму втрат кожні N хвилин.
- Cooling-off період: тимчасова пауза без повного self-exclusion.
Стек та архітектура
| Компонент | Рішення | Примітка |
|---|---|---|
| KYC провайдер | Sumsub / Onfido | Sumsub краще для WW покриття |
| AML on-chain | Chainalysis KYT | або Elliptic, Crystal Blockchain |
| Age verification | Yoti / AgeID | для soft-KYC ринків |
| Geo/IP check | MaxMind + IPQualityScore | два провайдери для надійності |
| OFAC/Sanctions | Chainalysis + власний list | денне оновлення |
| Document storage | Encrypted S3 + key management | retention policy за регуляцією |
Часова шкала розробки
| Компонент | Час |
|---|---|
| KYC tier система + Sumsub інтеграція | 2-3 тижні |
| AML скринінг + webhook обробка | 1-2 тижні |
| Геоблокування + IP перевірки | 1 тиждень |
| Responsible gambling функції | 1-2 тижні |
| Admin dashboard для compliance | 1-2 тижні |
Повна compliance система під конкретну ліцензію — 6-10 тижнів. Вартість залежить від обраних провайдерів та обсягу кастомізації.







