# Жеткізу қызметіне

> Курьер жеткізу сәтінде счёт шығарады, клиент өз телефонынан төлейді. Telegram бот немесе курьер қосымшасы арқылы, тапсырыс нөмірі мен метадеректер, қайтару және жеткізілмеген тапсырыс.

## Қысқаша

Курьер есік алдында тұрғанда счётты сол жерде шығарады: Telegram бот арқылы немесе өзіңіздің курьер қосымшаңыздан. Клиент телефонын алып QR сканерлейді немесе Kaspi қосымшасына келген счётты растайды. Ақша тіке компанияның Kaspi шотына түседі, курьер қолма-қол ақша тасымайды. Тапсырыс нөмірін `externalOrderId` өрісіне, курьер мен маршрутты `metadata` ішіне жазасыз — сонда есеп өздігінен жиналады.

## Сценарий

Тапсырыс сайтта немесе қоңырау арқылы қабылданды, төлемі — жеткізу кезінде. Бұрын бұл қалай жүретін: курьер қолма-қол ақша алады, майдасы жетпейді, күн соңында кассаға тапсырады, біреуі жоғалады, есеп ай соңында ғана шығады.

Керегі: курьер есік алдында бір батырма бассын, клиент телефонынан төлесін, ақша бірден компанияның шотына түссін, диспетчер тапсырыстың төленгенін нақты уақытта көрсін.

## Жұмыс схемасы қадамдап

1. **Курьер келді.** Тапсырысты тапсырады, сомасын растайды (тауар алмастырылса сома өзгеруі мүмкін).
2. **Счёт шығарылады.** Курьер Telegram ботта `/invoice` командасын береді немесе өз қосымшасындағы «Төлем» батырмасын басады. Артында `POST /api/v1/invoices` шақырылады.
3. **Клиент төлейді.** Екі нұсқа: курьер экраннан QR көрсетеді, немесе `kind: "phone"` арқылы счёт клиенттің Kaspi қосымшасына push болып барады.
4. **Растау келеді.** Webhook `invoice.paid` жіберіледі, курьер қосымшасында тапсырыс «төленді» болады. Іс жүзінде бұл бірнеше секунд алады.
5. **Курьер тауарды береді** де, келесі мекенжайға кетеді.
6. **Диспетчер көреді.** Кабинетте немесе өз жүйеңізде маршрут бойынша қай тапсырыс төленгені көрінеді.

## Қандай API әдісі керек

| Не істейді | Әдіс |
|---|---|
| Жеткізу сәтінде счёт | `POST /api/v1/invoices` |
| Маршрутқа алдын ала счёттар | `POST /api/v1/invoices/bulk`, 1-100 |
| Күйін тексеру | `GET /api/v1/invoices/{id}` |
| Клиент қабылдамаса | `POST /api/v1/invoices/{id}/cancel` |
| Тауарды қайтарса | `POST /api/v1/invoices/{id}/refund` |
| Төлем туралы хабар | Webhook `invoice.paid` |

## QR ма, телефонға счёт па

| Жағдай | Не таңдау керек |
|---|---|
| Клиент есік алдында тұр, курьердің экраны бар | QR |
| Тапсырысты басқа адам қабылдайды, төлейтіні — тапсырыс берген | Телефонға счёт |
| Есік алдында ыңғайсыз, ауа райы қолайсыз | Телефонға счёт |
| Клиентте Kaspi қосымшасы жоқ | QR немесе `payUrl` сілтемесі |
| Сомада тиын бар | QR (телефонға счётта бүтін теңге) |

Телефонға счёт жібергенде нөмір `7XXXXXXXXXX` пішімінде болуы керек. Айырмашылығы толық: [QR счёт пен телефонға счёт](/kb/qr-vs-phone).

**QR-дың сканерлеу терезесі шектеулі.** Клиент бірден сканерлемесе, терезе бітуі мүмкін — ондайда ескі счётты `cancel` арқылы жауып, жаңасын жасайсыз. Терезенің нақты уақытын `expiresAt` өрісінен алыңыз, кодқа тұрақты сан жазып қоймаңыз.

## Тапсырыс нөмірі мен метадеректер

Счёт жасаған сәтте белгілерді дұрыс қойсаңыз, есеп кейін өздігінен жиналады:

- **`externalOrderId`** — тапсырыс нөміріңіз. Бұл өріс webhook-та қайта келеді, тізімде де, экспортта да көрінеді. «Бұл төлем қай тапсырыс бойынша» деген сұрақ бір іздеуде шешіледі.
- **`metadata`** — кез келген JSON. Мұнда курьердің идентификаторын, маршрут нөмірін, ауысымды, қоймалық аймақты, жеткізу уақытын сақтаңыз.
- **`description`** — клиент көретін мәтін. «Тапсырыс №1204, жеткізу» түрінде жазыңыз. QR счётта 100 таңба, телефонға счётта 60.

