180 lines
6.4 KiB
Markdown
180 lines
6.4 KiB
Markdown
|
|
# Fastcheck Backend — изменения сверх api.txt
|
|||
|
|
|
|||
|
|
Документ с **дельтой** — что нужно добавить/изменить в спеке `public/api.txt`,
|
|||
|
|
чтобы фронт полноценно заработал. Базовая спека остаётся в силе, здесь только
|
|||
|
|
правки.
|
|||
|
|
|
|||
|
|
> Полный референс с примерами — см. `BACKEND.md` в этом же репозитории.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. `POST /fastcheck` (создание) — расширить тело
|
|||
|
|
|
|||
|
|
Добавить поля `orderId`, `note`, `returnUrl` (все опциональные):
|
|||
|
|
|
|||
|
|
```diff
|
|||
|
|
POST /fastcheck
|
|||
|
|
HEADER: Authorization: {"sessionID": "..."}
|
|||
|
|
Body:
|
|||
|
|
{
|
|||
|
|
"amount": 158000,
|
|||
|
|
"currency": "RUB",
|
|||
|
|
+ "orderId": "merchant-order-uuid", // id заказа на стороне мерчанта
|
|||
|
|
+ "note": "Оплата заказа №123", // комментарий, видит получатель
|
|||
|
|
+ "returnUrl": "https://shop.example.com/thanks" // куда вернуть юзера после оплаты
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Response:
|
|||
|
|
{
|
|||
|
|
"fastcheck": "1234-5678-0001",
|
|||
|
|
"expiration": "2026-07-07T09:08:18Z",
|
|||
|
|
"code": "5864",
|
|||
|
|
"Status": true,
|
|||
|
|
+ "orderId": "merchant-order-uuid" // эхо обратно
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`note` также возвращать в `GET /fastcheck`, чтобы получатель видел причину
|
|||
|
|
платежа перед приёмом.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1.1. `GET /fastcheck` — добавить `amount` в ответ
|
|||
|
|
|
|||
|
|
Фронт автоматически делает `GET /fastcheck` после ввода полного номера
|
|||
|
|
(`xxxx-xxxx-xxxx`), чтобы показать получателю сумму до ввода кода. Сейчас в
|
|||
|
|
`api.txt` ответ содержит только `fastcheck`, `expiration`, `Status` — суммы нет.
|
|||
|
|
|
|||
|
|
Добавить:
|
|||
|
|
|
|||
|
|
```diff
|
|||
|
|
GET /fastcheck
|
|||
|
|
Body: { "fastcheck": "1234-5678-0001" }
|
|||
|
|
Response:
|
|||
|
|
{
|
|||
|
|
"fastcheck": "1234-5678-0001",
|
|||
|
|
"expiration": "2026-07-07T09:08:18Z",
|
|||
|
|
+ "amount": 158000,
|
|||
|
|
+ "currency": "RUB",
|
|||
|
|
+ "note": "За кофе",
|
|||
|
|
"Status": true
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Также: GET с телом — нестандарт, многие HTTP-клиенты его выкидывают. **Принимать
|
|||
|
|
`?fastcheck=...` как query-параметр** (фронт шлёт оба варианта одновременно).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Зафиксировать единицу `amount`
|
|||
|
|
|
|||
|
|
В `api.txt` пример `"amount": 158000` неоднозначен. Зафиксировать:
|
|||
|
|
|
|||
|
|
> `amount` — **целое число в основной единице валюты** (для RUB — рубли,
|
|||
|
|
> не копейки). Минимум 1.
|
|||
|
|
|
|||
|
|
Если бэкенд считает в копейках — сообщить, фронт изменит формат.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Merchant webhook (новое)
|
|||
|
|
|
|||
|
|
После успешного `POST /fastcheck` (accept), сервер шлёт `POST` на
|
|||
|
|
`webhookUrl`, привязанный к `orderId`/мерчанту:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
POST <merchant_webhook_url>
|
|||
|
|
Headers:
|
|||
|
|
Content-Type: application/json
|
|||
|
|
X-Fastcheck-Signature: <hmac-sha256 от тела с секретом мерчанта>
|
|||
|
|
|
|||
|
|
Body:
|
|||
|
|
{
|
|||
|
|
"event": "fastcheck.paid",
|
|||
|
|
"fastcheck": "1234-5678-0001",
|
|||
|
|
"orderId": "merchant-order-uuid",
|
|||
|
|
"amount": 158000,
|
|||
|
|
"currency": "RUB",
|
|||
|
|
"paidAt": "2026-04-30T12:34:56Z"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Мерчант проверяет подпись и помечает заказ оплаченным. Ретраи (минимум
|
|||
|
|
3 попытки с экспоненциальной задержкой) при не-2xx ответах.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Развести create и accept на разные пути (рекомендация)
|
|||
|
|
|
|||
|
|
Сейчас `POST /fastcheck` делает оба действия — отличается только формой тела
|
|||
|
|
(`amount` vs `code`). Это хрупко.
|
|||
|
|
|
|||
|
|
```diff
|
|||
|
|
- POST /fastcheck (создание)
|
|||
|
|
- POST /fastcheck (приём)
|
|||
|
|
+ POST /fastcheck (создание)
|
|||
|
|
+ POST /fastcheck/accept (приём)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Фронт правится в одну строку. Если оставляете один путь — оставляем как есть.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Гранулярные ошибки `POST /fastcheck` (accept)
|
|||
|
|
|
|||
|
|
В `api.txt` любая ошибка = `404 { "message": "not authorized" }`. Юзер не
|
|||
|
|
понимает, что пошло не так. Различать:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
401 { "message": "not authorized" } — нет/невалидная сессия
|
|||
|
|
404 { "message": "fastcheck not found" } — нет такого номера
|
|||
|
|
403 { "message": "wrong code" } — код неверный
|
|||
|
|
410 { "message": "already used" } — чек уже погашен
|
|||
|
|
410 { "message": "expired" } — просрочен
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. CORS + HTTPS + DNS (блокер)
|
|||
|
|
|
|||
|
|
Сейчас `https://api.fastcheck.store` даёт `ERR_NAME_NOT_RESOLVED` —
|
|||
|
|
домен не резолвится. Без этого тестировать нечего.
|
|||
|
|
|
|||
|
|
Минимально:
|
|||
|
|
- Поднять DNS A-запись на `api.fastcheck.store`.
|
|||
|
|
- Валидный TLS-сертификат (Let's Encrypt подойдёт).
|
|||
|
|
- На все эндпоинты + `OPTIONS` отвечать заголовками:
|
|||
|
|
```
|
|||
|
|
Access-Control-Allow-Origin: https://<домен-фронта>
|
|||
|
|
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS
|
|||
|
|
Access-Control-Allow-Headers: Content-Type, Authorization
|
|||
|
|
Access-Control-Max-Age: 86400
|
|||
|
|
```
|
|||
|
|
`OPTIONS` → `204 No Content` без тела.
|
|||
|
|
|
|||
|
|
Подробности — `BACKEND.md` §1.2.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Что **не меняется**
|
|||
|
|
|
|||
|
|
- `GET /ping`
|
|||
|
|
- `GET /websession`, `GET /websession/:id`, `DELETE /websession/:id`
|
|||
|
|
- `GET /fastcheck`
|
|||
|
|
- Формат заголовка `Authorization: {"sessionID":"..."}`
|
|||
|
|
- Telegram-логин через бот `@DexarSupport_bot` с `?start=<sessionId>`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Чеклист для бэкенда
|
|||
|
|
|
|||
|
|
- [ ] DNS + HTTPS + CORS (блокер)
|
|||
|
|
- [ ] `orderId`, `note`, `returnUrl` в `POST /fastcheck` (create)
|
|||
|
|
- [ ] `note` возвращается в `GET /fastcheck`
|
|||
|
|
- [ ] `amount` (+ currency) возвращается в `GET /fastcheck`
|
|||
|
|
- [ ] `GET /fastcheck` принимает `?fastcheck=` как query-param
|
|||
|
|
- [ ] Зафиксировать `amount` в основной единице (рубли)
|
|||
|
|
- [ ] Webhook на `fastcheck.paid` с HMAC-подписью
|
|||
|
|
- [ ] Гранулярные ошибки accept
|
|||
|
|
- [ ] (опц.) Развести create / accept на разные пути
|