Қысқаша
Жалға беруде екі бөлек ақша қозғалысы бар: депозит (кепілдік, көбіне толық қайтарылады) және жалдау ақысы (қайтарылмайды). Екеуін бір счётқа қоспаңыз — бөлек счёт жасаңыз, сонда қайтару таза шығады. Автомат немесе құлып арқылы беретін болсаңыз, схема біреу: клиент QR-ды сканерлейді → төлейді → бізден сіздің серверге invoice.paid webhook келеді → сіздің сервер құрылғыны ашады. Қай құрылғы екенін metadata өрісіне жазып қоясыз.
Кімге жарайды
Пауэрбанк станциялары, велосипед пен самокат, аспап-құрал, құрылыс жабдығы, той киімі мен костюм, фотоаппарат, палатка — реті бәрінде бірдей.
Жұмыс схемасы қадамдап
Автомат арқылы беретін нұсқасы:
| Қадам | Кім | Не болады |
|---|---|---|
| 1 | Клиент | Станциядағы QR-ды Kaspi қосымшасымен сканерлейді |
| 2 | Станция немесе сіздің сервер | POST /api/v1/invoices — счёт жасайды, metadata-ға слот пен құрылғы нөмірін салады |
| 3 | Клиент | Kaspi-де растайды |
| 4 | Qut Pay | invoice.paid оқиғасын сіздің адреске жібереді |
| 5 | Сіздің сервер | metadata-дан құрылғы нөмірін оқып, құлыпты ашады |
| 6 | Клиент | Заттың өзін алады |
Адам қабылдайтын нүктеде (прокат пункті, киім салоны) 5-қадам орнына қызметкер затты береді — қалғаны сол.
Депозитті қалай алу керек
Екі счёт жасаңыз:
| Счёт | Сомасы | Сипаттамасы | Тағдыры |
|---|---|---|---|
| Жалдау ақысы | Мерзімге қарай | «Велосипед, 2 сағат» | Қалады |
| Депозит | Тұрақты сома | «Велосипед, кепілдік» | Қайтарылады |
Неге бөлек? Себебі қайтару счёт бойынша жүреді. Екеуін біріктірсеңіз, депозитті қайтару үшін ішінара қайтару жасауға тура келеді және есебіңіз шатасады.
Депозит — нақты ақша, оны клиент шынымен төлейді. Біз ақшаны бұғаттап ұстай алмаймыз: біздің жағымызда «ұсталған сома» деген нәрсе жоқ, ақша бірден сіздің Kaspi шотыңызға түседі. Сондықтан депозитті қайтару — бұл нақты қайтару операциясы, оны өзіңіз жасайсыз.
Клиентке мұны алдын ала түсіндіріңіз: «депозит қайтарылады, әдетте сол күні».
Депозитті қайтару
Зат түскенде, тексеріп болған соң:
POST https://api.qut.kz/api/v1/invoices/{депозит счётының id}/refund
{ "reason": "зат бүтін күйінде қайтарылды" }
amount бермесеңіз толық сома қайтарылады.
Ішінара қайтару
Зат зақымдалса немесе мерзімінен кеш қайтарылса, депозиттің бір бөлігін ұстап қаласыз:
POST https://api.qut.kz/api/v1/invoices/{id}/refund
{ "amount": 7000, "reason": "1 сағат кешіктірілді" }
Мұнда amount — қайтаратын сома, ұстап қалатын емес. 10 000 ₸ депозиттен 3 000 ₸ ұстағыңыз келсе, 7000 жазасыз. Счёт partially_refunded күйіне өтеді.
Қайтару жауабы белгісіз болып қалатын жағдай бар (refund_unknown) — бірден қайталамай, алдымен счёттың күйін оқыңыз. Толығы: Қайтару API.
Мерзімдік төлем
Ұзақ мерзімге беретін болсаңыз (айлық жабдық жалдау, ай сайынғы прокат), екі жол бар:
1. Әр кезеңге қолмен счёт. Кабинеттен немесе API-дан. Мерзім аяқталар алдында клиентке сілтеме жібересіз. Ең икемдісі: сома әр ай сайын өзгеруі мүмкін.
2. Жазылым. Кестеге сай счёт өздігінен шығады: day, week, month аралықтары бар. Бірақ маңызды: ақша клиенттің шотынан өздігінен шешілмейді, ол әр счётты Kaspi-де өзі растайды. Толығы: Жазылымдық бизнеске.
Тәулік бойынша есептелетін жалдау (самокат, велосипед) үшін жазылым жарамайды — ол жерде әр жолы бөлек счёт дұрыс.
Metadata: құрылғы нөмірін жазу
Бұл жалға беру бизнесіндегі ең маңызды техникалық тұсы. Счёт жасағанда:
{
"amount": 500,
"kind": "qr",
"description": "Пауэрбанк, 2 сағат",
"externalOrderId": "rent-90412",
"metadata": {
"station": "ALM-014",
"slot": 7,
"deviceId": "PB-33921",
"type": "rent",
"hours": 2
}
}
metadata — кез келген JSON. Ол webhook-та қайта келеді, сондықтан invoice.paid алған кезде қай станцияның қай ұясын ашу керегін базадан іздеудің қажеті жоқ — оқиғаның өзінде тұрады.
externalOrderId — сіздің жалдау нөміріңіз, ол да webhook-та қайтады. Екеуін қатар қолданыңыз: Metadata және тапсырыс нөмірі.
Депозит счётында "type": "deposit" деп белгілеңіз — сонда webhook өңдеушіңіз екеуін шатастырмайды.
Webhook жағында не істеу керек
- Идемпотентті болсын. Бір оқиға бірнеше рет келуі мүмкін.
(invoice.id, status)жұбы бойынша тексеріңіз: егер осы счёт бойынша құлып бұрын ашылған болса, екінші рет ашпаңыз. - Қолтаңбаны тексеріңіз.
X-Webhook-Signature—HMAC-SHA256(secret, timestamp + "." + rawBody). Денені өзгертілмеген байт күйінде тексеріңіз. - Жылдам жауап беріңіз. 2xx емес жауап берсеңіз, 11 рет қайталанады. Құлыпты ашу ұзаққа созылса, оқиғаны кезекке салып, бірден 200 қайтарыңыз.
- Адрес ашық болсын. Продакшенде тек
httpsжәне нақты домен, авторизациясыз.
Баптау: Webhook баптау.
Ерекше ескертулер
- QR-дың сканерлеу терезесі шамамен үш минут. Станцияда тұрған клиент ойланып қалса, счёт
expiredболады. Экранда «QR-ды қайта жасау» батырмасы тұрсын. - Кеш келген төлем. Счёт
expiredболғаннан кейін ақша келуі мүмкін —invoice.paidоқиғасыlate: trueбелгісімен келеді. Ондайда клиент станцияның қасында тұрған шығар: затты беріңіз немесе ақшаны бірден қайтарыңыз. Схемаңызда бұл жағдай қарастырылсын. - Байланыс жоқ станция. Станция интернетсіз қалса, счёт жасалмайды. Автомат схемасында бұл жағдай үшін бөлек мінез ойлаңыз.
- Депозит сомасы шектен аспасын. Тым үлкен депозит клиентті қорқытады, әрі қайтару операциясының көлемін өсіреді.
- Ақша тіке сіздің Kaspi шотыңызға түседі, бізде ұсталмайды.
Жиі қойылатын сұрақтар
Депозитті ұстап тұрып, кейін «босатуға» бола ма? Жоқ. Ондай механизм жоқ. Депозит — толық төлем, оны қайтару үшін қайтару операциясын жасайсыз.
Қайтаруға мерзім бар ма? Иә, шектеу бар. Ұзақ мерзімді жалдауда депозитті бірнеше ай ұстамаңыз — мерзімі мен қателері: Қайтару API.
Автоматта экран жоқ, тек жапсырма QR қойсам бола ма? Тұрақты (статикалық) сілтеме жасауға болады, бірақ ондайда счёт нақты құрылғыға байланбайды. Схемасы тұрақ пен шлагбаумға ұқсас: Тұрақ пен шлагбаумға және Вендинг автоматына.
Клиент затты қайтармаса ше? Депозитті ұстап қаласыз, ол сіздің шотыңызда тұр — ешқандай әрекет керек емес. Қалғаны сіз бен клиенттің арасындағы мәселе.
Бірнеше станциям бар, есепті бөлек көргім келеді. Әр станцияға бөлек API кілт жасаңыз немесе metadata.station бойынша сүзіңіз: Нүктелер бойынша бөлек есеп.