Uzgodnienie płatności i sprawozdań PSP
TL; DR
Pojednanie jest codziennym zautomatyzowanym ściegiem rejestru i zdarzeń (auth/capture/refund/payout) z raportami PSP/acquirer/bank. Klucz do sukcesu: pojedynczy model danych, deterministyczne klucze dopasowujące, ścisła idempotencja, suma/FX/tolerancje czasu, kolejka DLQ dla kontrowersyjnych przypadków i auto-korekty odtwarzaczy. KPI: Współczynnik niedopasowania Recon, Starzenie się niekonsekwentnie, Auto-match%.
1) Dlaczego i co sprawdzamy
Cele: potwierdzenie przychodów i prowizji, duplikat/wykrywanie strat, prawidłowe rozliczenie według dni i walut, kontrola zwrotu do źródła, zgodność z audytem/regulatorem.
Obiekty pojednania:- Depozyty: 'auth → capture → settle'
- Refundacje: pełne/częściowe, statusy i kwoty
- Wypłaty/wypłaty: Płatności metodą wychodzącą
- Opłaty i korekty: opłaty PSP, systemy wymiany, korekty
- Obciążenia zwrotne/spory: poza Twoją inicjatywą
- FX/Konwersje: stawki, spready, punkt ustalający
2) Źródła danych
Wydarzenia wewnętrzne: autobus imprezowy/Kafka, 'payments _ flat', 'refunds', 'payouts', Twój Ledger.
Raporty PSP (wysypisko SFTP/API/webhook):- Transakcje (sprawozdania operacyjne)
- Osiedle/partie
- Opłaty/wyciągi
- Obciążenia zwrotne/spory
- Wypłaty/rejestry OCT/RTP/SEPA
- Wyciągi bankowe: CAMT MT940/CSV/ISO20022, lift kredytowy.
3) Dopasowanie kluczy
Drzewo klucza priorytetowego (malejące w dokładności):1. provider_txid i provider_txid (niepowtarzalny identyfikator PSP)
2. idempotency_key/ merchant_reference (jeśli stabilne w PSP)
3. (kwota, waluta, timestamp_bucket, last4/bin, auth_code)
4. Warstwa zamazana: ± tolerancje według sumy/czasu, BIN/kraj emitenta, rodzina statusu
Zalecenia:- Zachowaj zarówno 'payment _ id', jak i' provider _ txid '.
- W przypadku częściowego/zwrotu dodaj 'sequence _ index' lub 'refund _ line _ id'.
- Дла payouts - 'payout _ batch _ id + line_id'.
- Dla FX - 'exec _ id' (konwersja) i źródło kursu.
4) Model danych (warstwa znormalizowana)
json
{
"source": "INTERNAL PSP_TX PSP_SETTLEMENT BANK",
"provider": "Acquirer_A",
"payment_id": "pay_123",
"provider_txid": "psp_tx_789",
"kind": "AUTH CAPTURE REFUND PAYOUT FEE SETTLEMENT CHARGEBACK",
"sequence": 0,
"amount": 100. 00,
"currency": "EUR",
"fee_amount": 1. 20,
"fx_rate": 1. 0000,
"fx_src": "PSP ECB BANK",
"status": "APPROVED CAPTURED SUCCESS FAILED SETTLED",
"event_ts": "2025-11-03T12:00:00Z",
"settlement_date": "2025-11-05",
"account": "PSP_MERCHANT_CARD_A",
"matching_keys": {
"provider_txid": "psp_tx_789",
"merchant_ref": "mr_456",
"idem_key": "idem_abc"
},
"hash_row": "sha256(...)"
}
5) Proces pojednania (ETL/orkiestra)
1. Ingest: bierzemy raporty PSP (SFTP/API), zatwierdzamy schemat/podpisy, zapisujemy do „raw”.
2. Normalizacja: mapa pola do jednolitego formatu (waluta ISO, przecinki, strefa czasowa UTC).
3. Mecz: algorytm dopasowywania drzewa kluczowego do tolerancji.
4. Po dopasowaniu: formularz diff (rozbieżności) i wpisy dziennika do księgi/poprawek.
5. Rozrachunek: ściegi 'PSP _ ROZLICZENIA- BANK' (zasilanie konta), scatter według dnia/partii.
6. Raport: deska rozdzielcza, wpisy; kontrowersyjne w DLQ do ręcznego parsowania/auto-replaying.
Idempotencja: dla każdego pliku/strony - 'ingest _ id'. Przeładunek nie zmienia wyniku.
6) Tolerancje i zasady
Czas: '± 15 min' dla transakcji, '± 1 dzień' dla rozrachunku.
Kwota: '≤ 0. 01 "waluta bazowa lub" ≤ 10 punktów bazowych "dla różnic w oprocentowaniu/opłacie.
FX: dopuszczamy rozbieżności z bankiem, jeśli źródło kursu wymiany jest inne; naprawić 'fx _ src'.
Częściowe/wielokrotne: Suma linii częściowych/zwrotów musi być równa bilansowi wewnętrznemu.
7) Taksonomia różnicowa
8) Księgowość i księgowość
Przechwytywanie: „DR Accounts Receivable/CR Revenue”, „DR Cash (po rozliczeniu )/CR Accounts Receivable”
Opłata: „Opłaty DR/CR Cash or Payable”
Zwrot: reverse postings pro rata częściowy
Obciążenie zwrotne: oddzielne konta i rezerwy na spory
Korekta FX: dzienna aktualizacja wyceny bilansu AR/cache w „fx _ src _ policy”
9) KPI i cele
Automatyczne dopasowanie% = linie automatycznego dopasowania/wszystkie linie (95% ≥ cel)
Oszacowanie współczynnika niedopasowania = linie różnicowe/wszystkie linie (≤ 1-2%)
Starzenie się Unconciled: p50/p95 dni w DLQ (p95 ≤ 3 dni)
Czas rozliczenia: odsetek partii zszywanych z bankiem D-day (≥ 99%)
Dokładność opłat: rozbieżności w opłatach dostawcy (≤ 0. 1% obrotów)
Duplikat/sierota Incydenty: Dążenie do 0
10) plasterki SQL
10. 1 Podstawowe dopasowanie provider_txid
sql
WITH i AS (
SELECT provider, provider_txid, kind, amount, currency, event_ts
FROM internal_norm
),
p AS (
SELECT provider, provider_txid, kind, amount, currency, event_ts
FROM psp_norm
)
SELECT
COALESCE(i. provider_txid, p. provider_txid) AS txid,
COALESCE(i. provider, p. provider) AS provider,
i.kind AS kind_internal, p. kind AS kind_psp,
i.amount AS amount_internal, p. amount AS amount_psp,
i.currency, p. currency,
CASE
WHEN i.provider_txid IS NULL THEN 'MISSING_INTERNAL'
WHEN p. provider_txid IS NULL THEN 'MISSING_PSP'
WHEN ABS(i. amount - p. amount) > 0. 01 THEN 'AMOUNT_MISMATCH'
ELSE 'MATCHED'
END AS recon_status
FROM i
FULL OUTER JOIN p USING (provider, provider_txid);
10. 2 Bank rozrachunku
sql
SELECT s. settlement_date, s. batch_id, s. currency,
s. amount_settled, b. amount_bank,
(b. amount_bank - s. amount_settled) AS diff
FROM psp_settlements s
LEFT JOIN bank_statements b
ON b. value_date = s. settlement_date
AND b. currency = s. currency
AND ABS(b. amount_bank - s. amount_settled) <= 0. 5;
10. 3 Starzenie DLQ
sql
SELECT diff_type,
COUNT() AS cnt,
PERCENTILE_CONT(0. 5) WITHIN GROUP (ORDER BY AGE(NOW(), created_at)) AS p50_age,
PERCENTILE_CONT(0. 95) WITHIN GROUP (ORDER BY AGE(NOW(), created_at)) AS p95_age
FROM recon_dlq
GROUP BY diff_type
ORDER BY cnt DESC;
11) Cechy dotyczące szyn/przypadków
Mapy: różnice między 'auth' i 'capture', późne 'settlement' korekty, opłata interchange/circuit - oddzielne linie.
A2A/Open Bankowość/RTP: natychmiastowe potwierdzenie, ale możliwe „cofnięcie”; sprawdź 'wypłatę' i zwroty.
Portfele: często doskonały 'provider _ txid', szybki 'zwrot'; Uważaj na linie opłat.
Bony: brak symetrycznego zwrotu pieniędzy - prawidłowe odzwierciedlenie w polityce i raportach.
Krypta: skrót łańcucha provider_txid; potwierdzenia N; księgowanie prowizji sieciowych i ewentualnych rabatów; kurs wymiany - w momencie konwersji.
12) Operacyjne playbooks
Przepięcie w MISSING_INTERNAL: sprawdź utratę haków/przekładek, powtórz spożycie, włącz ankietę API.
AMOUNT_MISMATCH z jednego PSP: porównaj model zaokrąglania/VAT/opłaty, poproś o wyciąg z korekty.
Rozliczenie nie łączy się z bankiem: data sprawdzenia wartości, opłaty bankowe, opóźnienia T + N; tymczasowo umieszczone na „Rachunku Zawieszenia”.
Masa REFUND_OVER: natychmiastowe zatrzymanie auto-refands, audyt iempotencji, ręczne korekty.
FX_DRIFT: ustalić politykę źródła kursu walutowego (EBC/PSP/BANK), ponownie obliczyć różnice w P & L.
13) Kontrola i bezpieczeństwo
Idempotencja spożycia: 'file _ id + checksum' i pobierz historię.
Dostęp (RBAC) i sterowanie 4-okiem: do ręcznych korekt/wpisów dziennika.
Ścieżka audytu: wszystkie dopasowania/dyfracje/korekty - w niezmiennym dzienniku.
Jakość danych: systemy, obowiązkowe pola, walidacja waluty/skali.
14) Deska rozdzielcza i wpisy
Widżety: Automatyczne dopasowanie%, Wskaźnik niedopasowania, Starzenie DLQ, Rozrachunek czasu, Dokładność opłaty, Top PSP przez diff, Mapa typu diff.
Wpisy:- 'Auto-match% <90%' przez dostawcę/dzień → P1
- „Starzenie p95> 3 dni” → P2
- „KWOTA _ NIEDOPASOWANIE” → P1
- „Rozrachunek bankowy” według kwoty/waluty → P0
15) Skrzynki testowe (UAT/Prod)
1. Przeładowanie tego samego pliku → 0 działań niepożądanych (idempotencja).
2. Częściowe odmowy (3 linie) → ilość meczów, dopasowanie według sekwencji.
3. Konwersja FX: rozbieżność kursu wymiany w ramach tolerancji → prawidłowy mecz.
4. Duplikat provider_txid w raporcie → dedup i alert.
5. Brakujące przechwytywanie webhook → sondaż zamknął lukę, stan jest wyrównany.
6. Partia rozliczeń z linią opłat → poprawny podział na przychody/opłata/netto.
16) Częste błędy i jak uniknąć
Porównaj 'próba' vs 'capture' → zachować tę samą ziarnistość.
Brak 'provider _ txid' w → log traci dokładność meczu.
Ignoruj timezon → przesunięcie przez daty rozliczenia.
Nie ma DLQ/retras → „wieczne” rozbieżności.
Ręczne edycje bez dziennika → niezgodność z audytem.
Fuzzy tolerancje → albo ponowny mecz lub „wszystko w DLQ”.
17) Lista kontrolna wdrażania
- Ujednolicony system normalizacji oraz katalogi PSP/metody/kont
- Mapowanie drzewa klucza (txid → merchant_ref → fuzzy)
- Tolerancje kwoty/czasu/FX, Polityka źródła kursu
- Idempotent ingestion, DLQ, retrai, alerty
- Uzgodnienie rozliczeniowe, Zasady dotyczące rachunku zawieszonego
- KPI tablicy rozdzielczej, sprawozdawczość finansowa/audytowa
- Playbooks i SLA parsing cases diff
Podsumowanie
Pojednanie to dyscyplina inżynieryjna: normalizacja, niezawodne klucze, tolerancje, automatyczne zapałki i przejrzyste korekty. Dzięki takiemu konturowi stabilizujesz przychody i prowizje, minimalizujesz „czarne dziury”, przyspieszasz okres zamykania i poddawaj się audytowi bez bólu: Auto-match%, Mismatch, Aging, Sylwetka.