hochu-sdelat-mini-servis-po/README.md

150 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Kaspi POS Automation
Автоматизация платежей для POS-систем через Kaspi Pay API. Проект предоставляет серверное приложение и веб-интерфейс для создания счетов, генерации QR-кодов, просмотра истории транзакций и оформления возвратов.
## Архитектура
```
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Web UI │◄─────►│ Express Server │◄─────►│ Kaspi Pay API │
│ (public/) │ │ (server.js) │ │ (entrance/ │
│ │ │ │ │ mtoken/qrpay) │
└──────────────┘ └──────────────────┘ └──────────────────┘
┌─────────┴─────────┐
│ src/ │
│ ├─ config.js │ Keypair, device, constants
│ ├─ crypto.js │ ECDH, ECDSA, TOTP, AES
│ ├─ helpers.js │ Fetch wrapper, headers
│ ├─ session.js │ Stateless session factory
│ ├─ logger.js │ File & console logging
│ ├─ polling.js │ Payment status polling
│ ├─ webhookStore │ Webhook management
│ └─ routes/ │ API route handlers
│ ├─ auth.js │ SMS auth (3-step)
│ ├─ invoice.js │ Invoice creation
│ ├─ qr.js │ QR code generation
│ ├─ history.js │ Transaction history
│ ├─ refund.js │ Refund processing
│ └─ session.js │ Session management
└───────────────────┘
```
Сервер **stateless после авторизации** — данные сессии (зашифрованный `vtokenSecret`, `tokenSN`, `profileId`) хранятся на стороне клиента и передаются через заголовки.
### Webhooks
Сервер автоматически отслеживает статусы созданных QR- и invoice-платежей (polling каждые 3 сек.) и отправляет HTTP POST-уведомления на указанные URL при изменении статуса.
- 📡 **События:** `payment.success` · `payment.failed` · `payment.expired`
- ⚙️ **Настройка:** файл `webhooks.json` (см. [`webhooks.example.json`](./webhooks.example.json))
- 🔐 **Подпись:** HMAC SHA-256
- 🔄 **Retry:** до 3 попыток с нарастающей задержкой
> 📖 Подробнее — в [документации API](./docs/API.md#webhooks--уведомления).
## Требования
- Node.js ≥ 20.6
## Быстрый старт
```bash
# 1. Клонировать репозиторий
git clone https://github.com/tapter-dev/kaspi-pos-automation.git
cd kaspi-pos-automation
# 2. Установить зависимости
npm install
# 3. Создать .env с ключом шифрования
echo "TOKEN_SECRET_KEY=$(openssl rand -hex 32)" > .env
# 4. (Опционально) Настроить вебхуки
cp webhooks.example.json webhooks.json
# Отредактируйте webhooks.json под свои нужды
# 5. Запустить сервер
npm start
```
При первом запуске автоматически генерируются `keypair.json` и `device.json`.
## Переменные окружения
| Переменная | Описание | По умолчанию | Обязательная |
| ------------------ | ---------------------------------------- | -------------------------- | ------------ |
| `TOKEN_SECRET_KEY` | 64-символьная hex-строка для AES-256-GCM | — | Да |
| `PORT` | Порт сервера | `3000` | Нет |
| `APP_VERSION` | Версия приложения Kaspi Pay | `4.110.1` | Нет |
| `APP_BUILD` | Номер сборки | `1099` | Нет |
| `APP_PLATFORM` | Платформа устройства | `iOS` | Нет |
| `APP_PLATFORM_VER` | Версия ОС | `18.5` | Нет |
| `APP_LOCALE` | Локаль | `ru-RU` | Нет |
| `APP_MODEL` | Модель устройства | `iPhone17,3` | Нет |
| `APP_BRAND` | Бренд устройства | `Apple` | Нет |
| `APP_DEVICE_NAME` | Имя устройства | `iPhone` | Нет |
| `APP_SCREEN_W` | Ширина экрана | `393.0` | Нет |
| `APP_SCREEN_H` | Высота экрана | `852.0` | Нет |
| `APP_CFNETWORK` | Версия CFNetwork | `CFNetwork/3826.500.131` | Нет |
| `APP_DARWIN` | Версия Darwin | `Darwin/24.5.0` | Нет |
> ⚠️ Параметры `APP_*` соответствуют реальному клиенту Kaspi Pay. API Kaspi валидирует эти значения и может отклонить запросы с неизвестными параметрами. Обновляйте их при выходе новой версии приложения.
## Ротация ключей
```bash
npm run regen:keypair # Перегенерация ECDSA-ключей
npm run regen:device # Перегенерация идентификатора устройства
```
Старые файлы сохраняются как `.bak`. После ротации существующие сессии становятся недействительными.
## Демо-интерфейс (`public/`)
В папке `public/` находится встроенный веб-интерфейс (SPA), который запускается автоматически вместе с сервером и доступен по адресу `http://localhost:3000`.
**Возможности интерфейса:**
- 🔐 **Авторизация** — вход по номеру телефона кассира Kaspi Pay через 3-шаговый SMS-flow (ввод номера → OTP-код → завершение)
- 🧾 **Выставление счёта** — создание счёта по номеру телефона клиента с указанием суммы и комментария
- 📱 **QR-оплата** — генерация QR-кода для оплаты с отслеживанием статуса в реальном времени
- 📋 **История операций** — просмотр списка транзакций с детализацией
- 💰 **Продажи и возвраты** — статистика продаж и оформление возвратов
**Файлы:**
| Файл | Описание |
| --- | --- |
| `public/index.html` | HTML-разметка и стили интерфейса |
| `public/app.js` | Клиентская логика (API-вызовы, управление состоянием) |
> Интерфейс предназначен для демонстрации и тестирования API. Для продакшена рекомендуется использовать собственный фронтенд.
## API документация
Подробная документация по всем эндпоинтам API: [`docs/API.md`](./docs/API.md).
📗 Документация также доступна на казахском языке: [`README.kk.md`](./README.kk.md) | [`docs/API.kk.md`](./docs/API.kk.md)
## Разработка
```bash
# Линтинг
npm run lint
# Форматирование
npm run format
# Тесты
npm test
```
## Лицензия
Этот проект распространяется под лицензией [MIT](./LICENSE).
## Участие в проекте
Мы приветствуем вклад сообщества! Пожалуйста, ознакомьтесь с [CONTRIBUTING.md](./CONTRIBUTING.md) перед созданием pull request.