对账付款和PSP报告
TL;DR
对账是使用PSP/收购商/银行报告对您的Ledger和事件(auth/capture/refund/payout)进行每日自动缝合。成功的关键是: 单一的数据模型,确定性匹配密钥,严格的幂等性,总和/FX/时间的推力,有争议案件的DLQ队列以及自动校正的花花公子。KPI: Recon Mismatch Rate↓, Aging of Unreconciled↓, Auto-match%↑.
1)为什么,我们检查什么
目标:确认收入和佣金,发现倍数/损失,在日子和货币上正确定位,对来源进行再融资控制,与审计/监管机构保持一致。
对照对象:- Deposits: `auth → capture → settle`
- Refunds:完整/分区、状态和金额
- Payouts/Withdrawals:方法外付款
- Fees&Adjustments:PSP佣金,互换计划,校正
- Chargebacks/Disputes:超出您的计划
- FX/转换:课程,利差,固定时刻
2)数据来源
Internal Events(您的):事件总线/Kafka, "payments_flat"、"refunds"、"payouts",您的Ledger。
PSP Reports (SFTP/API/webhook dump):
交易(操作摘录)
Settlements/Batches(T+N入学人数细目)
Fees/Statements(佣金,调整)
Chargebacks/Disputes
Payouts/OCT/RTP/SEPA登记册
银行统计:MT940/CSV/ISO20022 CAMT,贷款整顿。
3)映射键(匹配键)
优先键树(精度降低):1.provider_txid ↔ provider_txid(唯一PSP ID)
2.idempotency_key/ merchant_reference(如果PSP稳定)
3.(amount, currency, timestamp_bucket, last4/bin, auth_code)
4.Fuzzy层:± tolerans的总和/时间,BIN/issuer国家,状态家庭
建议:- 同时存储两者:"payment_id"和"provider_txid"。
- 对于partial/refund-添加"sequence_index"或"refund_line_id"。
- Для payouts — `payout_batch_id + line_id`.
- 对于FX是"exec_id"(转换)和课程来源。
4)数据模型(归一化层)
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)核对过程(ETL/编排)
1.Ingest:拿起PSP报告(SFTP/API),验证方桉/签名,保存在"原始"中。
2.Normalize:将字段映射到统一格式(currency ISO、decimals、UTC时区)。
3.Match:一种用于与tolerans进行密钥树匹配的算法。
4.后对决:我们形成diff(差异)和journal entries for leder/校正。
5.定位:缝合"PSP_SETTLEMENT ↔ BANK"(入账),分布在白天/蹦床上。
6.报告:dashboard,Alerts;在DLQ中因手动分析/自动重新设计而引起争议。
相同性:每个文件/页面为"ingest_id"。重新加载不会改变结果。
6)Tolerance(tolerances)和规则
时间:"± 15分钟"用于交易,"± 1天"用于定居。
总和:'≤ 0。FX/fee差异的01'基本货币或'≤ 10 bps'。
FX:如果汇率来源不同,我们允许与银行发生差异;捕获"fx_src"。
Partial/Multiple:分区/返还线上的总和应等于内部余额。
7)差异处理(diff taxonomy)
8) Ledger&Accounting(布线)
Capture: `DR Accounts Receivable / CR Revenue` и `DR Cash (upon settle) / CR Accounts Receivable`
Fee: `DR Fees / CR Cash or Payable`
退款: 反向布线与部分成正比
Chargeback: 单独账户和争议准备金
FX reval: 根据"fx_src_policy"课程每天重新评估AR/缓存余额'
9) KPI和目标
Auto-match%=自动映射行/所有行(目标≥ 95%)
Recon Mismatch Rate=diff行/所有行(≤ 1-2%)
Aging of Unreconciled: p50/p95 days in DLQ (p95 ≤ 3 dn)
Settlement Timeliness: 与D-Day银行缝合的蹦床比例(≥ 99%)
Fee Accuracy: 提供商佣金的差异(≤ 0.1%的营业额)
Duplicate/Orphan Incidents: 瞄准0
10) SQL切片
10.1基本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 Settlement ↔ Bank
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 Aging 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)铁路/案例功能
地图:"auth"和"capture"之间的差异,后来的"settlement"调整,间距/电路匹配是单独的线条。
A2A/Open 银行/RTP:即时确认,但"反向"是可能的;钻探"payout"和退货。
钱包:通常是完美的"provider_txid",快速的"refund";跟随球队。
凭证:没有对称的返还-在政策和报告中正确反映。
Crypto:ake-chane hash ↔ provider_txid;N confirms;考虑到网络的佣金和可能的重建;课程在转换时。
12)操作花花公子
MISSING_INTERNAL激增:检查webhook/Retraes的丢失,重新播放ingestion,启用polling API。
AMOUNT_MISMATCH一个PSP:比较四舍五入/VAT/fee模型,要求纠正声明。
定居点不与银行缝合:检查价值日期,银行佣金,T+N延迟;暂时放入"Suspense帐户"。
质量REFUND_OVER:立即停止自动反射,同步性审计,手动校正。
FX_DRIFT:记录政策课程来源(ECB/PSP/BANK),重新计算P&L差额。
13)控制与安全
等效性ingestion: "file_id+checksum"和下载日志。
可用性(RBAC)和4眼控制:手动校正/日记接线。
审核跟踪:所有比赛/演示/更正-在不变日志中。
数据质量:电路,强制性字段,货币/滑轨验证。
14)Dashbord和Alerts
小部件:自动匹配%、Mismatch Rate、Aging DLQ、Settlement Timeliness、Fee Accuracy、顶级PSP diff、diff类型卡。
Alerts:- "Auto-match% <90%"按供应商/日→ P1
- 'Aging p 95>3 dn' → P2
- `AMOUNT_MISMATCH spike` → P1
- 按金额/货币计算的"Bank≠Settlement" → P0
15)测试桉例(UAT/Prod)
1.重新加载同一文件→ 0个副作用(等效性)。
2.部分重构(3行)→总和匹配,顺序匹配。
3.FX转换:tolerance内的课程差异→正确的匹配。
4.报告中的重复provider_txid → dedup和alert。
5.失踪的webhook捕捉→ polling关闭插槽,状态对齐。
6.带有fee线路的定居点战斗在Revenue/Fee/Net上→正确的细分。
16)经常出错以及如何避免
比较基的混合(compare'attempt'vs' capture)→保持相同的粒度。
博客中缺少"provider_txid" →比赛的准确性丢失。
忽略时间区→定点日期的偏移。
没有DLQ/转发 →"永恒"差异。
没有日志的手动编辑→审计不一致。
模煳的tolerans →羽毛比赛或"all in DLQ"。
17)实施控制清单
- 统一归一化方案和PSP/方法/帐户指南
- 映射密钥树(txid → merchant_ref → fuzzy)
- Tolerans 按金额/时间/FX,课程来源政策
- Idempotent ingestion, DLQ, retraies, Alertes
- Settlement↔Bank核对,Suspense帐户政策
- Dashbord KPI,财务/审计报告
- Playbooks和SLA分析diff桉例
总结
和解是一门工程学科:正常化,可靠的密钥,tolerans,自动匹配和透明校正。有了这样的轮廓,您将稳定收入和佣金,尽量减少"黑洞",加快周期关闭并进行审计而不会感到痛苦:Auto-match%↑,Mismatch↓,Aging↓。