# Интернет-дүкенге Kaspi төлемін қосу

> Себеттен «төленді» күйіне дейінгі толық схема: счёт, төлем беті, webhook. Tilda, WooCommerce, OpenCart және өзі жазылған сайт үшін кодсыз жол мен API жолы.

## Қысқаша

Интернет-дүкен үшін реті әрдайым біреу: клиент себетті рәсімдейді → сіздің сайт Qut Pay-де счёт жасайды → клиент QR-ды сканерлейді немесе төлем сілтемесін ашады → Kaspi-де растайды → бізден сіздің сайтқа webhook келеді → тапсырыс «төленді» болады. WooCommerce мен OpenCart 4-ке дайын модуль бар, Tilda мен кез келген форма форма-хук арқылы қосылады, өзі жазылған сайтқа бір ғана API әдісі жетеді.

## Жұмыс схемасы

| Қадам | Кім істейді | Не болады |
|---|---|---|
| 1 | Клиент | Себетті рәсімдейді, «Kaspi арқылы төлеу» дейді |
| 2 | Сіздің сервер | `POST /api/v1/invoices` — счёт жасайды, `externalOrderId` ретінде тапсырыс нөмірін береді |
| 3 | Сіздің сервер | Жауаптан `payUrl` немесе `qrImageUrl` алып, клиентке көрсетеді |
| 4 | Клиент | Kaspi қосымшасында растайды |
| 5 | Qut Pay | Сіздің адреске `invoice.paid` оқиғасын жібереді |
| 6 | Сіздің сервер | Тапсырысты «төленді» етеді, клиентке хат жібереді |

Ақша сіздің Kaspi шотыңызға тікелей түседі, бізде ұсталмайды. Толығы: [Ақша қашан және қайда түседі](/kb/money-arrival).

## Қандай API әдісі қолданылады

Негізгісі біреу — счёт жасау:

```
POST https://api.qut.kz/api/v1/invoices
X-API-Key: qp_live_…
Idempotency-Key: order-10482
Content-Type: application/json

{
  "amount": 24900,
  "kind": "qr",
  "description": "Тапсырыс №10482",
  "externalOrderId": "10482",
  "successUrl": "https://dukenim.kz/thanks?order=10482",
  "failUrl": "https://dukenim.kz/cart",
  "metadata": { "source": "site", "city": "almaty" }
}
```

Жауап 201-де: `id`, `status`, `payUrl`, `qrUrl`, `deepLink`, `qrImageUrl`, `expiresAt`.

Қосымша керек болатындар:

- `GET /api/v1/invoices/{id}` — счёттың күйін сұрау (webhook кешігіп жатса немесе «Төледім» батырмасын қойсаңыз)
- `POST /api/v1/invoices/{id}/cancel` — клиент себеттен бас тартса
- `POST /api/v1/invoices/{id}/refund` — тауар қайтарылса, `{ amount?, reason? }`

## Кодсыз жолдар

