Платежи
Платёж — это запрос денег у покупателя через Kaspi. Вы выбираете способ оплаты, Sezgir Pay создаёт операцию в Kaspi, следит за её статусом и сообщает о результате вебхуком.
Типы платежей
| type | Как платит покупатель | Срок жизни | Что вы получаете |
|---|---|---|---|
link | Открывает страницу оплаты и нажимает «Оплатить»: на компьютере видит QR, на телефоне сразу переходит в Kaspi.kz | Задаётся expires_in: от 5 минут до 30 дней, по умолчанию 7 дней | checkout_url |
qr | Сканирует QR с вашего экрана камерой или в приложении Kaspi.kz | Несколько минут — срок QR задаёт Kaspi | provider.qr_url, provider.qr_expires_at |
invoice | Получает счёт в приложении Kaspi.kz по номеру телефона и подтверждает его | 24 часа | Счёт уже у покупателя |
Если не уверены, начните со ссылки: она работает везде, сама выпускает новый QR, если покупатель не успел оплатить, и не требует от вас интерфейса оплаты.
Создание платежа
Все платежи создаются одним запросом POST /payments; поле type выбирает способ. Обязательны только type и amount (и phone для счёта). Полный список параметров — в справочнике.
curl https://pay.sezgir.com/api/v1/payments \
-H "Authorization: Bearer $SEZGIR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9f1c2a4e-7b3d-4e8a-a1f0-5c6d7e8f9a0b" \
-d '{
"type": "link",
"amount": 15000,
"description": "Заказ №1042",
"external_id": "order_1042",
"metadata": { "order_id": 1042, "channel": "web" }
}'amount— целое число тенге от 1 до 50 000 000. Дробные суммы отклоняются с ошибкойvalidation_failed.external_id— ваш идентификатор заказа (до 200 символов). Уникальность не проверяется; по нему можно искать платежи.metadata— до 50 пар «ключ → значение» для ваших нужд. Ключ — до 40 символов, значение — строка до 500 символов, число илиtrue/false. Покупатель метаданные не видит.description— до 500 символов. Показывается покупателю на странице оплаты, а для счёта передаётся в Kaspi как комментарий.
Платёжная ссылка — link
Ссылка не создаёт операцию в Kaspi сразу. Она появляется, когда покупатель открывает checkout_url и нажимает «Оплатить»: Sezgir Pay выпускает QR на несколько минут. Если покупатель не успел, на странице можно получить новый QR — до 20 попыток на одну ссылку. Неудачная попытка не закрывает ссылку: платёж остаётся pending, пока его не оплатят, пока не истечёт expires_in или пока вы его не отмените.
Срок жизни задаётся параметром expires_in в секундах: от 300 (5 минут) до 2592000 (30 дней), по умолчанию — 7 дней. Момент истечения возвращается в поле expires_at.
curl "https://pay.sezgir.com/api/v1/payments" \
-H "Authorization: Bearer $SEZGIR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "type": "link", "amount": 5000, "expires_in": 3600 }'QR-код — qr
Платёж типа qr сразу создаёт операцию в Kaspi. В ответе приходит provider.qr_url — ссылка вида https://pay.kaspi.kz/pay/…. Закодируйте её в QR и покажите на экране, а на телефоне покупателя откройте её напрямую — запустится приложение Kaspi.kz.
curl "https://pay.sezgir.com/api/v1/payments" \
-H "Authorization: Bearer $SEZGIR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "type": "qr", "amount": 2500, "description": "Кофе и круассан" }'{
"id": "pay_8Rt2XvL5nQ1mZ7cK4wB9pJ3s",
"object": "payment",
"livemode": true,
"project_id": "prj_7HcTq2LwZ9mRk4VbN1sXe8Dy",
"type": "qr",
"status": "pending",
"amount": 2500,
"amount_refunded": 0,
"currency": "KZT",
"description": "Кофе и круассан",
"phone": null,
"external_id": "pos-77-1029",
"metadata": {},
"checkout_url": "https://pay.sezgir.com/pay/pay_8Rt2XvL5nQ1mZ7cK4wB9pJ3s",
"provider": {
"name": "kaspi",
"operation_id": "18734512",
"kind": "qr",
"status": "QrTokenCreated",
"qr_url": "https://pay.kaspi.kz/pay/fT9kq2Lx7mWc",
"qr_expires_at": "2026-10-25T10:05:41.000Z"
},
"failure_reason": null,
"requires_review": false,
"expires_at": "2026-10-25T10:06:41.000Z",
"paid_at": null,
"canceled_at": null,
"created_at": "2026-10-25T10:02:41.204Z"
}QR живёт несколько минут; точное время — в provider.qr_expires_at. Поле expires_at платежа чуть позже: после истечения QR Sezgir Pay ещё минуту ждёт подтверждения от Kaspi, на случай если покупатель оплатил в последний момент. Новый QR для того же платежа не выпускается — создайте новый платёж. Если нужен перевыпуск, используйте link и показывайте checkout_url.
expires_in действует только для link; для qr и invoice он вызывает ошибку 400. Номер phone для любого типа проверяется: неверный формат — 400.Счёт по телефону — invoice
Kaspi отправляет счёт в приложение Kaspi.kz покупателя, и тот подтверждает оплату в разделе уведомлений. Нужен номер телефона, к которому привязан Kaspi покупателя. Подойдёт любой казахстанский формат: +7 701 234 56 78, 87012345678, 7012345678, +7 (701) 234-56-78. В ответе номер приводится к виду 77012345678.
curl "https://pay.sezgir.com/api/v1/payments" \
-H "Authorization: Bearer $SEZGIR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "invoice",
"amount": 48900,
"phone": "+7 701 234 56 78",
"description": "Доставка, заказ 5521",
"external_id": "order_5521"
}'{
"id": "pay_4Vb9Kq2Lm7Xc1Zt8Rn5Ws3Pd",
"object": "payment",
"livemode": true,
"project_id": "prj_7HcTq2LwZ9mRk4VbN1sXe8Dy",
"type": "invoice",
"status": "pending",
"amount": 48900,
"amount_refunded": 0,
"currency": "KZT",
"description": "Доставка, заказ 5521",
"phone": "77012345678",
"external_id": "order_5521",
"metadata": {
"courier": "Алматы-3"
},
"checkout_url": "https://pay.sezgir.com/pay/pay_4Vb9Kq2Lm7Xc1Zt8Rn5Ws3Pd",
"provider": {
"name": "kaspi",
"operation_id": "55120934",
"kind": "invoice",
"status": "RemotePaymentCreated",
"qr_url": null,
"qr_expires_at": null
},
"failure_reason": null,
"requires_review": false,
"expires_at": "2026-10-26T11:20:00.000Z",
"paid_at": null,
"canceled_at": null,
"created_at": "2026-10-25T11:20:00.000Z"
}Счёт действует 24 часа. Если по истечении срока он не оплачен, Sezgir Pay отменяет его в Kaspi и закрывает платёж со статусом expired. Без телефона или с неверным номером API вернёт 400 с param: "phone".
Жизненный цикл
Каждый платёж создаётся в статусе pending и переходит в один из итоговых статусов. Каждый переход сопровождается событием.
| status | Что значит | Событие |
|---|---|---|
| pending | Ждём оплату. Для ссылки — покупатель ещё не оплатил ни одну попытку. | payment.created |
| succeeded | Kaspi подтвердил оплату, деньги на счёте кассира. Заполнено paid_at. | payment.succeeded |
| failed | Kaspi отклонил оплату (qr, invoice). Причина — в failure_reason. | payment.failed |
| expired | Срок оплаты истёк, и операция в Kaspi больше не может пройти. | payment.expired |
| canceled | Вы отменили платёж через API или кабинет либо покупатель отказался от оплаты в Kaspi (qr, invoice). | payment.canceled |
| partially_refunded | Часть суммы возвращена; amount_refunded < amount. | payment.refunded |
| refunded | Сумма возвращена полностью. | payment.refunded |
Отклонённая попытка оплаты по ссылке не переводит её в failed — ссылка остаётся открытой, а причина последней неудачи видна в failure_reason. Если Kaspi отказал уже при создании qr или invoice, API отвечает ошибкой, платёж сохраняется в статусе failed для истории, а вебхуков по нему не будет.
Поздняя оплата
Деньги, которые подтвердил Kaspi, — главный источник истины. Если подтверждение пришло после того, как платёж был закрыт как expired, canceled или failed, платёж переходит в succeeded и вы получаете payment.succeeded.
Так бывает, например, когда:
- вы отменили QR-платёж, а покупатель уже отсканировал код — отозвать выданный QR в Kaspi нельзя, поэтому Sezgir Pay следит за ним до конца;
- покупатель оплатил в последние секунды, и ответ Kaspi пришёл после истечения срока;
- Kaspi временно не отвечал, а позже подтвердил оплату.
Что делать на своей стороне:
- Не удаляйте заказ и не считайте его окончательно отменённым только по
payment.expiredилиpayment.canceled. - Обрабатывайте
payment.succeededдля любого заказа: если товар уже недоступен, сделайте возврат. - Не создавайте новый платёж для заказа, пока старый в статусе pending, — иначе покупатель может оплатить оба.
Флаг requires_review
Иногда Kaspi не отвечает в момент, когда деньги могут двигаться. Тогда Sezgir Pay не делает вид, что знает результат, а ставит платежу requires_review: true и пишет пояснение в failure_reason:
- Счёт выставлен, но Kaspi не ответил. Счёт мог дойти до покупателя, поэтому платёж создаётся (
201) и остаётся pending — не выставляйте второй счёт. - Срок истёк, но Kaspi сутки не подтверждал статус. Платёж закрывается как expired с флагом.
Администратор сверяет операцию в Kaspi Pay и снимает флаг в кабинете. Если оплата всё-таки прошла, вы получите payment.succeeded как обычно.
Страница оплаты
У каждого платежа любого типа есть checkout_url — страница Sezgir Pay вида https://pay.sezgir.com/pay/pay_…. На ней покупатель видит название и иконку сервиса, сумму и описание, а также:
| type | Что показывает страница |
|---|---|
link | Кнопку «Оплатить». На компьютере — QR для сканирования, на телефоне — кнопку «Открыть в Kaspi.kz» и таймер QR. Если QR истёк, можно получить новый. |
qr | Тот же QR, что в provider.qr_url, и кнопку «Открыть в Kaspi.kz». |
invoice | Маскированный номер, на который отправлен счёт, и подсказку, где его найти в Kaspi.kz. |
- Страница сама обновляет статус каждые несколько секунд и показывает результат: «Оплата прошла», «Время оплаты истекло», «Платёж отменён».
- Метаданные,
external_idи идентификаторы ваших объектов покупателю не показываются; номер телефона маскируется. - Тестовые платежи помечены плашкой «Тест» и содержат кнопки симуляции «Оплатить» и «Отклонить».
- Возврата покупателя на ваш сайт после оплаты нет. Узнавайте о результате по вебхуку и показывайте покупателю статус заказа на своей стороне.
Отмена
Отменить можно только платёж в статусе pending: POST /payments/:id/cancel. Для счёта Sezgir Pay отменяет его в Kaspi, и покупатель больше не сможет его оплатить. Для уже выданного QR отмена в Kaspi невозможна — платёж становится canceled, но если покупатель всё же оплатит этот QR, вы получите payment.succeeded.
curl -X POST "https://pay.sezgir.com/api/v1/payments/pay_2Nf8kQ1xYbV7cR4tLm9Pa3Ws/cancel" \
-H "Authorization: Bearer $SEZGIR_API_KEY"Повторная отмена или отмена завершённого платежа вернёт 409 с кодом payment_not_pending. Если Kaspi недоступен в момент отмены счёта — 503 provider_unavailable, платёж остаётся pending; повторите запрос позже.
Поиск и сверка
GET /payments/:id возвращает актуальное состояние платежа, GET /payments — список с фильтрами status, type и external_id, от новых к старым.
curl "https://pay.sezgir.com/api/v1/payments?external_id=order_1042" \
-H "Authorization: Bearer $SEZGIR_API_KEY"{
"object": "list",
"data": [
{
"id": "pay_2Nf8kQ1xYbV7cR4tLm9Pa3Ws",
"object": "payment",
"livemode": false,
"project_id": "prj_7HcTq2LwZ9mRk4VbN1sXe8Dy",
"type": "link",
"status": "succeeded",
"amount": 15000,
"amount_refunded": 0,
"currency": "KZT",
"description": "Заказ №1042",
"phone": null,
"external_id": "order_1042",
"metadata": {
"order_id": 1042,
"channel": "web"
},
"checkout_url": "https://pay.sezgir.com/pay/pay_2Nf8kQ1xYbV7cR4tLm9Pa3Ws",
"provider": {
"name": "test",
"operation_id": null,
"kind": null,
"status": null,
"qr_url": null,
"qr_expires_at": null
},
"failure_reason": null,
"requires_review": false,
"expires_at": "2026-11-01T09:14:03.512Z",
"paid_at": "2026-10-25T09:16:47.020Z",
"canceled_at": null,
"created_at": "2026-10-25T09:14:03.512Z"
}
],
"has_more": false
}Не опрашивайте статус в цикле — дождитесь вебхука. Для периодической сверки используйте GET /events: события упорядочены по времени и не теряются, даже если ваш сервер был недоступен. Подробнее о пагинации — в справочнике. Базовый URL всех запросов — https://pay.sezgir.com/api/v1.