21 KiB
📖 API Documentation
Kaspi POS Automation предоставляет REST API для работы с платежами Kaspi Pay: авторизация по SMS, выставление счетов, QR-оплата, история операций и возвраты.
Base URL: http://localhost:3000
Содержание
- Аутентификация
- Health Check
- Auth — Авторизация
- Invoice — Счета
- QR — QR-оплата
- History — История операций
- Refund — Возвраты
- Session — Проверка сессии
- Webhooks — Уведомления
Аутентификация
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.json→webhooks.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 → возврат средств (при необходимости)