update
This commit is contained in:
246
docs/integrace-eshop.md
Normal file
246
docs/integrace-eshop.md
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
# Požadavky na integraci eshopu – Tracking API
|
||||||
|
|
||||||
|
Dokument popisuje, jak má eshop posílat data o košících a objednávkách.
|
||||||
|
Integrace je **serverová** – eshop posílá data přímo z backendu podle e-mailu zákazníka, žádné browser-tracking cookies nejsou potřeba.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Autentizace
|
||||||
|
|
||||||
|
Každý požadavek musí obsahovat **Site Key** – buď jako HTTP hlavičku, nebo jako query parametr:
|
||||||
|
|
||||||
|
```
|
||||||
|
X-Site-Key: <vas-site-key>
|
||||||
|
```
|
||||||
|
nebo
|
||||||
|
|
||||||
|
```
|
||||||
|
POST https://tracking.domena.cz/api/eshop/cart?site_key=<vas-site-key>
|
||||||
|
```
|
||||||
|
|
||||||
|
Site Key vám bude přiděleno naší stranou.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Endpoint: Stav košíku
|
||||||
|
|
||||||
|
Volejte **při každé změně košíku** (přidání, odebrání, změna množství).
|
||||||
|
Párování košíku probíhá automaticky podle e-mailu zákazníka.
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/eshop/cart
|
||||||
|
Content-Type: application/json
|
||||||
|
X-Site-Key: <key>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tělo požadavku
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"email": "zakaznik@example.cz",
|
||||||
|
"currency": "CZK",
|
||||||
|
"total_no_tax": 198.00,
|
||||||
|
"cart_id": null,
|
||||||
|
"occurred_at": "2026-04-22T10:00:00+02:00",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"code": "PROD-001",
|
||||||
|
"name": "Název produktu",
|
||||||
|
"qty": 2,
|
||||||
|
"unit_no_tax": 99.00,
|
||||||
|
"total_no_tax": 198.00,
|
||||||
|
"url": "https://eshop.cz/produkt/nazev"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Popis polí
|
||||||
|
|
||||||
|
| Pole | Typ | Povinné | Popis |
|
||||||
|
|------|-----|---------|-------|
|
||||||
|
| `email` | string | ✅ | E-mail zákazníka – slouží k párování košíku |
|
||||||
|
| `currency` | string | ✅ | ISO kód měny, např. `"CZK"` |
|
||||||
|
| `total_no_tax` | float | ne | Celková suma košíku bez DPH |
|
||||||
|
| `cart_id` | int\|null | ne | ID košíku z předchozí odpovědi; při prvním volání vynechejte nebo pošlete `null` |
|
||||||
|
| `occurred_at` | datetime | ne | ISO 8601 čas události |
|
||||||
|
| `items` | array | ✅ | Pole položek (prázdné pole = prázdný košík) |
|
||||||
|
| `items[].code` | string | ✅ | SKU / kód produktu |
|
||||||
|
| `items[].name` | string | ne | Název produktu |
|
||||||
|
| `items[].qty` | int | ✅ | Počet kusů |
|
||||||
|
| `items[].unit_no_tax` | float | ne | Cena za kus bez DPH |
|
||||||
|
| `items[].total_no_tax` | float | ne | Celková cena za řádek bez DPH |
|
||||||
|
| `items[].url` | string | ne | URL produktu |
|
||||||
|
|
||||||
|
### Logika párování košíku
|
||||||
|
|
||||||
|
1. Eshop pošle e-mail → systém najde nebo vytvoří kontakt.
|
||||||
|
2. Systém hledá **poslední otevřený košík** pro daný kontakt.
|
||||||
|
3. Pokud obsah košíku je stejný jako naposledy, jen obnoví `last_seen_at` (žádný duplikát).
|
||||||
|
4. Pokud se obsah liší, aktualizuje košík a zapíše nový event.
|
||||||
|
5. `cart_id` z odpovědi doporučujeme ukládat a posílat zpět – urychlí párování.
|
||||||
|
|
||||||
|
### Odpověď
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"cart_id": 42,
|
||||||
|
"status": "open",
|
||||||
|
"changed": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ **`cart_id` z odpovědi si uložte** a posílejte ho v dalších voláních. Pokud ho nepošlete, systém dohledá košík sám podle e-mailu, ale s `cart_id` je to rychlejší a spolehlivější.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Endpoint: Dokončení objednávky
|
||||||
|
|
||||||
|
Volejte **jednorázově** při úspěšném dokončení objednávky (stránka "Děkujeme za objednávku" nebo webhook ze systému objednávek).
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /api/eshop/order
|
||||||
|
Content-Type: application/json
|
||||||
|
X-Site-Key: <key>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tělo požadavku
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"email": "zakaznik@example.cz",
|
||||||
|
"cart_id": 42,
|
||||||
|
"order_id": "ORD-2026-0042",
|
||||||
|
"total_no_tax": 198.00,
|
||||||
|
"currency": "CZK",
|
||||||
|
"occurred_at": "2026-04-22T10:05:00+02:00",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"code": "PROD-001",
|
||||||
|
"name": "Název produktu",
|
||||||
|
"qty": 2,
|
||||||
|
"unit_no_tax": 99.00,
|
||||||
|
"total_no_tax": 198.00
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"checkout": {
|
||||||
|
"shipping_no_tax": 89.00,
|
||||||
|
"shipping_label": "PPL",
|
||||||
|
"cod_fee_no_tax": 29.00
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Popis polí
|
||||||
|
|
||||||
|
| Pole | Typ | Povinné | Popis |
|
||||||
|
|------|-----|---------|-------|
|
||||||
|
| `email` | string | ✅ | E-mail zákazníka |
|
||||||
|
| `cart_id` | int | ne | ID košíku z předchozích volání (doporučeno) |
|
||||||
|
| `order_id` | string | ne | ID objednávky ve vašem systému |
|
||||||
|
| `total_no_tax` | float | ne | Celková hodnota objednávky bez DPH |
|
||||||
|
| `currency` | string | ne | Měna, např. `"CZK"` |
|
||||||
|
| `items` | array | ne | Stejný formát jako u `/eshop/cart` |
|
||||||
|
| `checkout.shipping_no_tax` | float | ne | Cena dopravy bez DPH |
|
||||||
|
| `checkout.shipping_label` | string | ne | Název dopravce (PPL, Zásilkovna...) |
|
||||||
|
| `checkout.cod_fee_no_tax` | float | ne | Příplatek za dobírku bez DPH |
|
||||||
|
|
||||||
|
### Logika párování objednávky
|
||||||
|
|
||||||
|
1. Systém najde kontakt podle e-mailu.
|
||||||
|
2. Hledá košík podle `cart_id` (pokud přišel), jinak poslední otevřený košík pro daný kontakt.
|
||||||
|
3. Pokud žádný košík nenajde, vrátí chybu `cart_not_found` (404).
|
||||||
|
4. Košík označí jako `converted` a uloží data objednávky.
|
||||||
|
|
||||||
|
### Odpověď
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"cart_id": 42,
|
||||||
|
"order_id": "ORD-2026-0042",
|
||||||
|
"status": "converted"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Chybové stavy
|
||||||
|
|
||||||
|
| HTTP kód | Chyba | Řešení |
|
||||||
|
|----------|-------|--------|
|
||||||
|
| 401 | Missing/invalid site key | Zkontrolujte X-Site-Key |
|
||||||
|
| 422 | Chybí povinné pole | Viz popis polí výše |
|
||||||
|
| 404 | `cart_not_found` | Zákazník neměl otevřený košík; pošlete nejdřív `/eshop/cart` |
|
||||||
|
| 500 | Server error | Opakujte požadavek, dejte nám vědět |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Doporučené pořadí volání
|
||||||
|
|
||||||
|
```
|
||||||
|
Zákazník přidá produkt do košíku
|
||||||
|
└─ POST /api/eshop/cart {email, items, currency, ...}
|
||||||
|
└─ uložit cart_id z odpovědi
|
||||||
|
|
||||||
|
Zákazník změní množství / přidá další produkt
|
||||||
|
└─ POST /api/eshop/cart {email, cart_id, items, ...}
|
||||||
|
(pokud se obsah nezměnil, systém jen obnoví čas – žádný duplikát)
|
||||||
|
|
||||||
|
Zákazník dokončí objednávku
|
||||||
|
└─ POST /api/eshop/order {email, cart_id, order_id, ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. PHP příklad
|
||||||
|
|
||||||
|
```php
|
||||||
|
// Při změně košíku
|
||||||
|
$response = Http::withHeaders(['X-Site-Key' => config('tracking.site_key')])
|
||||||
|
->post('https://tracking.domena.cz/api/eshop/cart', [
|
||||||
|
'email' => $customer->email,
|
||||||
|
'currency' => 'CZK',
|
||||||
|
'total_no_tax' => $cart->totalNoTax(),
|
||||||
|
'cart_id' => session('ft_cart_id'), // null při prvním volání
|
||||||
|
'items' => $cart->items->map(fn($item) => [
|
||||||
|
'code' => $item->sku,
|
||||||
|
'name' => $item->name,
|
||||||
|
'qty' => $item->qty,
|
||||||
|
'unit_no_tax' => $item->unitPriceNoTax,
|
||||||
|
'total_no_tax' => $item->totalNoTax,
|
||||||
|
'url' => $item->url,
|
||||||
|
])->toArray(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Uložit cart_id pro příští volání
|
||||||
|
if ($response->successful()) {
|
||||||
|
session(['ft_cart_id' => $response->json('cart_id')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Při dokončení objednávky
|
||||||
|
Http::withHeaders(['X-Site-Key' => config('tracking.site_key')])
|
||||||
|
->post('https://tracking.domena.cz/api/eshop/order', [
|
||||||
|
'email' => $customer->email,
|
||||||
|
'cart_id' => session('ft_cart_id'),
|
||||||
|
'order_id' => $order->id,
|
||||||
|
'total_no_tax' => $order->totalNoTax(),
|
||||||
|
'currency' => 'CZK',
|
||||||
|
'checkout' => [
|
||||||
|
'shipping_no_tax' => $order->shippingNoTax,
|
||||||
|
'shipping_label' => $order->shippingLabel,
|
||||||
|
'cod_fee_no_tax' => $order->codFeeNoTax,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Technické poznámky
|
||||||
|
|
||||||
|
- Všechna data v **UTF-8**, `Content-Type: application/json`
|
||||||
|
- `occurred_at` v ISO 8601 formátu, ideálně s časovou zónou
|
||||||
|
- Ceny jako **float bez DPH** – pokud nemáte ceny bez DPH, uveďte ceny s DPH a poznamenejte to
|
||||||
|
- Pokud zákazník nakupuje bez přihlášení (guest checkout) a e-mail je znám až při dokončení objednávky, pošlete `/eshop/cart` s e-mailem hned jak ho zadá do checkoutu
|
||||||
|
- Volání `/eshop/cart` s prázdným `items: []` správně uzavře košík (status `empty`)
|
||||||
Reference in New Issue
Block a user