Как работает удалённый платёж: ваш сервер отправляет запрос, xpayment отправляет счёт на телефон покупателя через Kaspi.
Прямой платёж — это платёж по счёту в xpayment. Когда вы вызываете POST /v1/payments, xpayment отправляет счёт в приложение Kaspi покупателя. Покупатель получает push-уведомление на телефон, открывает его и либо оплачивает, либо отклоняет.
Прямые платежи идеальны, когда вы уже знаете номер телефона покупателя:
Перед созданием первого платежа убедитесь, что у вас есть:
xdev_...) для этого устройстваВот что происходит от начала до конца:
POST /v1/payments с телефоном покупателя и суммойPENDINGpayment.completedНа диаграмме ниже показан технический поток между серверами:
Когда вы создаёте платёж через POST /v1/payments, вот что происходит на стороне покупателя:
Покупатель получает push-уведомление на телефон:
Kaspi.kz
Магазин ShopMebel выставил вам счёт на 50 000 ₸
Уведомление появляется мгновенно — даже если телефон заблокирован. Покупатель может нажать на него, чтобы сразу открыть приложение Kaspi.
Когда покупатель открывает уведомление, Kaspi показывает полный экран счёта с:
comment из вашего API-запроса)Если нажимает “Оплатить”:
payment.completedЕсли нажимает “Отклонить счёт”:
payment.cancelledЕсли игнорирует:
payment.expiredМакет ниже показывает, что видит покупатель на своём телефоне:
Отправьте запрос POST /v1/payments с API-ключом вашего устройства:
POST /v1/payments
Authorization: Bearer xdev_live_abc123...
Content-Type: application/json
X-Idempotency-Key: order-12345
{
"payer_phone": "+77001234567",
"amount": 1500.00,
"comment": "Заказ #12345 — Премиум подписка",
"merchant_order_id": "order-12345"
}
Поля запроса:
| Поле | Обязательно | Тип | Описание |
|---|---|---|---|
payer_phone |
Да | string | Номер телефона покупателя, зарегистрированный в Kaspi (формат E.164) |
amount |
Да | number | Сумма платежа в KZT (должна быть > 0) |
comment |
Нет | string | Сообщение, показываемое покупателю в приложении Kaspi (макс. 255 символов) |
merchant_order_id |
Нет | string | Ваш внутренний ID заказа/транзакции |
metadata |
Нет | object | Любой JSON-объект, который вы хотите сохранить (макс. 1КБ) |
Ответ (201 Created):
{
"id": "pay_a1b2c3d4e5f6...",
"status": "PENDING",
"amount": 1500.00,
"currency": "KZT",
"payer_phone": "+77001234567",
"comment": "Заказ #12345 — Премиум подписка",
"merchant_order_id": "order-12345",
"created_at": "2026-04-10T12:00:00Z",
"updated_at": "2026-04-10T12:00:00Z"
}
| Статус | Описание | Можно отменить? |
|---|---|---|
PENDING |
Создан, ожидает подтверждения покупателя в приложении Kaspi | ✅ Да |
COMPLETED |
Покупатель подтвердил, деньги получены на ваш счёт | ❌ Нет (используйте возврат) |
CANCELLED |
Отменён вами или отклонён покупателем | ❌ Нет |
FAILED |
Kaspi отклонил (неверный телефон, недостаточно средств и т.д.) | ❌ Нет |
EXPIRED |
Покупатель не ответил в течение тайм-аута (обычно 24ч) | ❌ Нет |
PENDING → COMPLETED (покупатель подтверждает)
PENDING → CANCELLED (вы отменяете ИЛИ покупатель отклоняет)
PENDING → FAILED (Kaspi отклоняет)
PENDING → EXPIRED (истекает время)
После того как платёж покидает статус PENDING, он неизменяем. Чтобы вернуть завершённый платёж, используйте API возврата.
Пока платёж находится в статусе PENDING, вы можете его отменить:
POST /v1/payments/{paymentId}/cancel
Authorization: Bearer xdev_live_abc123...
Ответ (200 OK):
{
"id": "pay_a1b2c3...",
"status": "CANCELLED",
"amount": 1500.00,
"cancelled_at": "2026-04-10T12:05:00Z"
}
Когда отменять:
| HTTP-статус | Код ошибки | Причина |
|---|---|---|
| 400 | VALIDATION_ERROR |
Отсутствуют или невалидны поля |
| 422 | KASPI_ERROR |
Устройство не зарегистрировано или сессия истекла |
| 409 | DUPLICATE |
Дублирующий merchant_order_id |
| 500 | INTERNAL_ERROR |
Неожиданная ошибка сервера |
Если получаете KASPI_ERROR, возможно истекла сессия устройства. Перерегистрируйте устройство или проверьте статус сессии в личном кабинете.