Last updated

Obsługa notyfikacji Płatności Online (IPN v2)

Informacja

Notyfikacje wysyłane są metodą POST za pomocą Content-Type application/json. Każda notyfikacja musi zwrócić w response jako plaintext odpowiedź OK ze statusem HTTP 200.

Struktura notyfikacji

PoleTypOpis
typeEnumPrzesyłany event, pełna lista poniżej
notification_idchar(36)Unikalne ID notyfikacji
datedate (ISO 8601)Data i godzina wysyłki notyfikacji w formacie ISO 8601 (np. 2025-05-20T16:36:07Z)
dataObiektDane przesyłane w tym evencie
signaturestringWyliczona sygnatura, szczegóły poniżej

Wyliczanie sygnatury

Sygnature generujemy za pomocą zestawienia ze sobą wartości pola type, notification_id, wszystkich odebranych parametrów (oprócz signature) do API w kolejności z tabel poniżej, oddzielając je seperatorem | i dodając na końcu klucz dostępny w Panelu Klienta w usłudze. Hashowanie musi odbyć się za pomocą sha256.

Bazowo ciąg do zahashowania powinnien wyglądać tak:

type|notification_id|date|data_value1|data_value2|data_valueN|key
Informacja

Wartości z pola data powinny być dołączane do sygnatury w takiej kolejności, jak zostały wypisane w dokumentacji.

Przykładowy sposób generowania sygnatury dla poniższych przykładowych danych:

  • type = example:type
  • notification_id = 0196bf93-aca4-7253-8a2d-0941a037f25b
  • date = 2025-05-20T16:36:07Z
  • data ma pola:
    • status = transaction_paid
    • amount (obiekt)
      • amount.currency = PLN
      • amount.value = 5.25
    • transaction_id = 123123123123
    • meta = test
  • key = keyFromPanel

Łącząc wszystkie elementy prawidłowo będzie wyglądać tak:

example:type|0196bf93-aca4-7253-8a2d-0941a037f25b|2025-05-20T16:36:07Z|transaction_paid|PLN|5.25|123123123123|test|keyFromPanel

Jeśli jakieś pole w dokumentacji informuje nas o tym, że może nie występować jeśli np. nie został przekazany podczas inicjacji płatności to pomijamy całkowicie ten element podczas generowania sygnatury.

Patrząc na przykład, załóżmy, że pole meta może nie występować i faktycznie nie występuje. W takim przypadku konkatenacja elementów będzie wyglądać tak:

example:type|0196bf93-aca4-7253-8a2d-0941a037f25b|2025-05-20T16:36:07Z|transaction_paid|PLN|5.25|123123123123|keyFromPanel

Tak przygotowany łańcuch znaków przekazujemy funkcji hashującej sha256. SimPay przesyła sygnaturę jako string lower-case.

Przykład generowania wartości sygnatury w wybranych językach i SDK:

<?php

class SimPaySignatureValidator
{
    public function isValid(): bool
    {
        $payload = json_decode(@file_get_contents('php://input'), true);
        if (empty($payload)) {
            return false;
        }

        $data = $this->flattenArray($payload);
        $data[] = 'KLUCZ_IPN_USŁUGI';

        $signature = hash('sha256', implode('|', $data));

        return hash_equals($signature, $payload['signature']);
    }

    private function flattenArray(array $array): array
    {
        unset($array['signature']);

        $return = [];

        array_walk_recursive($array, function ($a) use (&$return) {
            $return[] = $a;
        });

        return $return;
    }
}

$validator = new SimPaySignatureValidator();
if(!$validator->isValid()) {
  http_response_code(403);
  echo 'INVALID_SIGNATURE';
  die();
}

// reszta ipn

Dostępne globalne typy danych:

  1. TransactionStatusEnum - Enum(transaction_new, transaction_confirmed, transaction_generated, transaction_paid, transaction_failed, transaction_expired, transaction_canceled, transaction_refunded)
  2. RefundStatusEnum - Enum(refund_new, refund_pending, refund_completed, refund_rejected, refund_failed)

Dostępne wartości w polu type:

transaction:status_changed - zmiana statusu transakcji

Dane w polu data:

