Skip to main content

Steam Verification

1. Summary

Goal: Валидация Steam-аккаунтов пользователей для защиты от фрода и ботов. Система проверяет подлинность аккаунта через Steam API перед разрешением участия в розыгрышах и вывода предметов.

User Value: Возможность выводить выигранные скины в Steam и участвовать в розыгрышах. Путь: Trade URL → Верификация → Доступ к выводу/раффлам.


2. Business Logic

Verification Types

Доступ: Автоматический при установке Trade URL

Проверки:

  • Профиль публичный (visibility state = 3)
  • Возраст аккаунта ≥ 30 дней
  • Стоимость библиотеки ≥ 1000 RUB
  • Библиотека игр видима

Результат: steamVerified = true, steamVerifiedAt = timestamp

Verification Flow

Protection

ДействиеRate LimitAuthValidation
Установить Trade URLgeneral (100/min)TelegramUpdateTradeUrlSchema
Удалить Trade URLgeneral (100/min)Telegram
Получить статусgeneral (100/min)Telegram
Детали реализации

См. Security Matrix для полного обзора защит.

Anti-Fraud Mechanisms

1. 7-Day Cooldown

Пользователь не может менять Steam-аккаунт чаще, чем раз в 7 дней.

Зачем cooldown?

Предотвращает быструю смену аккаунтов для обхода банов или эксплуатации системы наград.

2. BannedSteamId Auto-Ban

При попытке привязать забаненный Steam ID:

  1. Пользователь автоматически банится
  2. Причина: "Violation of service terms"
  3. Возвращается ошибка VERIFICATION_FAILED (HTTP 403)
Критичная защита

Знание Trade URL забаненного аккаунта = связь с нарушителем. Система трактует это как попытку обхода бана.

3. Active Withdrawal Check

Нельзя изменить Trade URL, если есть активный вывод предмета (статусы PENDING, PROCESSING, SENT).

4. Uniqueness Constraint

Один Steam ID может быть привязан только к одному аккаунту GOLOOT.

Edge Cases

UI поведение:

СитуацияUI поведениеКод ошибки
❌ Неверный формат URLToast "Неверный формат Trade URL"INVALID_TRADE_URL
🔒 Профиль приватныйToast "Сделайте профиль Steam публичным"PROFILE_PRIVATE
🎮 Игры скрытыToast "Откройте библиотеку игр"GAMES_PRIVATE
📅 Аккаунт новыйToast "Аккаунт должен быть старше 30 дней"ACCOUNT_TOO_NEW
💰 Библиотека < 1000₽Toast "Стоимость библиотеки должна быть ≥ 1000₽"LIBRARY_VALUE_TOO_LOW
👤 ID занят другимToast "Этот Steam уже привязан к другому аккаунту"STEAM_ID_TAKEN
⏱️ Cooldown активенToast "Подождите X дней до смены аккаунта"COOLDOWN_ACTIVE
🚫 Забаненный Steam IDBannedScreen (пользователь забанен)VERIFICATION_FAILED
🌐 Steam API недоступенToast "Попробуйте позже"API_ERROR
Backend Error Details
КодHTTPОписание
INVALID_TRADE_URL400Trade URL не распознан (не содержит partner параметр)
PROFILE_PRIVATE400communityvisibilitystate !== 3
GAMES_PRIVATE400getOwnedGames() вернул пустой массив
ACCOUNT_TOO_NEW400daysSince(timecreated) < 30
LIBRARY_VALUE_TOO_LOW400reachedThreshold === false
STEAM_ID_TAKEN400Найден другой User с таким steamId
COOLDOWN_ACTIVE400daysSince(steamIdChangedAt) < 7
VERIFICATION_FAILED403Steam ID в таблице BannedSteamId → auto-ban
API_ERROR500Steam API вернул ошибку или недоступен

3. ADR (Architectural Decisions)

Почему Trade URL, а не Steam OAuth?

Проблема: Нужен способ идентификации Steam-аккаунта и возможность отправлять трейды.

