Қысқаша
Сатып алушы QR-ды төлегенде Qut Pay оны өзі байқап, екі нәрсе істейді: серверіңізге invoice.paid webhook-ін жібереді және счёттың күйін сұрауға болатын paid-қа өзгертеді. Дұрыс схема: тапсырыс қолтаңбасы тексерілген webhook бойынша немесе серверден GET /invoices/{id} жауабы бойынша төленді деп белгіленеді, бірақ ешқашан сатып алушының «рахмет» бетіне оралуы бойынша емес.
1-тәсіл — webhook (негізгі)
- Кабинет → Интеграциялар бөлімінде серверіңіздің адресін жазып, құпия сөзді алыңыз — webhook баптау.
- Төлем болғанда
POSTкеледі, JSON:{ "event": "invoice.paid", "invoice": { "id", "status": "paid", "amount", "externalOrderId", "paidAt", "receiptUrl", … } }. - Қолтаңбаны тексеріңіз:
X-Webhook-Signature: sha256=…тақырыбы —timestamp + "." + шикі денежолының HMAC-SHA256-сы,timestampX-Webhook-Timestamp-тан. JSON-ды талдамай тұрып, дененің шикі байттары бойынша есептеңіз — қолтаңба неге сәйкес келмейді. - Тапсырысты
externalOrderIdбойынша тауып,amount-ты салыстырып, төленді деп белгілеп, 8 секунд ішінде200қайтарыңыз. - Өңдеушіні идемпотентті етіңіз: сол
(invoice.id, status)екі рет келуі мүмкін, қайталанғаны ештеңе өзгертпеуі керек.
Сервер 2xx қайтармаса, Qut Pay жеткізуді шамамен екі сағат ішінде 11 ретке дейін қайталайды — webhook келмейді.
2-тәсіл — күйін сұрау (қосымша)
curl https://api.qut.kz/api/v1/invoices/inv_… -H "X-API-Key: qp_live_…"
Жауапта status: pending — күтудеміз, paid — төленді, expired / cancelled / failed — төленбеді. Сервис соңғы белгілі күйді емес, Kaspi-ден дәл қазір сұрауы үшін ?live=1 қосыңыз. Сатып алушы төлем бетінде тұрғанда 5–10 секунд сайын сұрау қалыпты; әр секунд сайын сұрау сұраныс лимитіне тіреледі. Қайсысын қашан таңдау: webhook пе, сұрау ма.
«Рахмет» беті
Төлемнен кейін сатып алушы сіздің successUrl-ге оралады. Бұл өту — төлемнің дәлелі емес: сілтемені қолмен де ашуға болады. Сол бетте счёт күйін серверден сұрап, «төленді» деп тек paid болғанда көрсетіңіз.
Тағы не күту керек
invoice.expired— QR бітті, сатып алушы төлемеді; жаңа счёт жасауға болады — QR неге бітеді.- Мерзімі өткен соң төлеу — сирек жағдай, сервис оны бәрібір тауып,
lateбелгісіменinvoice.paidжібереді — кешіккен төлем. - Барлық күй мен ауысулар: счёттың өмірлік циклі.
Нақты ақшасыз тексеру
Sandbox-та (qp_test_…) төлемді {"status":"paid"} денесімен POST /invoices/{id}/simulate сұрауы имитациялайды — webhook барлық тақырыбымен нағыз күйінде келеді — sandbox.