Қысқаша
Счёт жасағанда екі өріс сіздің жүйеңіздің деректерін счётқа тіркеп қоюға арналған:
externalOrderId— сіздің тапсырыс нөміріңіз. Қысқа жол, кабинетте көрінеді, іздеуге жарайды, webhook-та қайта келеді.metadata— кез келген JSON объектісі. Клиентке көрінбейді, іздеуге кірмейді, бірақ webhook-та да, күйді сұрағанда да сол күйінде қайтады.
Ережесі бір: екеуіне де құпия дерек жазбаңыз. metadata шифрланбайды және кабинетке кірген кез келген қызметкер оны көре алады.
externalOrderId
Бұл — сіздің дүкеніңіздегі немесе CRM-іңіздегі тапсырыс нөмірі. Kaspi-ге кетпейді, клиент оны көрмейді.
{
"amount": 12500,
"description": "Тапсырыс №4471",
"externalOrderId": "4471"
}
Не үшін керек:
| Мүмкіндік | Қалай жұмыс істейді |
|---|---|
| Webhook-та қайту | invoice.externalOrderId өрісінде келеді — қай тапсырысты жабуды бірден білесіз |
| Іздеу | GET /api/v1/invoices?externalOrderId=4471 — сол тапсырыстың счёттарын алады |
| Кабинетте көріну | Счёттар тізімінде және счёт карточкасында көрінеді |
| Экспорт | CSV бағанына түседі, бухгалтерияға салыстыруға ыңғайлы |
Бір тапсырысқа бірнеше счёт болуы мүмкін (біріншісі өтіп кетті, клиент қайта төледі). Сондықтан externalOrderId — бірегей кілт емес. Қайталанудан қорғау үшін бөлек Idempotency-Key тақырыбы бар: Идемпоттылық.
Не жазу керек: тапсырыс нөмірі, брондау коды, шот-фактура нөмірі. Не жазбау керек: клиенттің телефоны, ЖСН, email — бұлар үшін customer өрісі бар.
metadata
metadata — кез келген JSON объектісі. Біз оның ішіне қарамаймыз, тексермейміз, тек сақтап, кері қайтарамыз.
{
"amount": 3000,
"kind": "qr",
"description": "Су, 19 л",
"externalOrderId": "4471",
"metadata": {
"machineId": "vnd-07",
"slot": "A3",
"branch": "almaty-abay",
"courierId": 22,
"source": "telegram-bot"
}
}
Осы объект өзгертілмеген күйінде:
invoice.paidжәне басқа webhook оқиғаларыныңinvoice.metadataөрісінде келеді;GET /api/v1/invoices/{id}жауабында болады;- кабинеттегі счёт карточкасында көрінеді.
Сондықтан «төленді» хабары келгенде дерекқорға қайта бармай-ақ, қай автоматтың қай ұяшығын ашу керегін бірден білесіз.
Нені жазуға болады
| Мысал | Не үшін |
|---|---|
orderLineId, dealId | CRM-дегі ішкі идентификатор |
machineId, slot, terminalId | Вендинг автоматы, ұяшық, құрылғы нөмірі |
courierId, routeId | Курьер мен маршрут — жеткізу сәтінде төлем |
branch, pointId | Нүкте, филиал — есепті бөлу үшін |
source, campaign | Трафик көзі, науқан белгісі |
tableNo, waiterId | Мейрамханадағы үстел мен даяшы |
cartHash, attempt | Ішкі техникалық белгілер |
Ұстанымы: мұнда тек өз жүйеңіздің техникалық белгілері жатуы керек.
Нені ешқашан жазбау керек
| Жазбаңыз | Себебі |
|---|---|
| Пароль, токен, API кілт | Кабинетке кірген кез келген қызметкер көреді |
| Карта нөмірі, CVV, банк реквизиттері | Мұндай деректі сақтауға бізде негіз жоқ, ол сізге тәуекел |
| ЖСН, БИН, құжат нөмірі | Артық дербес дерек — қажет емес |
| Клиенттің мекенжайы, диагнозы, өтініш мәтіні | Дербес және құпия дерек |
| Толық себет мазмұны, ұзын журнал | metadata дерекқор емес, өз жүйеңізге идентификатор жазыңыз |
Клиенттің аты, телефоны, email керек болса — оларды metadata-ға емес, арнайы customer өрісіне жазыңыз: сонда ғана чек пен хабарлама дұрыс жұмыс істейді. Не сақталатыны туралы: Деректер және құпиялық.
Көлемі
metadata — қысқа объект болуға тиіс: бірнеше ондаған өріс, мәндері қысқа жолдар мен сандар. Ондаған килобайт JSON жіберсеңіз, счёт жасау баяулайды және webhook денесі ауырлайды. Ұзын мәтінді өз дерекқорыңызда сақтап, мұнда тек оның идентификаторын қалдырыңыз.
Webhook-та қалай қайтады
{
"event": "invoice.paid",
"invoice": {
"id": "inv_01J8…",
"externalOrderId": "4471",
"status": "paid",
"amount": 3000,
"metadata": { "machineId": "vnd-07", "slot": "A3" },
"receiptUrl": "https://…"
},
"sentAt": "2026-09-14T09:12:04.000Z"
}
Өңдеу мысалы:
if (event === 'invoice.paid') {
const { externalOrderId, metadata } = invoice;
await markOrderPaid(externalOrderId); // тапсырысты жабу
if (metadata?.machineId) openSlot(metadata.machineId, metadata.slot);
}
Webhook бір оқиғаны екі рет жеткізуі мүмкін, сондықтан өңдеу идемпотентті болсын — (invoice.id, status) жұбы бойынша тексеріңіз.
Жазылым бойынша шыққан счёттарда metadata ішінде subscriptionId және run өрістері автоматты пайда болады. Өз өрістеріңізді сол атаулармен атамаңыз.
Қайсысын таңдау керек
| Сұрақ | Жауап |
|---|---|
| Кабинеттен іздегім келеді | externalOrderId |
| CSV экспортта көрінуі керек | externalOrderId |
| Клиент көрсін деймін | Ешқайсысы емес — description жазыңыз |
| Webhook-та қайтса жетеді | metadata |
| Бірнеше мән керек | metadata |
Жиі қойылатын сұрақтар
metadata бойынша іздеуге бола ма? Жоқ. Іздеу externalOrderId бойынша жүреді. Іздеу керек мәнді сол өріске шығарыңыз.
metadata-ны кейін өзгертуге бола ма? Жоқ, ол счёт жасалған сәтте бекітіледі. Жаңа дерек пайда болса, оны өз жүйеңізде сақтаңыз.
Клиент metadata-ны көре ме? Жоқ. Төлем бетінде де, Kaspi қосымшасында да, чекте де көрінбейді. Клиент тек description мәтінін, соманы және сатушыны көреді.
externalOrderId бірегей болуы міндетті ме? Жоқ. Бір тапсырысқа бірнеше счёт болуы қалыпты жағдай. Қосарланудан қорғау Idempotency-Key арқылы жасалады.
metadata-ға массив немесе кірістірілген объект салуға бола ма? Иә, кез келген жарамды JSON. Бірақ өңдеуді жеңілдету үшін бір деңгейлі, қысқа объект ұстаған дұрыс.