PSPの支払いとレポートの調整
TL;DR(ドクター)
調整は、PSP/acquirer/bankレポートを使用して、レジャーとイベント(認証/キャプチャ/払い戻し/支払い)の毎日の自動ステッチです。成功への鍵: 単一のデータモデル、決定論的一致キー、厳格なidempotency、 sum/FX/time公差、物議を醸すケースのためのDLQキュー、自動補正プレイブック。KPI: Recon Mismatch Rate(リコンミスマッチ率)、Aging of Unreconciled(和解されていない老化率)、Auto-match%(自動マッチ率)
1)私達が点検する理由そして何
目的:収益と手数料の確認、重複/損失の検出、日数と通貨による正しい決済、ソースへの返金制御、監査/規制当局への準拠。
和解オブジェクト:- 預金:'auth→capture→settle'
- 払い戻し:フル/パーシャル、ステータスと金額
- 支払い/出金:出金方法の支払い
- 料金と調整:PSP料金、交換スキーム、修正
- チャージバック/紛争:あなたのイニシアチブを超えて
- FX/コンバージョン:レート、スプレッド、固定点
2)データソース
内部イベント:イベントバス/カフカ、'payments_flat'、 'refunds'、 'payouts'、あなたの元帳。
PSPレポート(SFTP/API/webhookダンプ):- トランザクション(運用ステートメント)
- 決済/バッチ
- 料金/ステートメント
- チャージバック/紛争
- 支払い/OCT/RTP/SEPAレジストリ
- 銀行明細書:CAMT MT940/CSV/ISO20022、クレジットリフト。
3)一致するキー
優先キーツリー(精度で降順):1.provider_txid ↔ provider_txid(ユニークなPSP ID)
2.idempotency_key/ merchant_reference (PSPで安定している場合)
3.(金額、通貨、timestamp_bucket、 last4/bin、 auth_code)
4.ファジー層:合計/時間による±公差、BIN/発行国、ステータスファミリー
推奨事項:- 'payment_id'と'provider_txid'の両方を保持します。
- 部分的/払い戻しの場合は、'sequence_index'または'refund_line_id'を追加します。
- ペイアウト-'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.インジェスト:PSPレポート(SFTP/API)を取得し、スキーム/署名を検証し、'raw'に保存します。
2.Normalize:フィールドのマッピングを統一フォーマット(通貨ISO、 10進数、UTCタイムゾーン)に変換します。
3.Match:公差とキーツリーを一致させるためのアルゴリズム。
4.マッチ後:帳簿/訂正のフォームdiff(矛盾)とジャーナルのエントリ。
5.Settle: stitch 'PSP_SETTLEMENT ↔ BANK'(口座へのクレジット)、day/batchごとに分散。
6.レポート:ダッシュボード、アラート;手動解析/自動再生のためのDLQで論争。
Idempotence:各ファイル/ページ-'ingest_id'。再ロードは結果を変更しません。
6)許容および規則
時間:トランザクションは'± 15分'、決済は'± 1日'。
Amount: '≤ 0。01'基本通貨または'≤ 10 bps 'FX/料金の違いのために。
FX:為替レートのソースが異なる場合は、銀行との不一致を許可します。'fx_src'を修正しました。
Partial/Multiple: partial/refundラインの合計は内部残高と等しくなければなりません。
7)差分分類
8)元帳・会計
Capture: 'DR Accounts Receivable/CR Revenue' 「DR Cash (settle時)/CR Accounts Receivable」
料金: 「DR手数料/CR現金または支払い」
払い戻し: リバースポスティングプロrata partial
チャージバック: 別々の口座と紛争の予約
FX reval: 'fx_src_policy'でのAR/キャッシュバランスの毎日の再評価'
9) KPIと目標
オートマッチ%=自動マッチライン/全行(95% ≥ターゲット)
Recon Mismatch Rate=差分行/全行(≤ 1-2%)
Unciledの老化: DLQのp50/p95日(p95 ≤ 3日)
決済時間: D日銀行とステッチされたバッチの割合(≥ 99%)
料金精度: プロバイダ料金の相違(≤ 0。売上高の1%)
重複/孤児インシデント: 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銀行↔決済
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
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 Banking/RTP:即座の確認、しかし可能な'逆転';'payout'をチェックして返金します。
財布:多くの場合、完璧な'provider_txid'、クイック'払い戻し';料金ラインを見てください。
バウチャー:対称返金なし-ポリシーとレポートに正しく反映されます。
暗号:オンチェーンハッシュ↔ provider_txid;確認N;ネットワーク手数料と可能なリベートの会計;為替レート-変換時。
12)オペレーション・プレイブック
MISSING_INTERNALのサージ:Webhook/Retrayの損失、リプレイ摂取、APIポーリングを有効にします。
1つのPSPからのAMOUNT_MISMATCH:丸め/付加価値税/料金モデルを比較し、訂正文を要求して下さい。
決済は銀行にリンクされていません:チェックバリュー日付、銀行手数料、T+N遅延;一時的に「サスペンスアカウント」に入れます。
大量REFUND_OVER:即時停止自動リファンド、idempotency監査、手動修正。
FX_DRIFT:為替レートソース(ECB/PSP/BANK)のポリシーを修正し、P&Lの違いを再計算します。
13)制御および安全
Idempotence of ingestion: 'file_id+checksum'とダウンロード履歴。
アクセス(RBAC)および4目コントロール:手動補正/ジャーナル入力用。
監査証跡:変更できないログ内のすべての一致/差分/補正。
データ品質:スキーム、必須フィールド、通貨/スケール検証。
14)ダッシュボードとアラート
ウィジェット:Auto-match%、 Mismatch Rate、 Aging DLQ、決済タイミング、Fee Accuracy、 diffによるトップPSP、 diff-type map。
アラート:- プロバイダ/日→P1による'Auto-match% <90%'
- 「老化p95> 3日」→P2
- 'AMOUNT_MISMATCH spike'→P1
- 金額/通貨別の'Bank≠Settlement'→P0
15)テストケース(UAT/Prod)
1.同じファイルを再読み込み→0の副作用(idempotency)。
2.partial refands (3行)→amount match、 match by sequence。
3.FX変換:許容差→正しいマッチ内の為替レートの不一致。
4.レポート→dedup and alertの重複provider_txid。
5.欠落しているWebhookキャプチャ→ポーリングがギャップを閉じ、ステータスが整列されます。
6.有料回線付き決済バッチ→収益/手数料/ネットの正しい内訳。
16)頻繁な間違いと回避方法
'attempt'と'capture'を比較する→同じ粒度を保持する。
→logに'provider_txid'がないと、マッチの精度が失われます。
決済日ごとにタイムゾーン→オフセットを無視します。
DLQ/retras→「永遠」の矛盾はありません。
ログなしの手動編集→監査との矛盾。
ファジー公差→再マッチまたは「DLQのすべて」のいずれか。
17)実装チェックリスト
- 統一された正規化スキームとPSP/method/accountディレクトリ
- マッピングキーツリー(txid→merchant_ref→fuzzy)
- 量/時間公差/FX、コースソースポリシー
- Idempotent ingestion、 DLQ、 retrai、アラート
- Settlement↔Bank和解、サスペンスアカウントポリシー
- ダッシュボードKPI、財務/監査レポート
- プレイブックとSLA解析差分ケース
概要
和解は、ノーマライゼーション、信頼できるキー、公差、自動マッチ、透明補正などのエンジニアリング分野です。このような輪郭で、収益と手数料を安定させ、「ブラックホール」を最小限に抑え、期間の終了を加速し、痛みなく監査されます。