Қысқаша
Sandbox-та нақты Kaspi жоқ, сондықтан клиенттің төлеуін өзіңіз симуляциялайсыз:
POST /api/v1/invoices/{id}/simulate
{ "status": "paid" }
Осыдан кейін счёт нағыз төлемдегідей жүреді: күйі өзгереді, чек нөмірі беріледі, оқиғалар журналға жазылады және webhook нақты жағдайдағыдай жіберіледі. Интеграцияңызды толық циклмен, бір тиын тәуекелсіз тексеруге болады.
Бұл әдіс тек sandbox-та істейді. Live режимде not_sandbox (HTTP 403) қатесі келеді.
Қандай күйлерге ауыстыруға болады
status | Не болады |
|---|---|
paid | Счёт төленген болып белгіленеді, чек нөмірі беріледі, invoice.paid жіберіледі |
failed | Төлем өтпеген болып жабылады, invoice.failed жіберіледі |
expired | Мерзімі өткен болып жабылады, invoice.expired жіберіледі |
Басқа мән берсеңіз, invalid_status (HTTP 422) келеді.
Ауыстыру тек ашық счётқа қолданылады (new, pending). Жабылған счётқа тағы симуляция жасасаңыз, invoice_not_open (HTTP 409) келеді.
Бір ғана ерекшелік бар: cancelled немесе expired күйдегі счётқа paid симуляциясын жасауға болады. Бұл — кеш төлемді әдейі жаңғырту: счёт жабылып қалған, ал ақша кейін келген жағдай. Ондайда оқиға late: true белгісімен келеді, дәл продакшендегідей. Өңдеуіңіз бұл жағдайды дұрыс қарсы алатынын осылай тексересіз: Кеш келген төлем.
Не керек
- Ұйым sandbox режимінде тұруы керек (кабинеттен ауыстырасыз);
- кілт
qp_test_…болуы керек; - кілтте
invoices:writeқұқығы болуы керек.
Sandbox-та Kaspi кассирі керек емес: Sandbox пен нақты режимнің айырмашылығы.
Kaspi мүлде шақырылмайды. Ешқандай SMS, ешқандай нақты QR, ешқандай ақша қозғалысы жоқ. Sandbox счёттары тарифтің айлық лимитіне де кірмейді және сынақ мерзімін бастамайды.
Қолмен жүргізу
Үш жол бар, үшеуі де бірдей нәтиже береді.
API арқылы:
curl -X POST https://api.qut.kz/api/v1/invoices/inv_…/simulate \
-H 'X-API-Key: qp_test_…' \
-H 'Content-Type: application/json' \
-d '{"status":"paid"}'
Жауап — жаңартылған счёттың өзі: status, paidAt, receiptNumber, receiptUrl және басқа өрістер.
Төлем бетінен: sandbox счётының payUrl бетін ашсаңыз, онда төлеуді имитациялайтын батырма болады. Қолмен тексергенде ең жылдам жол.
Кабинеттен: Счёттар бөлімінде счёттың карточкасын ашыңыз — sandbox счётында симуляция әрекеті тұрады.
Сынау циклі
Интеграцияны тексерудің қысқа реті:
- Счёт жасаңыз.
POST /api/v1/invoices—qp_test_…кілтімен. ЖауаптағыidменpayUrl-ды сақтаңыз. - Webhook адресіңіз тіркелгенін тексеріңіз. Кабинет → Интеграциялар. Sandbox-та адрес талаптары жұмсақ, бірақ адрес қолжетімді болуы керек.
- Симуляция жасаңыз.
POST /invoices/{id}/simulate{"status":"paid"}. - Webhook келгенін тексеріңіз. Өз журналыңызда
invoice.paidбар ма, қолтаңба тексерісінен өтті ме, жауабыңыз 2xx па. - Счёттың күйін оқып шығыңыз.
GET /invoices/{id}—status: "paid",receiptNumberбар. - Қалған тармақтарды қайталаңыз: жаңа счёт →
failed, тағы біреуі →expired, тағы біреуін болдырып, сосынpaid(кеш төлем).
Webhook келмесе, себебі әдетте симуляцияда емес: Webhook келмей жатыр.
Автоматты тест жазу
Симуляция — автотест үшін жасалған. Бір тесттің қаңқасы:
const API = 'https://api.qut.kz/api/v1';
const H = { 'X-API-Key': process.env.QUTPAY_TEST_KEY, 'Content-Type': 'application/json' };
// 1. счёт
const inv = await (await fetch(`${API}/invoices`, {
method: 'POST', headers: { ...H, 'Idempotency-Key': `test-${Date.now()}` },
body: JSON.stringify({ amount: 100, description: 'Тест', externalOrderId: 'T-1' }),
})).json();
// 2. төлемді симуляциялау
await fetch(`${API}/invoices/${inv.id}/simulate`, {
method: 'POST', headers: H, body: JSON.stringify({ status: 'paid' }),
});
// 3. нәтижені тексеру
const after = await (await fetch(`${API}/invoices/${inv.id}`, { headers: H })).json();
if (after.status !== 'paid') throw new Error(`күтілгені paid, келгені ${after.status}`);
Webhook-ты да тестке қосқыңыз келсе, екі тәсіл бар:
- Тікелей тексеру. Тестіңіз webhook қабылдағышын өзі көтереді (жергілікті сервер) және симуляциядан кейін оқиғаның келуін күтеді. Жеткізу бірден жүрмейтінін ескеріп, күту уақытын қойыңыз.
- Жанама тексеру. Webhook-ты бөлек тексеріп, тестте тек өз қабылдағышыңыздың логикасын сынайсыз: дайын payload-ты өз функцияңызға беріп, дұрыс өңдейтінін тексересіз. Бұл тұрақтырақ және жылдамырақ.
Тестті қайталанатын етудің екі шарты: әр жүгіруде жаңа счёт жасаңыз (бір счётты екі рет paid етуге болмайды) және Idempotency-Key мәнін әр жүгіруде өзгертіңіз.
Қателер
| Қате | HTTP | Себебі |
|---|---|---|
not_sandbox | 403 | Ұйым live режимінде немесе счёт live счёты |
invalid_status | 422 | status — тек paid, failed, expired |
invoice_not_open | 409 | Счёт бұрын жабылған (және paid кеш төлем жағдайы емес) |
invoice_not_found | 404 | Идентификатор қате немесе счёт басқа ұйымдікі |
insufficient_scope | 403 | Кілтте invoices:write жоқ |
Толық тізім: Қателер каталогы.
Жиі қойылатын сұрақтар
Live счётты симуляциялауға бола ма? Жоқ, ешқашан. Нақты режимде бұл эндпоинт not_sandbox қайтарады — бұл әдейі солай.
Симуляциядан кейін webhook нақтысындай келе ме? Иә, дәл сондай: сол оқиға атаулары, сол қолтаңба схемасы, 2xx емес жауапта сол қайталау тәртібі.
Sandbox счёты чек алады ма? Иә, чек нөмірі беріледі және чек беті жасалады, бірақ онда SANDBOX белгісі тұрады. Фискалды чек шықпайды.
Қайтаруды да симуляциялауға бола ма? Бөлек симуляция керек емес: sandbox-та paid күйге жеткен счётқа әдеттегі қайтару шақыруын жасай бересіз.
Бұл тәсілді ЖИ-агентке тапсыруға бола ма? Иә, дәл осы цикл агенттің өзін-өзі тексеруіне ыңғайлы: ЖИ-агентке интеграцияны тапсыру.