**WooCommerce.** Дайын плагин бар. Орнатасыз, API кілтті енгізесіз, webhook адресі автоматты қосылады. Тапсырыс күйі төлемге қарай өзі ауысады. Нұсқаулық: [WordPress интеграциясы](https://api.qut.kz/docs/guide/wordpress), файл [жүктеулер бөлімінде](https://api.qut.kz/downloads/).

**OpenCart 4.** Кеңейту бар, орнату реті сол сияқты: кілт, режим, webhook.

**Tilda және кез келген форма.** Форма-хук арқылы. Tilda формасының жіберу адресі ретінде біздің хук адресін көрсетесіз, өрістерді (сома, сипаттама, телефон) сәйкестендіресіз, клиент форманы жібергенде счёт жасалып, ол төлем бетіне бағытталады. Бұл жол сайты бар, бірақ сервері жоқ дүкендерге ыңғайлы.

**Төлем сілтемелері.** Ассортименті шағын болса, әр тауарға тұрақты сілтеме жасауға болады: `qut.kz/p/<slug>`. Оны сайтқа батырма етіп қоясыз, серверде ештеңе жазбайсыз. Сомасы ашық сілтеме де бар — клиент соманы өзі енгізеді.

**Кабинеттен қолмен счёт.** Тапсырыс күніне бірнешеу ғана болса, әуелі осылай бастаңыз: [Бірінші счётты қалай жасау керек](/kb/first-invoice).

## API жолы: өзі жазылған сайт

Үш нәрсені дұрыс істесеңіз жеткілікті.

**1. Кілт тек серверде.** `X-API-Key` браузерде орындалатын кодта болмауы керек. Себет бетіндегі JavaScript өз серверіңізге жүгінеді, счётты сервер жасайды.

**2. Идемпоттылық.** Клиент «Төлеу» батырмасын екі рет бассa, екі счёт шықпауы керек. `Idempotency-Key` тақырыбына тапсырыс нөмірін беріңіз — сол кілтпен қайталасаңыз жаңа счёт жасалмай, бұрынғысы қайтады.

**3. Webhook өңдеу.** Кабинет → Интеграциялар → адресті қосасыз. Продакшенде тек `https` және нақты домен. Қолтаңбаны тексеріңіз: `HMAC-SHA256(secret, timestamp + "." + rawBody)`, денені **JSON-ға айналдырғанға дейін**, өзгертілмеген байт күйінде. 2xx қайтармасаңыз 11 рет қайталанады.

SDK бар: Node.js, PHP, Python. Жалпы реті: [Интеграция нұсқаулығы](https://api.qut.kz/docs/guide/integration).

## Ерекше ескертулер

- **QR-дың сканерлеу терезесі шамамен үш минут.** Оны Kaspi белгілейді. Төлем бетінде таймер көрсетіңіз және терезе біткенде «Жаңа QR» батырмасын беріңіз — ескі счётты «expired» деп қалдырып, жаңасын жасайсыз. Тұрақты деп жазбаңыз, `expiresAt` өрісінен алыңыз.
- **Кеш төлем болады.** `expired` немесе `cancelled` счётқа ақша кешігіп келсе, `invoice.paid` оқиғасы `late: true` белгісімен келеді. Ондай тапсырысты автоматты жауып тастамаңыз: не тауарды беріңіз, не ақшаны қайтарыңыз.
- **Webhook өңдеуіңіз идемпотентті болсын.** Бір оқиға бірнеше рет келуі мүмкін. `(invoice.id, status)` жұбы бойынша бір-ақ рет өңдеңіз.
- **Тек webhook-қа сүйенбеңіз.** «Рақмет» бетінде `GET /invoices/{id}` арқылы күйді бір рет сұраңыз — сонда webhook кешіксе де клиент дұрыс бетті көреді.
- **Алдымен sandbox.** `qp_test_…` кілтімен бүкіл тізбекті өткізіп шығыңыз, төлемді `simulate` арқылы қолдан жасаңыз. Айырмашылығы: [Sandbox пен нақты режимнің айырмашылығы](/kb/sandbox-vs-live).
- **Тест режимін өшіруді ұмытпаңыз.** Ең жиі кездесетін мәселе осы: [Клиентке төлем келмей жатыр](/kb/payment-not-arriving).

## Жиі қойылатын сұрақтар

**Сайтымда сервер жоқ, тек Tilda. Бола ма?** Иә. Форма-хук немесе төлем сілтемелері арқылы кодсыз жұмыс істейді. Тапсырыс күйін кабинеттен қарайсыз.

**Бір тапсырысқа бірнеше QR шыға бере ме?** Иә, терезе біткен сайын жаңа счёт жасай бересіз. Бірақ әрқайсысы бөлек счёт болып саналады — сондықтан ескісін `cancel` етіп отырыңыз, әйтпесе есепте шатасасыз.

**Клиент төледі, бірақ тапсырыс жаңармады. Не істеймін?** Алдымен webhook журналын қараңыз: [Webhook келмей жатыр](/kb/webhook-not-arriving). Ол жерде жеткізу әрекеттері мен қате коды тұрады.

**Клиентте Kaspi қосымшасы жоқ болса?** Онда QR немесе сілтеме береміз, телефонға счёт жарамайды: [Клиентте Kaspi қосымшасы жоқ](/kb/customer-no-kaspi).

**Айына қанша тапсырыс өткізе аламын?** Тарифке байланысты: Бастау — 800, Бизнес — 4 000, Про — 15 000 счёт. Таңдау: [Қай тарифті таңдау керек](/kb/tariff-choose).
