Kaspi Pay webhook: бұл не және AiPay арқылы қалай баптау керек
Kaspi Pay webhook дегеніміз не, неге ол кірістірілген түрде жоқ және AiPay арқылы бір сағатта event-driven төлем хабарламаларын қалай қосуға болатынын түсіндіреміз.
Сіз Kaspi-шот жасадыңыз. Клиент төледі. Кодыңыз бұл туралы білмейді
Жиі кездесетін жағдайды елестетіп көріңіз: Қазақстанға арналған онлайн-дүкен, төлем Kaspi арқылы. Клиент ақша аударады — және одан кейін үш сценарийдің бірі орын алады:
- Менеджер үзінді-копияны қолмен қарайды — 5–10 минут сайын, жұмыс уақытында, жұмыс күндері ғана.
- Скрипт polling жасайды — API-ға 30 секунд сайын сұраныс жібереді, сұраныстардың 99% нәтижесіз, сервер бос жүреді.
- Клиент «мен төледім» деп жазады — тексерілмейінше сенесіз.
Үш тәсіл де түнде, демалыс күндері және «күніне бірнеше тапсырыстан» жоғары жүктемеде бұзылады. Дұрыс шешім — webhook: сервер жүйені сұратпайды, жүйенің өзі бірдеңе болған кезде сізге хабарлайды. Дәл осыны баптаймыз.
Webhook дегеніміз не және ол polling-тен қалай ерекшеленеді
Пицца жеткізуді бақылаудың екі моделін елестетіңіз.
Polling — сіз 5 минут сайын қолданбаны ашып, статусты тексересіз. Көбінесе — «жолда», ештеңе өзгермеген. Уақыт пен назарыңызды бекер жұмсайсыз.
Webhook — қолданба курьер шыққанда, жақындағанда, есікке қоңырау шалғанда өзі хабарлама жібереді. Есікті ашу керек болғанша ештеңе жасамайсыз.
Бағдарламалауда дәл солай. Polling — кодыңыз мезгіл-мезгіл «енді, төлем өттіме?» деп сұрайды. Webhook — төлем жүйесінің өзі оқиға болған сәтте сіздің эндпоинтіңізге HTTP POST сұраныс жібереді.
Polling: сіздің серверіңіз → API (×N рет) → «жоқ» / «жоқ» / «жоқ» / «төленді»
Webhook: төлем жүйесі → сіздің серверіңіз (бір рет, дұрыс сәтте)
Webhook — бұл event-driven архитектура: код тек бірдеңе болған кезде ғана орындалады. Бұл сенімдірек, ресурс тиімдірек және қолдауы оңайырақ.
Kaspi Pay неге вебхуктерді өзі жібермейді
Kaspi — Қазақстанның ең ірі финтех-платформасы: айына 14,7 миллион белсенді пайдаланушы, 737 000 саудагер. Офлайн-бизнес үшін Kaspi керемет жұмыс істейді: кассир қолданбада хабарлама көреді, транзакция жеке кабинетте көрсетіледі.
Бірақ Kaspi Pay сыртқы әзірлеушілерге арналған жалпыға қолжетімді webhook API бермейді. Яғни, сіздің серверіңіз «#12345 шот төленді» оқиғасына тікелей жазыла алмайды. Себептері бар:
- Kaspi бастапқыда B2C-ағынын орталықтандырып салынған: хабарлама пайдаланушы қолданбасына барады, сыртқы серверге емес.
- Жалпыға қолжетімді webhook API жазылымдарды басқару, жеткізуді қайталау, мониторинг үшін инфрақұрылым қажет — бұл бөлек өнім.
- Осы мақала жазылған уақытта тәуелсіз әзірлеушілерге арналған ресми webhook-интеграция жалпыға ашық емес.
Нәтижесінде: әзірлеушілер айналым жолдарды пайдаланады — email/SMS парсинг, бейресми тәсілдер, үздіксіз polling. Барлығы өндірістік ортада тұрақсыз.
AiPay — middleware, ол дәл осы олқылықты жабады. Ресми серіктестік механизмдер арқылы Kaspi-мен жұмыс істейді және оның үстіне толыққанды webhook-қабатын қосады.
AiPay webhook қалай жұмыс істейді: 2 минуттық архитектура
Төлемді бастаудан бастап тапсырысты орындауға дейінгі толық ағын:
Сіздің қызметіңіз AiPay Kaspi Pay Клиент
──────────────────────────────────────────────────────────────────────
POST /invoices → Шот жасайды → Push-хабарлама → [қолданбада көреді]
[«Төлеу» басады]
Статус алады ← Растама ← [төлем өтті]
POST /webhook ← Жібереді ←
[HMAC тексереді]
[тапсырыс жаңартады]
[тауар береді]
Негізгі компоненттер:
- REST API — бір POST сұранысымен шот жасайсыз,
invoice_idаласыз. - Webhook жеткізу — AiPay шоттың статусын өзі бақылайды және кез-келген өзгеріс болғанда сіздің URL-ге HTTP POST жібереді.
- HMAC-SHA256 қолтаңба — әр сұраныс қолтаңбаланған, сіз шынайылығын тексере аласыз.
- Retry логикасы — серверіңіз уақытша қолжетімсіз болса, AiPay жеткізуді қайталайды.
- Polling резерв ретінде — webhook жетпей қалса,
GET /invoices/{id}арқылы статусты сұратуға болады.
AiPay webhook ағыны: қадам бойынша
- Клиент төлемді бастайды — интерфейстегі (сайт, бот, қолданба) «Төлеу» батырмасын басады.
- Бэкендіңіз шот жасайды — AiPay-ге клиент телефоны мен соммасымен POST сұранысы.
- AiPay Kaspi-де шот жасайды — клиент Kaspi қолданбасында төлем сұрауы туралы push-хабарлама алады.
- Клиент төлемді растайды — Kaspi қолданбасындағы бір басу.
- AiPay растама алады — шот статусының өзгергенін тіркейді.
- AiPay webhook жібереді — төлем деректері мен HMAC-қолтаңбамен эндпоинтіңізге HTTP POST.
- Серверіңіз оқиғаны өңдейді — қолтаңбаны тексереді, идемпотенттілікті тексереді, бизнес логиканы орындайды.
- Тапсырыс орындалды — тауар берілді, статус жаңартылды, клиент риза.
Бүкіл цикл (3–8 қадам) 20–60 секунд алады. Қолмен қатысусыз, тәулік бойы.
Код мысалы: AiPay API арқылы шот жасау
Алдымен шот жасау керек. Бұл бір ғана POST сұранысы.
cURL:
curl -X POST https://api.aipay.kz/v1/invoices \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "77001234567",
"amount": 12900,
"description": "Тапсырыс #4521 — жеткізу",
"external_id": "order_4521"
}'
Жауап:
{
"invoice_id": "inv_k7x9m2p",
"status": "pending",
"amount": 12900,
"phone": "77001234567",
"created_at": "2026-03-27T10:15:00Z",
"expires_at": "2026-03-27T10:30:00Z"
}
Python (httpx):
import httpx
AIPAY_API_KEY = "your_api_key_here"
AIPAY_BASE_URL = "https://api.aipay.kz/v1"
async def create_kaspi_invoice(
phone: str,
amount: int,
external_id: str,
description: str = "",
) -> dict:
"""
AiPay API арқылы Kaspi Pay-де шот жасайды.
:param phone: клиент телефон нөмірі 77XXXXXXXXX форматында
:param amount: теңгемен сомма (бүтін сан)
:param external_id: webhook сәйкестендіру үшін ішкі тапсырыс ID-і
:param description: төлем сипаттамасы (клиент Kaspi-де көреді)
:return: invoice_id, status және басқа өрістері бар dict
"""
async with httpx.AsyncClient() as client:
response = await client.post(
f"{AIPAY_BASE_URL}/invoices",
headers={
"Authorization": f"Bearer {AIPAY_API_KEY}",
"Content-Type": "application/json",
},
json={
"phone": phone,
"amount": amount,
"description": description,
"external_id": external_id,
},
)
response.raise_for_status()
return response.json()
Жауаптан invoice_id-ді сақтаңыз — резервтік polling қажет болса пайдаланасыз. external_id өрісі — AiPay webhook оқиғасында қайтаратын өзіңіздің тапсырыс ID-іңіз.
Код мысалы: HMAC тексерісімен webhook өңдегіші
Бұл ең маңызды бөлік. POST сұранысын алу жеткіліксіз — ол дәл AiPay-ден келгенін тексеру қажет.
Python (Flask):
import hmac
import hashlib
import json
from flask import Flask, request, jsonify, abort
app = Flask(__name__)
WEBHOOK_SECRET = "your_webhook_secret_here"
# Өңделген invoice_id жиыны — идемпотенттілік үшін
# Өндірісте Redis немесе дерекқор кестесін пайдаланыңыз
processed_invoices: set[str] = set()
def verify_aipay_signature(body: bytes, signature: str) -> bool:
"""AiPay-ден HMAC-SHA256 қолтаңбасын тексереді."""
expected = hmac.new(
WEBHOOK_SECRET.encode("utf-8"),
body,
hashlib.sha256,
).hexdigest()
# compare_digest timing-шабуылдардан қорғайды
return hmac.compare_digest(expected, signature)
@app.route("/webhook/aipay", methods=["POST"])
def handle_aipay_webhook():
# 1. JSON талдауға дейін шикі денені оқу — қолтаңбаны тексеруге қажет
body = request.get_data()
signature = request.headers.get("X-Signature", "")
# 2. Қолтаңбаны тексеру — дұрыс болмаса, қабылдамау
if not verify_aipay_signature(body, signature):
abort(403)
payload = json.loads(body)
invoice_id = payload.get("invoice_id")
status = payload.get("status")
# 3. Идемпотенттілік: бір оқиғаны екі рет өңдемеу
if invoice_id in processed_invoices:
return jsonify({"status": "already_processed"}), 200
# 4. Тек сәтті төлемдерді өңдеу
if status == "paid":
external_id = payload.get("external_id")
amount = payload.get("amount")
timestamp = payload.get("timestamp")
# Бизнес логикаңыз осында:
# - дерекқорда тапсырыс статусын жаңарту
# - клиентке хабарлама жіберу
# - жеткізуді бастау / қатынасты ашу
fulfill_order(external_id, amount)
processed_invoices.add(invoice_id)
elif status == "expired":
# Шот мерзімі өтті — клиентке хабарлап, қайта төлеуді ұсыну
handle_expired_invoice(payload.get("external_id"))
elif status == "error":
# Kaspi жағында қате болды
handle_payment_error(payload.get("external_id"))
# 5. Әрдайым 200 қайтарыңыз — болмаса AiPay сұранысты қайталайды
return jsonify({"status": "ok"}), 200
def fulfill_order(external_id: str, amount: int):
"""Сәтті төлемнен кейін тапсырысты орындау логикасы."""
print(f"Тапсырыс {external_id} {amount} ₸ сомасына төленді")
# дерекқорды жаңарту, хабарлама жіберу, т.б.
def handle_expired_invoice(external_id: str):
"""Мерзімі өткен шотты өңдеу."""
print(f"{external_id} тапсырысының шоты мерзімі өтті")
def handle_payment_error(external_id: str):
"""Төлем қатесін өңдеу."""
print(f"{external_id} тапсырысы бойынша төлем қатесі")
if __name__ == "__main__":
app.run(port=8000)
API толық анықтамалығын әзірлеушілер бетінен қараңыз.
Қауіпсіздік: HMAC тексерісі неге міндетті
Қолтаңбаны тексермесеңіз, /webhook/aipay эндпоинтіңіз — ашық есік. URL-ді білетін кез-келген адам "status": "paid" бар жалған POST сұранысын жіберіп, тауарды тегін алуы мүмкін.
HMAC-SHA256 қорғанысы қалай жұмыс істейді:
- AiPay сіздің
WEBHOOK_SECRET-іңізді біледі (тіркеу кезінде жасалады, тек сізде сақталады). - Әр webhook сұранысында AiPay
HMAC-SHA256(сұраныс_денесі, WEBHOOK_SECRET)есептеп, нәтиженіX-Signatureтақырыбына қояды. - Серверіңіз бәл есептеуді тәуелсіз жасап, нәтижелерді салыстырады.
- Қолтаңбалар сәйкес келсе — сұраныс дәл AiPay-ден келген және жол бойында өзгертілмеген.
Бұзуға болмайтын үш ереже:
- Қолтаңбаны әрдайым тексеріңіз — кез-келген бизнес логикаға дейін.
hmac.compare_digestқолданыңыз (немесе тіліңіздегі балама) — қарапайым жол салыстыру timing-шабуылына осал.- HMAC-ты шикі деннен есептеңіз — талданған JSON-нан емес. JSON-талдаушылар кілт ретін өзгертуі мүмкін, және қолтаңба сәйкес келмейді.
Шеткі жағдайларды өңдеу
Қайталау әрекеттері (retries)
Серверіңіз 200 қайтармаса (немесе таймаут ішінде жауап бермесе), AiPay белгілі уақыттан кейін жеткізуді қайталайды. Бұл қысқа мерзімді сәтсіздіктерден қорғайды — жақсы жаңалық.
Жаман жаңалық: бір оқиға екі рет келуі мүмкін. Берілген invoice_id өңделген-өңделмегенін әрдайым тексеріңіз. Жоғарыдағы кодта бұл processed_invoices set арқылы жасалған — нақты өндірісте TTL бар дерекқор кестесін немесе Redis қолданыңыз.
Идемпотенттілік
Ереже қарапайым: бір webhook-ты екі рет өңдеу дубликат жасамауы керек. Іске асырудың екі нұсқасы:
- Upsert insert орнына:
INSERT INTO orders ... ON CONFLICT (invoice_id) DO NOTHING - Тікелей тексеру: өңдеу алдында
processed_webhooksкестесіненinvoice_idіздеу
Мерзімі өткен шоттар (expired)
Kaspi-дегі шоттың өмір сүру мерзімі шектеулі (әдетте 15 минут). Клиент уақытында төлемесе — AiPay "status": "expired" жібереді. Әдеттегі жауап: клиентке хабарлап, жаңа шот жасауды ұсыну.
Өңдегіштің таймауты
AiPay жауапты шектеулі уақыт күтеді. Бизнес логикаңыз (email жіберу, сыртқы API-ға жүгіну) 5 секундтан көп уақыт алса — оны фондық тапсырмаға шығарыңыз. Webhook-өңдегіш мүмкіндігінше тез 200 OK қайтаруы керек, ауыр жұмысты асинхронды орындаңыз.
AiPay-ді тегін байқап көріңіз — 7 күн тегін
Kaspi арқылы төлем қабылдайтын бірдеңе жасап жатсаңыз және қолмен тексеруден немесе polling-тен арылғыңыз келсе, AiPay осы мәселені шешеді. Базалық бэкенд болса, интеграция шамамен бір сағат алады.
Сынақ мерзімі — 7 күн, функциялар шектеусіз. Одан кейінгі бағасы — терминал үшін айына ₸25 000.
Интеграция архитектурасы бойынша көмек немесе сұрақтар болса — бізге жазыңыз, бірге шешеміз.
Жиі қойылатын сұрақтар
Webhook жеткізу кезінде серверім өшіп қалса ше?
AiPay жеткізуді автоматты түрде қайталайды. Retry логикасы серверіңізде қысқа мерзімді ақаулар болса (қайта іске қосу, деплой, шамадан тыс жүктеме) оқиғаның жоғалмауын қамтамасыз етеді. Кодыңыздан бір ғана талап — идемпотенттілікті іске асыру, қайта жеткізу тапсырыстың қайталануына әкелмес үшін.
Қосымша сақтандыру: GET /invoices/{invoice_id} әдісі кез-келген уақытта шот ағымдағы статусын сұратуға мүмкіндік береді — қызмет іске қосылған кезде күйді синхрондау үшін пайдалы.
Сервер (no-code / low-code) жоқ болса пайдалана алам ба?
Техникалық тұрғыдан webhook жалпыға қолжетімді HTTP эндпоинтін талап етеді. Бірақ толыққанды сервер жазбай-ақ опциялар бар:
- Make (ex-Integromat) / n8n — webhook-триггерлерді қолдайтын визуалды автоматтандыру. Код жоқ, 30 минутта баптауға болады.
- Zapier — дәл солай, webhook-триггер бар.
- Serverless functions — Vercel Functions, AWS Lambda, Cloudflare Workers. Минималды код, тұрақты жұмыс істейтін сервер қажет емес.
Вебхуктерді жергілікті жерде қалай тестілеуге болады?
Жергілікті сервер интернеттен көрінбейді, сондықтан AiPay оған жете алмайды. Екі ыңғайлы шешім бар:
ngrok — ең танымал құрал. Іске қосасыз:
ngrok http 8000
https://abc123.ngrok.io түріндегі жалпыға қолжетімді URL аласыз — оны AiPay баптауларында webhook URL ретінде көрсетесіз. Барлық сұраныстар жергілікті серверіңізге проксиленеді.
Sandbox ортасы — AiPay нақты ақшасыз шот жасап, төлемдерді модельдеуге мүмкіндік беретін тест ортасын ұсынады. Әзірлеу және CI/CD pipeline-дар үшін өте ыңғайлы.
Kaspi жеке кабинетінде бірдеңе баптау керек пе?
Жоқ — барлық өзара әрекет AiPay арқылы жүреді. Тек aipay.kz-де тіркеліп, API кілті мен WEBHOOK_SECRET алу және AiPay кабинетінің баптауларында webhook URL-іңізді көрсету керек. Kaspi жүйелерінде тікелей баптау қажет емес.
Барлық параметрлер, қате кодтары және әртүрлі тілдердегі мысалдары бар толық API анықтамалығы — әзірлеушілер бетінде.