# Struktura i obsługa powiadomienia IPN

Każde powiadomienie IPN (Webhook) wysyłane przez system SimPay posiada spójną, bazową strukturę. Niezależnie od tego,
jakiego zdarzenia dotyczy powiadomienie (np. dokonana wpłata czy zwrot), przesyłane żądanie zawsze składa się z tych samych
nagłówków HTTP oraz głównych elementów JSON – swoistej "koperty".

## Nagłówki HTTP (Headers)

Każde żądanie POST wysyłane przez nasze serwery będzie zawierało następujące nagłówki. Zwróć uwagę na `User-Agent`,
który może posłużyć jako pierwszy, wstępny (choć niewystarczający do pełnego bezpieczeństwa) filtr odrzucający ruch z
botów:

| Nagłówek | Wartość |
|  --- | --- |
| `Content-Type` | `application/json` |
| `User-Agent` | `SimPay-IPN/2.0` |


## Wymagania techniczne

Aby Twój system mógł prawidłowo odbierać powiadomienia od SimPay, musi spełniać kilka rygorystycznych warunków
technicznych:

1. **Dostępność publiczna:** Twój endpoint IPN musi być wystawiony w publicznej sieci Internet. Powiadomienia nie dotrą
na środowiska lokalne (`localhost`), chyba że użyjesz narzędzi typu ngrok.
2. **Szybka odpowiedź:** Czas oczekiwania naszego serwera na odpowiedź jest ograniczony. Ciężkie operacje (wysyłka
e-maili, generowanie PDF) bezwzględnie deleguj do systemów kolejkowych pracujących w tle.
3. **Poprawna odpowiedź HTTP:** Oczekujemy konkretnej odpowiedzi potwierdzającej odebranie żądania. Twój serwer musi
zwrócić jedną z poniższych opcji:
  * Status `HTTP 200 OK` z nagłówkiem `Content-Type: text/plain` oraz ciałem odpowiedzi zawierającym wyłącznie słowo
`OK`.
  * Status `HTTP 202 Accepted` lub `HTTP 204 No Content` (bez ciała odpowiedzi / pusty response).


## Rekomendowana kolejność obsługi

Aby zapewnić maksymalne bezpieczeństwo i wydajność, rekomendujemy obsługę każdego przychodzącego powiadomienia w
dokładnie takiej kolejności:

1. **Weryfikacja adresu IP** – sprawdź, czy adres IP nadawcy znajduje się na naszej liście autoryzowanych adresów.
Odrzuć żądanie, jeśli IP nie pasuje.
2. **Weryfikacja sygnatury** – przelicz hash z otrzymanych danych i porównaj go z polem `signature`. Zyskasz 100%
pewności, że nikt nie zmodyfikował ładunku w locie.
3. **Rozpoznanie typu (routing)** – odczytaj wartość z pola `type` i na jej podstawie oddeleguj dane (z obiektu `data`)
do asynchronicznej kolejki w Twoim systemie (Queue/Worker).
4. **Zakończenie połączenia** – natychmiast po wysłaniu zadania w tło, zwróć do nas poprawną odpowiedź (np.
`200 OK text/plain`), zamykając połączenie z serwerem SimPay.


## Struktura JSON (Koperta)

Gdy Twój endpoint odbierze żądanie, jego ciało (body) będzie zawierać następujące pola:

| Pole | Typ | Opis |
|  --- | --- | --- |
| `type` | `string` (Enum) | Typ przesyłanego zdarzenia (np. `transaction:status_changed`). Na jego podstawie wiesz, jakiego schematu spodziewać się w polu `data`. |
| `notification_id` | `char(36)` | Unikalny identyfikator (UUID) konkretnej notyfikacji. Pozwala na zapobieganie przetwarzaniu tego samego powiadomienia wielokrotnie. |
| `date` | `string` (ISO 8601) | Data i godzina wygenerowania/wysyłki notyfikacji przez nasz system (np. `2025-05-20T16:36:07Z`). |
| `data` | `object` | Obiekt zawierający szczegółowe dane biznesowe dotyczące konkretnego zdarzenia. |
| `signature` | `string` | Podpis kryptograficzny (hash SHA-256) wygenerowany z wartości pól. Służy do weryfikacji autentyczności powiadomienia. |


### Przykładowe żądanie (Request)


```http
POST /twoj-endpoint-ipn HTTP/1.1
Host: twoj-sklep.pl
Content-Type: application/json
User-Agent: SimPay-IPN/2.0

// przesyłane body nie jest formatowane (nie zawiera spacji, nowych linii itp.)
{
  "type": "transaction:status_changed",
  "notification_id": "0196fec6-7a61-7219-9458-bcc45237c252",
  "date": "2025-05-23T22:12:22+02:00",
  "data": {
    "id": "dbc87423-b121-4ad4-977f-b63c3d3831e8",
    "payer_transaction_id": "Q68KLAKN",
    "service_id": "e65c7519",
    "status": "transaction_failure",
    "amount": {
      "final_currency": "PLN",
      "final_value": "8.00",
      "original_currency": "PLN",
      "original_value": "8.00",
      "commission_system": "0.06",
      "commission_partner": "7.94",
      "commission_currency": "PLN"
    },
    "control": "3e63e31d-f08d-4942-a223-3bad2dce8096",
    "payment": {
      "channel": "blik",
      "type": "blik"
    },
    "customer": {
      "country_code": null
    },
    "created_at": "2024-08-10T15:41:50+02:00"
  },
  "signature": "095a7be5d77c4bab667dbd0f35d9b1cb0c9cec50d8af42842cc37a95b233925e"
}
```

## Co dalej?

Kiedy znasz już bazową strukturę, czas wdrożyć zabezpieczenia i zapoznać się z konkretnymi danymi, które wysyłamy:

👉 **[Weryfikacja sygnatury i bezpieczeństwo](/notifications/payment/signature)** – dowiedz się, jak poprawnie wyliczyć i
zweryfikować hash w kroku 2.

👉 **[Zdarzenie: transaction:status_changed](/notifications/payment/events/transaction_status_changed)** – zobacz strukturę pola `data` dla
najważniejszego eventu dotyczącego opłacenia transakcji.