9.6 KiB
Fastcheck Backend — требования к серверу
Документ для команды бэкенда. Описывает, что должен реализовать сервер api.fastcheck.store, чтобы веб-фронт (этот репозиторий) полностью заработал.
1. Общие требования
1.1 Транспорт
- Протокол: HTTPS обязателен (валидный TLS-сертификат, Let's Encrypt или иной).
- Хост:
api.fastcheck.store(или другой — тогда поправитьFASTCHECK_APIвsrc/app/api.ts). - Формат тел запроса/ответа:
application/json; charset=utf-8.
1.2 CORS — критично
Браузер фронта пойдёт с другого origin. Без правильных CORS-заголовков ничего не заработает (preflight упадёт, fetch вернёт network error — ровно то, что мы видим сейчас).
Сервер должен на любой OPTIONS (preflight) и на ответы реальных запросов отдавать:
Access-Control-Allow-Origin: https://<домен-фронта> # либо * для dev
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Если используются cookies/credentials — добавить Access-Control-Allow-Credentials: true и нельзя использовать * в Allow-Origin.
OPTIONS должен отвечать 204 No Content без тела.
1.3 Авторизация
Заголовок передаётся как JSON-строка, а не Bearer:
Authorization: {"sessionID":"1AF3781BF6B94604B771AEA1D44FA63A"}
Парсинг на сервере: JSON.parse(req.headers.authorization) → { sessionID }.
Если заголовок отсутствует или сессия невалидна — 404 { "message": "not authorized" }.
1.4 Ошибки
Любая ошибка — JSON { "message": "<человекочитаемое описание>" } + HTTP-статус (4xx/5xx). Фронт показывает message пользователю.
2. Эндпоинты
База: https://api.fastcheck.store
2.1 GET /ping
Healthcheck. Ответ: 200 { "message": "pong" }. Без авторизации.
2.2 GET /websession
Создаёт новую веб-сессию для QR-логина через Telegram-бот.
Запрос: без тела, без авторизации.
Ответ 200:
{
"sessionId": "1AF3781BF6B94604B771AEA1D44FA63A",
"userId": "",
"expires": "sessionId",
"userSessionId": "",
"Status": false
}
sessionId фронт подставляет в QR-код и в deeplink на бот:
https://t.me/DexarSupport_bot?start=<sessionId>
TTL сессии: рекомендуем 5–10 минут. По истечении GET /websession/:id должен вернуть Status: false навсегда (фронт сам пересоздаст).
2.3 GET /websession/:webSessionID
Поллинг статуса логина. Фронт зовёт каждые 3 секунды, пока попап открыт.
Ответ 200 пока пользователь не залогинился:
{ "sessionId": "...", "userId": "", "expires": "sessionId", "userSessionId": "", "Status": false }
Ответ 200 после того, как Telegram-бот подтвердил вход:
{
"sessionId": "1AF3781BF6B94604B771AEA1D44FA63A",
"userId": "kHaAe9roaC2uq63AKGE/8+Ti/t/iFro68QhEZ1dRGLo",
"expires": "sessionId",
"userSessionId": "8A94EFEFD003426A9B456C48CAC99BE6",
"Status": true
}
Если сессия не найдена/истекла — 404 { "message": "session expired" }.
2.4 DELETE /websession/:webSessionID
Logout / закрытие попапа.
Запрос:
{ "sessionId": "1AF3781BF6B94604B771AEA1D44FA63A" }
Ответ 200 {}. Идемпотентно — повторный вызов не должен ломаться.
2.5 GET /fastcheck
Проверка существования и срока действия чека (используется опционально перед оплатой).
Запрос (тело в GET):
{ "fastcheck": "1234-5678-0001" }
Ответ 200:
{
"fastcheck": "1234-5678-0001",
"expiration": "2026-07-07T09:08:18Z",
"Status": true
}
Не существует / просрочен → 404 { "message": "not found" }.
2.6 POST /fastcheck — создание чека
Юзер уже залогинен, его sessionID есть на фронте. С этого аккаунта списывается amount, выпускается чек.
Заголовок: Authorization: {"sessionID":"..."} обязателен.
Тело:
{ "amount": 158000, "currency": "RUB" }
amount — в минимальных единицах валюты (копейки для RUB). Уточнить с фронтом, если иначе.
Ответ 200:
{
"fastcheck": "1234-5678-0001",
"expiration": "2026-07-07T09:08:18Z",
"code": "5864",
"Status": true
}
Ошибки:
404 { "message": "not authorized" }— нет/невалидная сессия.400 { "message": "insufficient balance" }— мало средств.400 { "message": "invalid amount" }— некорректная сумма/валюта.
2.7 POST /fastcheck — приём чека (оплата)
Этот же путь, отличается шейпом тела (без amount, с code).
Заголовок: Authorization: {"sessionID":"..."} обязателен (сессия получателя — того, кто оплачивает).
Тело:
{ "fastcheck": "1234-5678-0001", "code": "5864" }
Ответ 200 { "message": "ok" } — чек погашен, средства зачислены получателю.
Ошибки:
404 { "message": "not authorized" }— сессия невалидна или код неверный, или чек уже использован, или просрочен. (Так в текущей доке. Если можно различать — лучше отдельные сообщения.)
⚠️ Серверу важно различать два POST-кейса по наличию поля
amountvscodeв теле. Альтернатива (предпочтительнее на проде) — развести на разные пути:POST /fastcheck(создание) иPOST /fastcheck/accept(приём). Если разведёте — скажите, фронт правится за 5 минут.
3. Интеграция с Telegram-ботом
Фронт сам бот не дёргает — это задача бэкенда.
- Юзер сканит QR / кликает deeplink → попадает в бот
@DexarSupport_botс параметром?start=<sessionId>. - Бот идентифицирует Telegram-аккаунт (по
from.id) → находит/создаётuserId→ биндит его кsessionId→ ставитStatus: true, заполняетuserIdиuserSessionId. - Следующий поллинг с фронта вернёт
Status: true— фронт переходит кPOST /fastcheck.
Если юзер впервые в боте — стандартный onboarding, потом всё то же самое.
4. Чеклист «готово к проду»
- HTTPS с валидным сертификатом на
api.fastcheck.store. - CORS разрешает домен фронта на всех 6 эндпоинтах + OPTIONS.
GET /pingотвечает.- Полный цикл:
GET /websession→ бот ставитStatus:true→GET /websession/:idэто видит. POST /fastcheck(create) с заголовкомAuthorizationсоздаёт чек, списывает баланс.POST /fastcheck(accept) погашает чек только один раз, зачисляет получателю.DELETE /websession/:idкорректно завершает сессию.- Все ошибки в формате
{ "message": "..." }+ правильный HTTP-код. - Сессии экспайрятся (5–10 мин для websession, разумный TTL для userSession).
- Rate-limit на
GET /websession/:id(фронт поллит каждые 3 с) и наPOST /fastcheck.
5. Открытые вопросы (нужны ответы от бэкенда)
- Единица
amount: рубли или копейки? - Currency: какие коды поддерживаете кроме
RUB? (фронт уже умеет показывать, но шлёт пока только RUB) - Merchant callback для эквайринга: после успешного
POST /fastcheck (accept)нужно ли серверу самому пинговать мерчант-вебхук, или это полностью на фронте через?return_url=? - Различение ошибок accept: можно ли вместо общего
404 not authorizedотдаватьnot found/wrong code/already used/expired? - WebSession TTL — сколько живёт?