Қысқаша
Спортзалда үш түрлі төлем бар: бір реттік кіру, абонемент сату және ай сайын қайталанатын төлем. Алғашқы екеуі — қарапайым счёт: ресепшенде QR көрсетесіз немесе клиенттің телефонына счёт жібересіз. Үшіншісіне жазылым бар: ол счётты кестеге сай өзі шығарады. Бірақ бірден келісіп алайық — жазылым ақшаны клиенттің картасынан өздігінен алмайды, ол тек счёт шығарады, клиент әр төлемді Kaspi қосымшасында өзі растайды.
Абонемент сату
Клиент ресепшенге келді, үш айлық абонемент алғысы келеді.
- Әкімші CRM-де немесе есеп жүйесінде абонемент карточкасын жасайды.
- Жүйе счёт шығарады:
POST /api/v1/invoices
{
"amount": 45000,
"kind": "qr",
"description": "Абонемент 3 ай, ересек",
"externalOrderId": "ABN-2026-1187",
"metadata": { "client_id": "1187", "plan": "3m", "starts": "2026-09-15" }
}
- Ресепшендегі экранда QR шығады, клиент сканерлеп төлейді.
invoice.paidwebhook келеді — жүйе абонементті белсенді етеді, картаны/браслетті береді.
Абонементті invoice.paid келгенде ғана белсендіріңіз, счёт жасалған сәтте емес. Әйтпесе төлемей кетіп қалған клиент те залға кіріп жүреді.
Клиент қашықтан сатып алса (Instagram, WhatsApp, сайт) — kind: "phone" жіберіңіз, оның Kaspi-іне push келеді. Телефон 7XXXXXXXXXX пішімінде, description 60 таңбадан аспасын.
Мерзімді ұзарту
Ұзарту — жаңа счёт, ерекше API әдісі жоқ. Маңыздысы — қашан жіберу және не жазу.
| Не | Қалай |
|---|---|
| Ескерту | Аяқталуына 3-5 күн қалғанда счёт жіберіңіз |
| Түрі | kind: "phone" — клиент залда емес |
| Сипаттама | «Абонемент ұзарту, қазан» — не үшін төлейтіні түсінікті болсын |
| Байланыс | externalOrderId ішіне ұзарту нөмірін, metadata ішіне client_id мен жаңа мерзімді жазыңыз |
| Төленбесе | Мерзім біткен соң абонементті жабасыз, кейін клиент келгенде жаңа счёт |
Ұзарту счётының мерзімі шектеулі: QR терезесі шамамен үш минут, телефонға счёт та мәңгі тұрмайды. Сондықтан «айдың басында бәріне жіберіп қою» жұмыс істемейді — жазылым дұрысырақ, ол әр клиентке өз күнінде жаңа счёт шығарады.
Ай сайынғы төлемді жазылымға беру
Жазылым — бұл счётты кестеге сай автоматты шығару. Клиенттің картасынан ақша өздігінен алынбайды, әр төлемді ол өзі растайды. Бұл маңызды айырмашылық: клиент кез келген айда «төлемеймін» деп шеше алады, сіз оны зорлай алмайсыз.
Не баптайсыз:
- Аралық:
month, кратностьevery: 1— ай сайын. Апталық форматтар үшінweekбар. - Қайталау сатысы
retryDelaysMin, әдепкі[15, 60, 360]минут. Клиент жұмыста болып, счётты көрмей қалса, 15 минуттан кейін, сосын бір сағаттан кейін, сосын алты сағаттан кейін қайта шығады. Ең көбі 5 мән. Фитнеске әдепкі жарайды, тым жиі қайталау клиентті мазалайды. - Өткізіп алу саясаты
misfirePolicy:run_once(әдепкі) немесеskip,misfireAfterMinәдепкі 1440. Жүйе бірнеше сағат жұмыс істемей қалса, кезек не бір рет жіберіледі, не тасталады. - Саты біткенде сол айдың кезегі тасталады, кесте келесі айға жалғасады.
failedRuns,lastError,lastRunStatusөрістерінен көресіз.
Клиент мұздатуға кетсе — жазылымды pause етесіз. Қайтып келгенде resume. Өткізіп қалған кезекті бірден жіберу керек болса, POST /subscriptions/{id}/resume { catchUp: true }.
Толығырақ: Жазылым API және Жазылымдық бизнеске.
Мұздату мен қайтару
Мұздату. Клиент екі аптаға кетті. Абонементтің мерзімін өз жүйеңізде жылжытасыз, жазылымы бар болса — pause. Qut Pay жағында ештеңе қайтарудың қажеті жоқ, ақша қозғалмайды.
Қайтару. Клиент абонементті мүлде қайтарғысы келсе:
POST /api/v1/invoices/{id}/refund
{ "amount": 30000, "reason": "Абонемент қайтарылды, 1 ай пайдаланылды" }
amount жазбасаңыз толық қайтарылады. Ішінара қайтарғанда счёт partially_refunded күйіне өтеді. Есептеуді өзіңіз жасайсыз: пайдаланған күндерін шегеріп, қалғанын қайтарасыз — Qut Pay пропорция есептемейді.
Бір счётты екі рет қайтарып жіберуден сақтаныңыз: Екі рет қайтарып жіберуден қалай сақтану керек. Қайтару өтпей жатса: Қайтару өтпей жатыр.
Турникетпен байланыстыру
Бір реттік кіруді автоматтандыруға болады: клиент QR-ды сканерлеп төлейді, турникет ашылады.
Реті:
- Турникет алдындағы экран (планшет, шағын монитор) сіздің серверіңізден счёт сұрайды:
amount: 2500,metadata: { "gate": "north" }. - Экранда
qrImageUrlкөрінеді. - Клиент төлейді.
- Сіздің серверіңізге
invoice.paidwebhook келеді. Олmetadata.gateбойынша қай турникет екенін біліп, контроллерге «аш» сигналын жібереді.
Webhook-ты міндетті түрде тексеріңіз: HMAC-SHA256(secret, timestamp + "." + rawBody), денені өзгертілмеген байт күйінде, JSON-ға айналдырғанға дейін. Бұл әсіресе физикалық есік ашатын жерде маңызды: Webhook қауіпсіздігі.
Өңдеуіңіз идемпотентті болсын — webhook 2xx алмаса 11 рет қайталанады, турникет он бір рет ашылмауы керек. (invoice.id, status) жұбын сақтап, қайталанғанын елемеңіз.
Кідіріске сезімтал жер болғандықтан, webhook-пен қатар күйді сұрап та тұрыңыз: Webhook пен күйді сұрау. Дәл осындай схема тұрақтарда да қолданылады: Тұрақ пен шлагбаумға.
Кодсыз нұсқасы
- Тұрақты төлем сілтемелері. Әр тарифке бір сілтеме: «1 ай», «3 ай», «жеке жаттықтырушы». Оларды Instagram профиліне, WhatsApp жауаптарына, ресепшендегі тақтайшаға қоясыз: Төлем сілтемелері.
- Кабинеттен қолмен счёт. Әкімші ресепшенде сома мен сипаттаманы жазып, QR шығарады.
- Telegram бот.
/invoice 45000 Абонемент 3 ай,/today— күндік қорытынды,/last— соңғы счёттар. Топқа қосып, бүкіл ауысымды көріп отыруға болады. - Жазылымды кабинеттен де жасауға болады, API жазбай.
Ерекше ескертулер
- «Ақша автоматты алынады» деп уәде бермеңіз. Жазылым тек счёт шығарады. Клиентке де солай түсіндіріңіз, әйтпесе «неге тағы растау керек» деген сұрақ туады.
- Кассир нөмірімен Kaspi Pay қосымшасына кірмеңіз — байланыс үзіледі де, ресепшенде счёт шығару тоқтайды: Кассир байланысы үзілді.
- Кеш келген төлемді ұмытпаңыз.
expiredсчётқа ақша кейін келсе,invoice.paidlate: trueбелгісімен келеді. Абонементті беріңіз немесе ақшаны қайтарыңыз: Кеш келген төлем. - Тарифті клиент саны бойынша емес, счёт саны бойынша есептеңіз. 300 жазылымшы + ұзартулар + бір реттік кірулер — айына 800-ден асып кетуі мүмкін: Қай тарифті таңдау керек.
Жиі қойылатын сұрақтар
Жазылым қосылса, клиент әр ай сайын растауы керек пе? Иә. Жазылым счётты шығарады, төлемді клиент Kaspi қосымшасында өзі растайды. Ақша өздігінен алынбайды.
Клиент бір айды өткізіп жіберсе не болады? Қайталау сатысы (әдепкі 15, 60, 360 минут) біткенде сол айдың кезегі тасталады, кесте келесі айға жалғасады. Абонементті жабу-жаппауды өз жүйеңіз шешеді.
Мұздатқанда ақша қайтару керек пе? Жоқ. Мұздату — мерзімді жылжыту, ол сіздің есеп жүйеңізде болады. Жазылымды pause етіп қоясыз.
Турникетті ашу қанша уақыт алады? Клиент төлегеннен кейін webhook әдетте 5 секунд ішінде келеді. Бұл Kaspi мен желіге байланысты, кепілдік бере алмаймыз — сондықтан webhook-пен қатар күйді сұрап та тұрыңыз.
Екі залым бар, есепті бөлуге бола ма? Иә: әр залға бөлек API кілт беріп, әрқайсысын өз кассиріне байлайсыз: Нүктелер бойынша бөлек есеп.