# Dobre praktyki

Sprawdzone zalecenia dla integracji produkcyjnych. Większość opisanych niżej
problemów pochodzi z prawdziwych zgłoszeń wsparcia — oszczędź sobie tej
wycieczki.

## Nie hardkoduj przewoźników i usług

**Pobieraj listę usług z API zamiast wpisywać ją na stałe w kodzie.** Zestaw
dostępnych przewoźników i usług zmienia się w czasie — przewoźnicy są
dodawani i usuwani, usługi dostępne dla *Twojego konta* zależą od umowy, a
katalog różni się także między
[sandboksem a produkcją](/pl/guides/testing). Zahardkodowana lista po cichu
się dezaktualizuje: albo oferujesz usługi, które odrzucą zamówienie, albo
pomijasz przewoźników, za których już płacisz.

Wywołaj `service_structure` ([SDK](/pl/sdk): `getServiceStructure()`), aby
pobrać aktualne usługi, typy paczek, opcje i typy odbioru dla swojego konta:

```php
$structure = $client->getServiceStructure();

foreach ($structure->getServices() as $service) {
    // Zbuduj z tej listy swój UI / konfigurację wyboru przewoźnika
    registerService($service['service_id'], $service['name'], $service['supplier']);
}
```

Struktura zmienia się rzadko — cache'uj ją (np. odświeżaj raz dziennie albo
przy deploymencie) zamiast pobierać przy każdym żądaniu, ale źródłem prawdy
jest zawsze API, nigdy Twój kod.

## Uwaga: nieznane klucze payloadu są po cichu ignorowane

API nie odrzuca nieznanych pól w payloadzie `request` — błędnie nazwany
klucz nie powoduje błędu, tylko **po cichu gubi Twoje dane**, a API wraca
do wartości domyślnych. Klasyczna pułapka: wymiary przesyłki to
`dimension1` / `dimension2` / `dimension3` (cm) — wyślij `length` /
`width` / `height`, a zamówienie powstanie z domyślnymi wymiarami i błędną
ceną, bez żadnego ostrzeżenia. Buduj payloady w oparciu o
[referencję API v2](/pl/reference/v2-legacy) (albo używaj typowanych
obiektów żądań z [SDK](/pl/sdk)) i weryfikuj utworzone zamówienia przez
`getOrder()` podczas developmentu.

## Nigdy nie ufaj kodowi statusu HTTP

API zwraca **HTTP 200 również dla błędów** — rzeczywisty wynik to pole
`status` w ciele odpowiedzi. Sprawdzaj je przy każdym wywołaniu albo użyj
[SDK](/pl/sdk), które robi to za Ciebie i rzuca `ApiException`. Zobacz
[semantykę błędów](/pl/legacy/error-semantics).

## Ostrożnie z ponawianiem żądań

Timeout nie oznacza, że żądanie nie dotarło do serwera. Ślepe ponawianie
operacji nieidempotentnych — przede wszystkim `order_send` — może utworzyć
**zduplikowane zamówienia** (i zduplikowane opłaty). Ponawiaj błędy sieciowe
tylko dla operacji odczytu, a operacje zapisu weryfikuj przez `getOrders()`
zanim je ponowisz. `RetryingHttpClient` z SDK celowo ponawia wyłącznie błędy
sieciowe, nigdy błędy API.

## Pamiętaj: ceny są w groszach

Ceny wycen i zamówień są zwracane **w groszach** (1 PLN = 100 gr). Dziel
przez 100 przed pokazaniem człowiekowi i przechowuj je jako liczby
całkowite — float i pieniądze kończą się źle.

## Trzymaj dane dostępowe po stronie serwera

`app_secret` podpisuje każde żądanie — każdy, kto go zna, może tworzyć
zamówienia na Twoim koncie. Nigdy nie umieszczaj go w kodzie frontendu,
aplikacjach mobilnych ani publicznych repozytoriach. Zobacz
[Uwierzytelnianie](/pl/guides/authentication).

## Podpisuj dokładnie to, co wysyłasz

Jeśli integrujesz się bez SDK: wyliczaj podpis z **dokładnie** tego łańcucha
`request`, który wysyłasz. Ponowna serializacja payloadu po podpisaniu (inna
kolejność kluczy, białe znaki, escapowanie) to najczęstsza przyczyna błędów
`Invalid signature` — zobacz [podpisywanie żądań](/pl/legacy/hmac-signing).

## Weryfikuj podpisy webhooków

Jeśli używasz [push trackingu](/pl/guides/tracking#webhooki-push-tracking),
zawsze weryfikuj podpis notyfikacji przed jej przetworzeniem — inaczej
każdy, kto pozna URL Twojego endpointu, może wstrzykiwać fałszywe statusy.
`PushTrackingWebhook` z SDK z założenia odrzuca niezweryfikowane payloady.

## Identyfikuj swoją integrację

Wysyłaj z każdym żądaniem opisowy `User-Agent` (nazwa i wersja aplikacji).
Gdy coś pójdzie nie tak — seria nieudanych zamówień, burza retry — Apaczka
wie, która integracja i które wydanie za tym stoi, i może się odezwać, zanim
zrobi się z tego incydent. [SDK PHP](/pl/sdk) robi to za Ciebie
(`AlsendoOneSDK/<wersja> PHP/<wersja>`); integracje bez SDK powinny ustawić
ten nagłówek samodzielnie.

## Najpierw testuj w sandboksie

Używaj [środowiska sandbox](/pl/guides/testing) do developmentu i CI —
zamówienia produkcyjne to prawdziwe zamówienia, prawdziwi kurierzy i
prawdziwe faktury.
