Reconcilierea plăților și rapoartelor PSP
TL; DR
Reconcilierea este coaserea zilnică automată a registrului și evenimentelor (auth/capture/rambursare/plată) cu rapoartele PSP/achizitor/bancar. Cheia succesului: un singur model de date, chei de potrivire deterministe, idempotență strictă, toleranțe de sumă/FX/timp, coadă DLQ pentru cazuri controversate și playbook-uri de corecție automată. KPI: Recunoașterea nepotrivirii Rate↓, îmbătrânirea Unreconciled↓, Auto- match%↑.
1) De ce și ce verificăm
Obiective: confirmarea veniturilor și comisioanelor, detectarea duplicatelor/pierderilor, decontarea corectă pe zile și valute, controlul rambursării la sursă, respectarea regulatorului/auditului.
Obiecte de reconciliere:- Depozite: 'auth → capture → settle'
- Restituiri: integral/parțial, statusuri și sume
- Plăți/retrageri: Metode de plată
- Taxe și ajustări: comisioane PSP, scheme interbancare, corecții
- Chargebacks/Dispute: Dincolo de inițiativa dvs
- FX/Conversii: rate, spread-uri, punct de fixare
2) Surse de date
Evenimente interne: event bus/Kafka, 'payments _ flat', 'ramburss', 'payouts', your Ledger.
Rapoarte PSP (dump SFTP/API/webhook):- Tranzacții (declarații operaționale)
- Așezări/Loturi
- Taxe/Declarații
- Chargebacks/Litigii
- Plăți/OCT/RTP/SEPA registre
- Extrase de cont: CAMT MT940/CSV/ISO20022, ridicare de credit.
3) Chei de potrivire
Arbore cheie prioritar (descrescător în precizie):1. provider_txid ↔ provider_txid (ID unic PSP)
2. idempotency_key/ merchant_reference (dacă este stabil în PSP)
3. (suma, moneda, timestamp_bucket, last4/bin, auth_code)
4. Strat fuzzy: toleranțe ± în funcție de sumă/timp, țara BIN/emitent, familia de statut
Recomandări:- Păstrați atât 'payment _ id' cât și' provider _ txid '.
- Pentru parțială/rambursare, adăugați 'sequence _ index' or 'refund _ line _ id'.
- Для plăți - 'payout _ batch _ id + line_id'.
- Pentru FX - ' _ id' (conversie) și sursa ratei.
4) Modelul de date (strat normalizat)
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) Procesul de reconciliere (ETL/orchestrare)
1. Ingera: luăm rapoartele PSP (SFTP/API), validăm schema/semnăturile, salvăm la „raw”.
2. Normalizați: mappim al câmpului la formatul unificat (ISO valutar, zecimale, fusul orar UTC).
3. Meci: algoritm pentru potrivirea arborelui cheie cu toleranțe.
4. Post-meci: forma diff (discrepanțe) și intrările în jurnal pentru registru/corecții.
5. Decontare: cusătură 'PSP _ SETTLEMENT ↔ BANK' (creditare în cont), scatter pe zi/lot.
6. Raport: tablou de bord, alerte; controversat în DLQ pentru parsare manuală/auto-reluare.
Idempotence: pentru fiecare fișier/pagină - 'ingest _ id'. Reîncărcarea nu schimbă rezultatul.
6) Toleranțe și reguli
Timp: „± 15 min” pentru tranzacții, „± 1 zi” pentru decontare.
Suma: '≤ 0. 01 "monedă de bază sau" ≤ 10 bps "pentru diferențe FX/taxă.
FX: permitem discrepanța cu banca dacă sursa cursului de schimb este diferită; fix 'fx _ src'.
Parțial/Multiplu: Suma liniilor parțiale/de rambursare trebuie să fie egală cu soldul intern.
7) Diff taxonomy
8) Registru & Contabilitate
Captură: 'DR Accounts Receivable/CR Revenue' и 'DR Cash (la decontare )/CR Accounts Receivable'
Taxa: 'DR Taxe/CR Cash sau Payable'
Rambursare: postări inverse pro rata parțială
Chargeback: conturi separate și rezervă pentru litigii
Reval FX: reevaluarea zilnică a soldului AR/cache la 'fx _ src _ policy'
9) KPI-uri și obiective
Auto-meci% = linii de auto-meci/toate liniile (95% ≥ țintă)
Rata de neconcordanță de recunoaștere = linii diff/toate liniile (≤ 1-2%)
Îmbătrânirea neconciliată: p50/p95 zile în DLQ (p95 ≤ 3 zile)
Timpul de decontare: proporția loturilor cusute cu banca D-day (≥ 99%)
Acuratețea taxei: discrepanțele dintre comisioanele furnizorului (≤ 0. 1% din cifra de afaceri)
Incidente duplicate/orfane: cu scopul 0
10) Felii SQL
10. 1 Potrivire provider_txid de bază
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 Decontare ↔ Banca
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 DLQ îmbătrânire
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) Caracteristici pe șine/cazuri
Hărți: diferențe între ajustările „auth” și „capture”, reglajele „late”, taxa interbancară/circuit - linii separate.
A2A/Open Banking/RTP: confirmări instantanee, dar „inversare” posibilă; check 'plată' și se întoarce.
Portofele: adesea perfect „provider _ txid”, rapid „rambursare”; urmăriți liniile de taxare.
Vouchere: nici o rambursare simetrică - se reflectă corect în politică și rapoarte.
Cripto: hash on-chain ↔ provider_txid; confirmări N; contabilizarea comisioanelor de rețea și eventualele reduceri; cursul de schimb - la momentul conversiei.
12) Playbook-uri operaționale
Supratensiune în MISSING_INTERNAL: verificați pierderea cârligelor/retraielor, rejucați ingestia, activați sondarea API.
AMOUNT_MISMATCH de la un PSP: comparați modelul de rotunjire/TVA/taxă, solicitați o declarație de corecție.
Decontarea nu se leagă de bancă: data valorii de verificare, comisioane bancare, întârzieri T + N; temporar pus în „Contul de suspans”.
REFUND_OVER de masă: auto-refands oprire imediată, audit de idempotență, corecție manuală.
FX_DRIFT: fixați politica sursei cursului de schimb (BCE/PSP/BANK), recalculați diferențele P&L.
13) Control și siguranță
Idempotența ingestiei: 'file _ id + checksum' și istoricul descărcărilor.
Access (RBAC) și 4-eye control: pentru corecții manuale/intrări jurnal.
Traseu de audit: toate meciurile/diffs/corecții - într-un jurnal neschimbabil.
Calitatea datelor: scheme, câmpuri obligatorii, validare valută/scară.
14) Tabloul de bord și alerte
Widget-uri: Auto-meci%, Rata de nepotrivire, Imbatranire DLQ, Decontare timp, Taxa de precizie, top PSP de diff, diff-tip hartă.
Alerte:- 'Auto-match% <90%' de către furnizor/zi → P1
- 'Imbatranire p95> 3 zile' → P2
- 'CUANTUM _ MISMATCH spike' → P1
- 'Bank≠Settlement' după sumă/monedă → P0
15) Cazuri de testare (UAT/Prod)
1. Reîncărcarea aceluiași fișier → 0 efecte secundare (idempotență).
2. Refandurile parțiale (3 linii) → suma se potrivește, se potrivesc după secvență.
3. Conversia FX: discrepanța cursului de schimb în toleranța → potrivirea corectă.
4. Duplicați provider_txid în raport → dedup și alertă.
5. Captura lipsă a cârligului web → sondarea au închis decalajul, starea este aliniată.
6. Lot de decontare cu linie de taxare → defalcare corectă pe Venituri/Taxe/Net.
16) Greșeli frecvente și cum să evitați
Comparați „încercare” vs „captură” → păstrați aceeași granularitate.
Absența 'provider _ txid' în jurnalul → pierde acuratețea meciului.
Ignorați fusul orar → compensate de datele de decontare.
Nu există discrepanțe DLQ/retras → „eterne”.
Editări manuale fără un jurnal → neconcordanță cu auditul.
Toleranțele fuzzy → fie o re-meci sau „toate în DLQ”.
17) Lista de verificare a implementării
- Schema de normalizare unificată și directoarele PSP/metodă/cont
- Mapping Key Tree (txid → merchant_ref → fuzzy)
- Suma/Toleranțe de timp/FX, Politica sursei cursului
- Idempotent ingestie, DLQ, retrai, alerte
- Reconcilierea Settlement↔Bank, Politica contului de suspans
- Tablou de bord KPI, raportare financiară/audit
- Playbooks și SLA defilare cazuri diff
Rezumat
Reconcilierea este o disciplină inginerească: normalizare, chei de încredere, toleranțe, meciuri automate și corecții transparente. Cu un astfel de contur, stabilizați veniturile și comisioanele, minimizați „găurile negre”, accelerați închiderea perioadei și vă auditați fără durere: Auto- match%↑, Mismatch↓, Aging↓.