PoleTypOpisPrzykładowa wartość
idUUIDID transakcji przesyłany po wygenerowaniu transakcji00554475-7ebb-4f16-b30b-0ce21da1a03b
payer_transaction_idchar(8)ID transakcji pokazywane płacącemu4878R2PN
service_idchar(8)Identyfikator usługie65c7519
statusTransactionStatusEnumStatus transakcjitransaction_paid
amountObiektObiekt informacji o kwocie
amount.final_currencyISO 4217Waluta, w której płacący dokonał płatnościPLN
amount.final_valuestring (%.2f)Finalna kwota, którą płacący zapłacił (np. "0.30", "10.00", "12.37")8.47
amount.original_currencyISO 4217Waluta, która była zadeklarowana przy inicjacji płatnościEUR
amount.original_valuestring (%.2f)Zadeklarowana kwota przy inicjacji płatności (np. "0.30", "10.00", "12.37")2.00
amount.commission_systemstring (%.2f) or nullKwota prowizji, która została pobrana przez SimPay (np. "0.30", "10.00", "12.37")0.13
amount.commission_partnerstring (%.2f) or nullKwota prowizji, która została dla Partnera (np. "0.30", "10.00", "12.37")0.13
amount.commission_currencyISO 4217 or nullWaluta, w której została pobrana prowizja (PLN/EUR)PLN
controlstringPole przesyłane tylko wtedy, gdy zostało przekazane podczas inicjacji płatnościSHOP_ORDER_1
paymentObiektPole z informacjami o płatności
payment.channelstringKanał płatności, którym zapłacił płacącyblik
payment.typestringTyp/grupa metody płatnościblik
customerObiektObiekt informacji o płacącym
customer.country_codeISO 3166-1 Alpha-2 or nullKraj kupującego (np. "PL")PLN
paid_atISO 8601 or null (może nie być przesyłane, kiedy transakcja nie opłacona)Data i czas zapłaty2025-05-26T15:10:24Z
created_atISO 8601Data i czas utworzenia transakcji2025-05-26T15:09:59Z

Przykładowy wysyłany event (dla ipn key = UwSkKiIwlxIeOMF8MIq9iDkQWBTtjoJQ):

{
  "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"
}

transaction_refund:status_changed - zmiana statusu zwrotu

Dane w polu data:

PoleTypOpisPrzykładowa wartość
idUUIDID zwrotu SimPay0194837c-69df-71dd-adff-4b3058f3fb58
service_idchar(8)Identyfikator usługie65c7519
statusRefundStatusEnumStatus zwroturefund_completed
amountObiektObiekt informacji o kwocie
amount.currencyISO 4217Waluta, w której zlecono zwrotPLN
amount.valuestring (%.2f)Kwota, zlecona w zwrocie8.47
amount.wallet_currencyISO 4217Waluta portfela, z którego pobrano środkiEUR
amount.wallet_valuestring (%.2f)Kwota, którą pobrano z portfela2.00
transactionObiektPole z informacjami o płatności
transaction.idUUIDID transakcji SimPay00554475-7ebb-4f16-b30b-0ce21da1a03b
transaction.payment_channelstringKanał płatności, którym zapłacił płacącyblik
transaction.payment_typestringTyp/grupa metody płatnościblik

Przykładowy wysyłany event (dla ipn key = UwSkKiIwlxIeOMF8MIq9iDkQWBTtjoJQ):

{
  "type": "transaction_refund:status_changed",
  "notification_id": "0196ff00-376d-7399-a457-d166c9adf073",
  "date": "2025-05-23T23:15:26+02:00",
  "data": {
    "id": "0194837c-69df-71dd-adff-4b3058f3fb58",
    "service_id": "e65c7519",
    "status": "refund_completed",
    "amount": {
      "currency": "PLN",
      "value": "1.00",
      "wallet_currency": "PLN",
      "wallet_value": "1.00"
    },
    "transaction": {
      "id": "e568d9ba-a85a-444c-87c4-3b1e431428d1",
      "payment_channel": "paysafecard",
      "payment_type": "paysafe"
    }
  },
  "signature": "835819c5720c74f01b8d10a58b2dc43185f05379ea26f25a15158061f3bce10c"
}

ipn:test - testowe powiadomienie

To powiadomienie można wysłać z Panelu Klienta.

Dane w polu data:

PoleTypOpisPrzykładowa wartość
service_idchar(8)Identyfikator usługie65c7519
noncestringLosowy ciąg znaków01JVZCXGZ77DJTM08WMSX34ETQ

Przykładowy wysyłany event (dla ipn key = UwSkKiIwlxIeOMF8MIq9iDkQWBTtjoJQ):

{
  "type": "ipn:test",
  "notification_id": "0196fece-c3e7-71ba-ac8a-ac64056d7d6b",
  "date": "2025-05-23T22:21:25+02:00",
  "data": {
    "service_id": "e65c7519",
    "nonce": "01JVZCXGZ77DJTM08WMSX34ETQ"
  },
  "signature": "02df1a420def7e5de9b316d2bd1ef70796f50abc461561a85bb1243f0a08984d"
}