hochu-sdelat-mini-servis-po/docs/API.md

21 KiB
Raw Blame History

📖 API Documentation

Kaspi POS Automation предоставляет REST API для работы с платежами Kaspi Pay: авторизация по SMS, выставление счетов, QR-оплата, история операций и возвраты.

Base URL: http://localhost:3000


Содержание


Аутентификация

API использует 3-шаговую SMS-авторизацию. После успешной авторизации клиент получает tokenSN и vtokenSecret, которые передаются в заголовках для всех защищённых эндпоинтов.

Заголовки сессии

Все эндпоинты кроме /api/auth/* и /health требуют следующие заголовки:

Заголовок Тип Обязательный Описание
X-Token-SN string Токен сессии, полученный при авторизации
X-Vtoken-Secret string Зашифрованный секрет сессии
X-Profile-Id string ID профиля организации

Health Check

GET /health

Проверка работоспособности сервера.

Ответ:

{ "status": "ok" }

Auth — Авторизация

Трёхшаговый процесс авторизации через SMS-код Kaspi.

⚠️ Важно: Для входа используйте номер телефона аккаунта кассира Kaspi Pay.

POST /api/auth/init

Инициализация процесса авторизации. Возвращает processId для последующих шагов.

Тело запроса: не требуется

Пример запроса:

curl -X POST http://localhost:3000/api/auth/init

Успешный ответ:

{
  "success": true,
  "processId": "abc123-...",
  "view": "EnterPhoneNumber",
  "body": { ... }
}

POST /api/auth/send-phone

Отправка номера телефона — инициирует отправку SMS-кода.

Тело запроса:

Поле Тип Обязательный Описание
phoneNumber string Номер телефона (формат: 7XXXXXXXXXX)
processId string ID процесса из /api/auth/init

Пример запроса:

curl -X POST http://localhost:3000/api/auth/send-phone \
  -H "Content-Type: application/json" \
  -d '{"phoneNumber": "77001234567", "processId": "abc123-..."}'

Успешный ответ:

{
  "success": true,
  "processId": "abc123-...",
  "desc": "Код отправлен на номер +7 700 *** ** 67",
  "view": "EnterOtp",
  "body": { ... }
}

POST /api/auth/verify-otp

Подтверждение SMS-кода. При успехе автоматически завершает авторизацию и возвращает данные сессии.

Тело запроса:

Поле Тип Обязательный Описание
otp string SMS-код
processId string ID процесса из /api/auth/init

Пример запроса:

curl -X POST http://localhost:3000/api/auth/verify-otp \
  -H "Content-Type: application/json" \
  -d '{"otp": "1234", "processId": "abc123-..."}'

Успешный ответ:

{
  "success": true,
  "processId": "abc123-...",
  "step": "finished",
  "message": "OTP verified and finish completed",
  "tokenSN": "TOKEN_SN_VALUE",
  "vtokenSecret": "ENCRYPTED_SECRET",
  "profileId": 12345,
  "organizationId": 67890,
  "orgName": "ИП Иванов",
  "phone": "77001234567",
  "organizations": [ ... ]
}

⚠️ Сохраните tokenSN и vtokenSecret — они нужны для всех последующих запросов.


POST /api/auth/session

Проверка наличия токена (клиентская проверка).

Тело запроса:

Поле Тип Обязательный Описание
tokenSN string Токен сессии

Ответ:

{
  "authenticated": true,
  "tokenSN": "TOKEN_SN_VALUE"
}

POST /api/auth/logout

Завершение сессии.

Тело запроса: не требуется

Ответ:

{ "success": true }

Invoice — Счета

Выставление счетов на оплату по номеру телефона клиента.

🔒 Все эндпоинты требуют заголовки сессии.

GET /api/invoice/client-info

Получение информации о клиенте по номеру телефона.

Query-параметры:

Параметр Тип Обязательный Описание
phoneNumber string Номер телефона клиента

Пример запроса:

curl "http://localhost:3000/api/invoice/client-info?phoneNumber=77001234567" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -H "X-Profile-Id: ..."

POST /api/invoice/create

Создание счёта на оплату.

Тело запроса:

Поле Тип Обязательный Описание
phoneNumber string Номер телефона клиента
amount number Сумма в тенге
comment string Комментарий к платежу

Пример запроса:

curl -X POST http://localhost:3000/api/invoice/create \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -H "X-Profile-Id: ..." \
  -d '{"phoneNumber": "77001234567", "amount": 1000, "comment": "Оплата заказа #42"}'

Успешный ответ:

{
  "StatusCode": 0,
  "Data": {
    "Id": 123456,
    "Status": "RemotePaymentCreated",
    "Amount": 1000,
    "ClientMobile": "77001234567",
    "ReceiptUrl": "https://...",
    "OrderNumber": "..."
  }
}

GET /api/invoice/details

Получение деталей счёта.

Query-параметры:

Параметр Тип Обязательный Описание
operationId string ID операции

Пример запроса:

curl "http://localhost:3000/api/invoice/details?operationId=123456" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..."

POST /api/invoice/cancel

Отмена выставленного счёта.

Тело запроса:

Поле Тип Обязательный Описание
operationId string ID операции для отмены

Пример запроса:

curl -X POST http://localhost:3000/api/invoice/cancel \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -d '{"operationId": "123456"}'

POST /api/invoice/history

Получение истории выставленных счетов (последние 20).

Тело запроса: не требуется (пустой JSON {})

Пример запроса:

curl -X POST http://localhost:3000/api/invoice/history \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -d '{}'

QR — QR-оплата

Генерация QR-кодов для оплаты через Kaspi Pay.

🔒 Все эндпоинты требуют заголовки сессии.

POST /api/qr/create

Создание QR-токена для оплаты.

Тело запроса:

Поле Тип Обязательный Описание
amount number Сумма в тенге
latitude number Широта (по умолчанию: Алматы)
longitude number Долгота (по умолчанию: Алматы)

Пример запроса:

curl -X POST http://localhost:3000/api/qr/create \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -H "X-Profile-Id: ..." \
  -d '{"amount": 500}'

Успешный ответ:

{
  "StatusCode": 0,
  "Data": {
    "QrOperationId": 789012,
    "QrToken": "https://pay.kaspi.kz/pay/...",
    "ExpireDate": "2025-01-01T12:05:00",
    "Amount": 500,
    "ReceiptUrl": "https://..."
  }
}

💡 QrToken содержит ссылку для оплаты — можно преобразовать в QR-код.


GET /api/qr/status

Проверка статуса QR-платежа.

Query-параметры:

Параметр Тип Обязательный Описание
qrOperationId string ID QR-операции из /api/qr/create

Пример запроса:

curl "http://localhost:3000/api/qr/status?qrOperationId=789012" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..."

History — История операций

Просмотр истории всех операций (QR + счета).

🔒 Все эндпоинты требуют заголовки сессии.

POST /api/history/operations

Получение списка операций за период.

Тело запроса:

Поле Тип Обязательный Описание
endDate string Конечная дата (формат: YYYY-MM-DD)
lastTransactionDate string Дата последней транзакции (для пагинации)
statementPeriodCode number Код периода (по умолчанию: 0)

Пример запроса:

curl -X POST http://localhost:3000/api/history/operations \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -d '{"endDate": "2025-01-15"}'

POST /api/history/details

Получение деталей конкретной операции.

Тело запроса:

Поле Тип Обязательный Описание
id number ID операции
operationMethod number Метод операции (по умолчанию: 0)

Пример запроса:

curl -X POST http://localhost:3000/api/history/details \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -d '{"id": 123456}'

Refund — Возвраты

Возврат средств по ранее проведённой операции.

🔒 Все эндпоинты требуют заголовки сессии.

POST /api/refund/create

Создание возврата.

Тело запроса:

Поле Тип Обязательный Описание
qrOperationId number ID операции для возврата
returnAmount number Сумма возврата в тенге

Пример запроса:

curl -X POST http://localhost:3000/api/refund/create \
  -H "Content-Type: application/json" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..." \
  -d '{"qrOperationId": 789012, "returnAmount": 500}'

Session — Проверка сессии

GET /api/session/check

Проверка валидности текущей сессии через запрос к Kaspi API.

🔒 Требует заголовки сессии.

Пример запроса:

curl "http://localhost:3000/api/session/check" \
  -H "X-Token-SN: ..." \
  -H "X-Vtoken-Secret: ..."

Активная сессия:

{ "active": true }

Неактивная сессия:

{
  "active": false,
  "error": "Session rejected by Kaspi API.",
  "code": 401,
  "details": { ... }
}

Коды ошибок

Все эндпоинты возвращают ошибки в формате:

{ "error": "Описание ошибки" }
HTTP-код Описание
400 Отсутствуют обязательные параметры
401 Отсутствуют или невалидные заголовки сессии
500 Внутренняя ошибка сервера или ошибка Kaspi API

Webhooks — Уведомления

Система автоматически отслеживает статусы созданных QR- и invoice-платежей (polling каждые 3 секунды) и отправляет HTTP POST-уведомления (webhooks) на указанные URL при изменении статуса платежа.

Настройка

Вебхуки настраиваются в файле webhooks.json в корне проекта. Файл содержит массив объектов:

[
  {
    "url": "https://example.com/webhook",
    "events": ["payment.success", "payment.failed", "payment.expired"],
    "secret": "your-webhook-secret"
  }
]
Поле Тип Обязательный Описание
url string URL, на который будут отправляться уведомления
events string[] Список событий для подписки
secret string Секрет для HMAC-подписи (рекомендуется)

💡 Для начала скопируйте webhooks.example.jsonwebhooks.json и отредактируйте.

Можно указать несколько вебхуков с разными URL и событиями:

[
  {
    "url": "https://my-crm.com/kaspi-hook",
    "events": ["payment.success"],
    "secret": "crm-secret-key"
  },
  {
    "url": "https://my-accounting.com/hook",
    "events": ["payment.success", "payment.failed", "payment.expired"],
    "secret": "accounting-secret"
  }
]

События

Событие Описание Когда срабатывает
payment.success Платёж успешно проведён QR: статус Processed; Invoice: статус Processed
payment.failed Платёж отклонён / отменён QR: CancelledByUser, Rejected, Error и др.; Invoice: RemotePaymentCanceled, RemotePaymentRejected
payment.expired Время оплаты истекло QR: QrTokenDiscarded, Expired; Invoice: Expired

Формат payload

При срабатывании события на каждый подписанный URL отправляется POST-запрос с JSON-телом:

{
  "event": "payment.success",
  "paymentId": "123456",
  "type": "qr",
  "status": "Processed",
  "statusDesc": "Операция проведена успешно",
  "amount": 5000,
  "qrToken": "QR-TOKEN-...",
  "receiptUrl": "https://...",
  "orderNumber": "ORDER-001",
  "data": { ... },
  "timestamp": "2026-05-10T00:00:00.000Z"
}
Поле Тип Описание
event string Название события (payment.success, payment.failed, payment.expired)
paymentId string ID платежа (QR operationId или invoice operationId)
type string Тип платежа: qr или invoice
status string Финальный статус от Kaspi API
statusDesc string Описание статуса
amount number|null Сумма платежа в тенге
qrToken string|null QR-токен (только для QR-платежей)
receiptUrl string|null Ссылка на чек
orderNumber string|null Номер заказа
data object Полные данные ответа от Kaspi API
timestamp string Время отправки уведомления (ISO 8601)

Подпись (HMAC)

Каждый запрос подписывается HMAC SHA-256 с использованием secret из конфигурации вебхука. Подпись передаётся в заголовке:

X-Webhook-Signature: sha256=<hex-digest>

Проверка подписи на стороне получателя (Node.js):

import crypto from 'crypto';

const verifySignature = (body, signature, secret) => {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
};

// В обработчике запроса:
const rawBody = JSON.stringify(req.body); // или используйте raw body
const sig = req.headers['x-webhook-signature'];
if (!verifySignature(rawBody, sig, 'your-webhook-secret')) {
  return res.status(401).send('Invalid signature');
}

Повторные попытки (Retry)

Если доставка вебхука не удалась (ошибка сети, таймаут, HTTP-ошибка), система выполняет до 3 попыток с нарастающей задержкой:

Попытка Задержка
1-я (первая) Немедленно
2-я 5 секунд
3-я 30 секунд
  • Таймаут запроса: 10 секунд.
  • Очередь повторных попыток сохраняется в webhook-retries.json и переживает перезапуск сервера.
  • После 3 неудачных попыток уведомление отбрасывается (логируется ошибка).

Типичный сценарий использования

1. POST /api/auth/init              → получить processId
2. POST /api/auth/send-phone        → отправить SMS
3. POST /api/auth/verify-otp        → подтвердить код → получить tokenSN + vtokenSecret

4. POST /api/qr/create              → создать QR для оплаты
5. GET  /api/qr/status              → проверить статус оплаты

   — или —

4. POST /api/invoice/create         → выставить счёт по номеру телефона
5. GET  /api/invoice/details        → проверить статус счёта

6. POST /api/refund/create          → возврат средств (при необходимости)