Курьер бойынша есеп жинағыңыз келсе, `metadata` ішіндегі курьер идентификаторы жеткілікті — CSV экспорттағанда сол өріс бойынша топтайсыз. Толығы: [Metadata және тапсырыс нөмірі](/kb/metadata-and-orders).

## Кодсыз нұсқасы: Telegram бот

Курьерге бөлек қосымша жазудың қажеті жоқ — Telegram бот жеткілікті. Командалары:

| Команда | Не істейді |
|---|---|
| `/invoice` | Счёт жасайды |
| `/last` | Соңғы счёттарды көрсетеді |
| `/today` | Бүгінгі қорытынды |
| `/status` | Бір счёттың күйі |
| `/cancel` | Счётты болдырмайды |
| `/support` | Қолдауға жазу |

Курьер телефонында Telegram болса жеткілікті. Ботты кабинеттен байланыстырасыз. Толығы: [Telegram бот командалары](/kb/telegram-bot-commands).

Аз көлемді жеткізуде диспетчердің [кабинеттен](https://qut.kz/app) қолмен счёт жасап, сілтемені курьерге жіберуі де жарайды.

## Қайтару

Клиент тауарды ашып көріп, қайтарып берсе, ақшаны `POST /invoices/{id}/refund` арқылы қайтарасыз: `{ amount?, reason? }`. `amount` бермесеңіз толық, берсеңіз ішінара қайтарылады (мысалы бір позицияны ғана).

Екі рет қайтарып жібермеу үшін: сұраудың жауабы белгісіз болса (желі үзілді, таймаут), бірден қайталамаңыз. Алдымен `GET /invoices/{id}` арқылы қайтарулар тізімін оқыңыз. Толығы: [Қайтару API](/kb/refunds-api).

Курьерге қайтару құқығын бермей, диспетчерге қалдырған дұрыс: `refunds:write` scope-ын курьер қолданатын кілттен алып тастаңыз.

## Жеткізілмеген тапсырыс

Клиент үйде жоқ, телефон алмайды немесе қабылдаудан бас тартты. Реті:

1. **Счёт жасалмаған болса** — ештеңе істеудің қажеті жоқ, тапсырысты өз жүйеңізде «жеткізілмеді» деп белгілейсіз.
2. **Счёт жасалып қойса, төленбесе** — `POST /invoices/{id}/cancel` арқылы жабасыз. Ашық счёттар жиналып қалмағаны дұрыс.
3. **Клиент төлеп қойып, содан кейін бас тартса** — қайтару жасайсыз.
4. **Кеш төлем келсе** — бұл болатын жағдай. `cancelled` немесе `expired` счётқа ақша кейін келсе, `invoice.paid` оқиғасы `late: true` белгісімен келеді. Ондайда не тауарды қайта жеткізесіз, не ақшаны қайтарасыз. Жүйеңізде осы тармақ болсын: [Кеш келген төлем](/kb/late-payment).

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

- **Курьер қолма-қол ақша тасымайды** — бұл негізгі пайдасы. Бірақ клиенттердің бір бөлігі бәрібір қолма-қол төлегісі келеді, екі жолды қатар қалдырыңыз.
- **Кассир нөмірі клиентке көрінеді** счёт хабарламасында. Бұл Kaspi-дің қалыпты жұмысы. Курьердің жеке нөмірі емес, компанияның кассир нөмірі көрінеді.
- **Курьерге API кілтті бермеңіз.** Курьер қосымшасы сіздің серверіңізге жүгінеді, ал сервер бізге. Кілт мобильді қосымшаға салынбауы керек.
- **Интернет.** Кейбір мекенжайларда байланыс нашар. Курьер қосымшасында счёт жасау сәтсіз болса, қайталауға мүмкіндік беретін батырма болсын — бірақ `Idempotency-Key` арқылы дубльден қорғаңыз.
- **Сома өзгерсе** ескі счётты жауып, жаңасын жасаңыз. Бір счёттың сомасын өзгерту мүмкін емес.
- **Алдымен sandbox.** `qp_test_…` кілтімен бүкіл циклді өткізіңіз: счёт, төлем симуляциясы, қайтару, болдырмау.

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

**Курьерге бөлек құрылғы керек пе?** Жоқ. Telegram бот кез келген телефонда жұмыс істейді. Өз қосымшаңыз болса, оған «Төлем» батырмасын қосасыз.

**Курьер бөтен счётты көре ала ма?** API кілтті нақты кассирге байласаңыз, ол тек сол кассир арқылы жүрген счёттарды көреді, басқаларына 404 қайтады.

**Ақша курьердің шотына түсе ме?** Жоқ. Ақша компанияның Kaspi шотына тікелей түседі.

**Клиент есік алдында ойын өзгертсе не істеу керек?** Счёт төленбеген болса `cancel` арқылы жабасыз. Төленіп қойса, қайтару жасайсыз.

**Бір маршрутқа счёттарды алдын ала жасап қоюға бола ма?** Болады, `bulk` арқылы. Бірақ QR-дың сканерлеу терезесі шектеулі, сондықтан счётты жеткізу сәтінде жасаған дұрыс.