Решение: Пользователь вводит Trade URL из настроек Steam.

Альтернативы (отклонены):

  • Steam OAuth — требует сложной интеграции, не даёт Trade URL
  • Ручной ввод SteamID — пользователи путаются между форматами ID

Последствия: Простота для пользователя (copy-paste), но требует парсинга URL.

Почему 7-дневный cooldown?

Проблема: Пользователи могут быстро переключать аккаунты для обхода ограничений.

Решение: Cooldown 7 дней между сменами Steam-аккаунта.

Альтернативы (отклонены):

  • Без cooldown — слишком просто обойти систему
  • 30 дней — слишком строго для легитимных случаев

Последствия: Баланс между безопасностью и UX.

Почему auto-ban за BannedSteamId?

Критичное решение

Автоматический бан — жёсткая мера, но необходима для борьбы с мультиаккаунтингом.

Проблема: Забаненные пользователи создают новые аккаунты и пытаются привязать тот же Steam.

Решение: Автоматический бан + запись в логи для расследования.

Альтернативы (отклонены):

  • Только предупреждение — неэффективно против злоумышленников
  • Ручная проверка — масштабируется плохо

Последствия: Эффективная защита, но риск false-positive (передача аккаунта/компьютера).


4. Architecture

Services Overview

Key Components

КомпонентПутьОписание
SteamVerificationServicebackend/src/domains/steam-verification/services/steam-verification.service.tsОркестратор верификации
SteamApiClientbackend/src/domains/steam-verification/services/steam-api.client.tsКлиент Steam Web API
Typesbackend/src/domains/steam-verification/types/steam-api.types.tsTypeScript типы
Routesbackend/src/domains/users/routes/profile.routes.ts:209-400API эндпоинты
Schemasbackend/src/domains/users/schemas/profile.schemas.ts:218-268Валидация

5. Database Schema

User Steam Fields

ПолеТипОписание
steamIdString? (unique)SteamID64, извлечён из Trade URL
steamTradeUrlString?Полный Trade URL
steamLinkedAtDateTime?Когда впервые привязан
steamVerifiedBooleanАвтоматическая верификация
steamVerifiedAtDateTime?Когда верифицирован
steamManuallyVerifiedBooleanРучная верификация админом
steamManuallyVerifiedAtDateTime?Когда одобрено
steamAccountCreatedAtDateTime?Дата создания Steam-аккаунта
steamLibraryValueUsdFloat?Стоимость библиотеки
steamGamesCountInt?Количество игр
steamIdChangedAtDateTime?Последняя смена аккаунта (для cooldown)

BannedSteamId Model

ПолеТипОписание
idString (PK)CUID
steamIdString (unique)Забаненный SteamID64
originalUserIdStringID забаненного пользователя
reasonString?Причина бана (до 500 символов)
bannedAtDateTimeКогда забанен
bannedByString?ID админа

Relationships


6. API Endpoints

МетодЭндпоинтОписаниеDocs
PUT/api/users/steam/trade-urlУстановить Trade URL и запустить верификацию
DELETE/api/users/steam/trade-urlУдалить привязку Steam
GET/api/users/verification-statusПолучить статус верификации
Response Examples

PUT /steam/trade-url (Success):

{
"success": true,
"data": {
"steamId": "76561198012345678",
"personaName": "PlayerName",
"profileUrl": "https://steamcommunity.com/id/playername",
"libraryValueUsd": 1500,
"gamesCount": 45,
"isVerified": true
}
}

GET /verification-status:

{
"success": true,
"data": {
"hasVerificationRequest": false,
"status": null,
"isVerified": true,
"canSubmitNew": false,
"lastRequestDate": null,
"adminNote": null
}
}

  • Profile — общие настройки профиля
  • Steam Trade Bot — вывод предметов в Steam
  • Feedback — ручная верификация через тикеты
  • Raffle — требует верификацию для участия
  • Withdraw Readiness — проверка готовности к выводу