本手册围绕 DGJ2 的采购在线支付、预订单支付、销售收款、退款、待退款账户、返利、授信/白条、还款、账户调整、提现和对账核销,建立“支付中心消息 -> 业务单 -> 收付款单 -> 账户流水 -> 业务状态”的完整排查路径。
适用于支付成功业务单没推进、付款单重复/缺失、退款不到账、账户余额异常、授信还款重复、金额相差 100 倍、回调重复投递和迟到支付等问题。所有生产修复都必须先确认金额单位、业务唯一键和外部最终状态。
1. 业务目标
- 从支付单号、采购单号、预订单号、退款/售后号任一标识找到完整资金链。
- 正确计算
sid%32收付款分片和sid%16账户分片。 - 区分外部支付金额“分”和本地财务金额“元”。
- 解释 Payment 主单、PaymentInfo 明细、Account 流水和 PoOrderPayInfo 快照各自职责。
- 判断回调在消息校验、业务定位、财务落账、状态推进还是后置副作用处失败。
- 让支付成功、退款、余额调整和授信还款在重复投递下保持幂等。
- 修复后同时核对外部支付、业务单、财务单、账户、报表和特殊来源业务。
2. 六层资金模型
flowchart LR
EXT["支付中心订单/回调"] --> BIZ["采购/预订单/销售/售后"]
EXT --> PAY["Payment收付款主单"]
PAY --> PI["PaymentInfo结算明细"]
PI --> ACC["Account账户流水"]
EXT --> SNAP["PoOrderPayInfo支付构成快照"]
BIZ --> REPORT["往来账/报表"]
PAY --> REPORT
ACC --> REPORT
| 层 | 回答的问题 | 不能替代 |
|---|---|---|
| 支付中心 | 外部最终支付/退款结果 | DGJ 本地是否完整落账 |
| 业务单 | 这笔钱为哪张订单服务 | 账户实际增减 |
| Payment | 生成了哪张收款/付款/收入/支出单 | 每个账户分摊 |
| PaymentInfo | 每个账户、结算对象和业务单的金额 | 账户余额汇总 |
| Account | 账户余额如何变化 | 原业务履约状态 |
| PoOrderPayInfo | 采购支付方式、折扣、返利、退款账户构成 | Payment/Account 的元级财务流水 |
3. 适用现象与首查方向
| 现象 | 首查 | 常见原因 |
|---|---|---|
| 支付中心成功,采购仍待支付 | PayCenterNotify、采购状态 | 回调未到、状态前置不符、事务回滚 |
| 支付成功没有付款单 | 32 分片 Payment/Info | 查错分片、零元订单、回调中途失败 |
| 有付款单但账户流水没有 | AccountService、16 分片账户 | saveAccounts 失败、事务/连接问题 |
| 账户流水有但采购状态没变 | 同一事务和状态更新 | 业务状态更新失败或外部脚本直写财务 |
| 金额相差 100 倍 | 分/元边界 | 外部字段未除 100 或本地字段重复除 100 |
| 付款总额比支付金额大 | 服务费 | Payment 总额包含 serviceAmount |
| 重复支付回调 NACK | 采购状态已推进 | 代码把重复状态识别为错误并要求重试 |
| 支付超时后又成功 | 迟到支付 | 采购状态 12 仍允许成功回调 |
| 退款回调后普通退款没财务单 | 回调职责 | paycenterRefundResult 当前主要处理专属授信返还 |
| 退款账户余额不对 | 账户类型和退款事件 | 退款/提现/支付抵扣不同事件混淆 |
| 授信还款重复生成支出单 | 还款幂等键 | bill_no/state 未正确判断 |
| 调整单重复 | adjustNo | PaymentInfo 未保存或查错站点分片 |
| 销售收全款未核销 | 出库金额和 PaymentInfo | stlId 错、有效状态过滤、差额口径 |
| 逾期锁站状态错误 | 逾期消息 | lockStatus、时间门槛、菜单规则失败 |
4. 排查前事实卡
环境:
回调事件/routing key:
回调时间:
sourceOrderType:
sourceOrderNo / afterSaleNo:
payOrderNo / refundNo / adjustNo:
sid:
业务单 id / billNo / 当前状态:
mainPayTypeCode:
外部总金额(分):
外部明细金额(分):
本地 Payment 金额(元):
本地 PaymentInfo 汇总(元):
Account 汇总(元):
PoOrderPayInfo 金额(分):
是否包含服务费/折扣/返利/待退款/授信:
是否重复回调或迟到支付:
5. 分表和核心表
5.1 收付款:32 分片
t_scm_payment_{sid % 32}
t_scm_payment_info_{sid % 32}
PaymentModel、PaymentInfoModel 的 setSid() 已确认使用该规则。
5.2 账户:16 分片
t_scm_account_{sid % 16}
t_scm_account_info_{sid % 16}
ScmAccountSubModel、ScmAccountInfoSubModel 使用该规则。
5.3 非同规则表
| 表 | 分片 | 用途 |
|---|---|---|
t_scm_po_order_payinfo | 当前 Model 单表 | 采购支付构成快照 |
t_scm_repayment_order | 当前 Model 单表 | 授信还款单 |
t_scm_payment_log | 以线上 DDL/Model 为准 | 收付款操作日志 |
th_scm_account | 历史表 | 往月账户金额/流水 |
采购主单 t_scm_po_order | 不按 sid 分片 | 在线支付业务单 |
销售出库 t_scm_sa_invoice_0_{sid%64} | 64 分片 | 销售应收和核销对象 |
flowchart TB
SID["sid"] --> M32["sid % 32"]
SID --> M16["sid % 16"]
SID --> COL["单表sid字段"]
M32 --> P["payment_n"]
M32 --> PI["payment_info_n"]
M16 --> A["account_n"]
M16 --> AI["account_info_n"]
COL --> POI["po_order_payinfo"]
COL --> REPAY["repayment_order"]
5.4 常见误查
- 查
t_scm_payment基表,漏新 32 分片。 - Payment 用 32 后缀,Account 也机械使用 32,实际应为 16。
- 把
PoOrderPayInfo.iid当 Payment 主单 ID,实际主要关联采购/预订单业务 ID。 - 用 Payment
billNo反查业务单,而业务关联稳定字段是 PaymentInfostlId/stlNo。 - 跨月只查当前账户分片,不考虑
th_scm_account。
6. 入口与代码地图
6.1 PC/业务入口
| 业务 | Controller/Service |
|---|---|
| 付款 | application/controllers/scm/Payment.php |
| 收款 | application/controllers/scm/Receipt.php |
| 对账 | application/controllers/scm/AccCheck.php |
| 采购支付 | application/controllers/scm/InvPo.php |
| 销售对账/核销 | application/service/scm/InvSaService.php、ReceiptService.php |
| 授信还款 | Repayment 相关 Controller/Service |
6.2 回调入口
application/controllers/tasks/PayCenterNotify.php 消费:
destination = DEST_PAYCENTER_NOTIFY
6.3 核心 Model/Service
| 模块 | 文件 |
|---|---|
| Payment 主单 | application/models/payment/PaymentModel.php |
| PaymentInfo | application/models/payment/PaymentInfoModel.php |
| 采购支付快照 | application/models/orders/PoOrderPayInfoModel.php |
| Account | application/models/bs/AccountModel.php、application/models/scm/ScmAccount*Model.php |
| 账户写入 | application/service/scm/AccountService.php |
| 还款单 | application/models/payment/RepaymentOrderModel.php |
| 支付回调 | application/controllers/tasks/PayCenterNotify.php |
| 全车件支付 | application/controllers/tasks/QPayCenterNotify.php |
7. Payment 状态和交易类型
7.1 Payment 状态
| 值 | 枚举 | 含义 |
|---|---|---|
| 0 | BILLSTATUS_CONFIRMED | 已确认 |
| 1 | BILLSTATUS_SUBMITED | 已提交 |
| 2 | BILLSTATUS_CONFIRMED1 | 已确认兼容值 |
| 6 | BILLSTATUS_CANCELED | 已撤销 |
报表通常排除 billStatus=6 和 isDelete=1。
7.2 常见资金交易类型
transType | 含义 | 常见方向 |
|---|---|---|
| 153001 | 收款 | 账户增加/应收减少,按业务定义 |
| 153101 | 付款 | 账户支出 |
| 153401 | 其他收入 | 账户增加 |
| 153402 | 其他支出 | 账户减少 |
| 155001 | 预收款 | 客户资金 |
| 155002 | 退款 | 账户退款 |
| 155003 | 余额支出 | 账户扣减 |
| 154001 | 调拨收款 | 收入 |
| 154002 | 调拨付款 | 支出 |
| 150601 | 销售收款/销售出库结算 | 应收 |
| 150602 | 销售退款/销退结算 | 应退 |
| 150501 | 采购付款明细 | 应付 |
| 170401 | 采购订单支付快照主类型 | 采购 |
| 170001 | 预订单支付快照主类型 | 预订单 |
交易类型命名有历史复用,必须联合 billType + transType + stlId/stlNo 判断。
8. 支付中心十类事件
| 事件 | Handler | 主要副作用 |
|---|---|---|
| 支付结果 | paycenterPayResult | Payment/Info/Account/PayInfo、业务状态 |
| 额度调整 | paycenterBalanceAdjust | 收入/支出单和账户 |
| 提现退款结果 | paycenterRefundWithdrawResult | 提现状态、支出单、待退款账户 |
| 授信线上还款 | paycenterBaitiaoReturnPayResult | 还款单、支出明细、账户 |
| 授信线下还款 | paycenterBaitiaoOfflineReturnPayResult | 新建已还款单、支出和账户 |
| 授信到期 | paycenterBaitiaoExpire | 站内信/短信提醒 |
| 支付异常 | paycenterPayException | 取消待支付采购单 |
| 分期到期 | paycenterInstallmentExpire | 到期提醒 |
| 退款结果 | paycenterRefundResult | 当前主要返还专属授信活动额度 |
| 服务站逾期变化 | paycenterBaitiaoServiceOverdueChange | 锁定/解锁菜单 |
flowchart LR
Q["支付中心MQ"] --> D{"routing key"}
D --> PAY["支付结果"]
D --> EX["支付异常"]
D --> REF["退款/提现"]
D --> BAL["额度调整"]
D --> BT["授信还款/到期"]
PAY --> DB["财务+业务事务"]
REF --> DB
BAL --> DB
BT --> DB
9. 金额单位矩阵
这是财务排查最重要的口径。
| 字段/表 | 典型单位 | 代码证据 |
|---|---|---|
回调 detailTotalAmount | 分 | Payment 总额写入时 /100 |
回调 details[].payAmount | 分 | PaymentInfo 写入时 /100 |
回调 serviceAmount | 分 | PaymentInfo 合并后 /100 |
| 回调折扣/返利/退款明细 | 分 | PoOrderPayInfo 直接保留 |
Payment.totalAmount | 元 | detailTotalAmount/100,再加服务费 |
PaymentInfo.amount | 元 | (payAmount+serviceAmount)/100 |
| Account 流水金额 | 元 | 由 PaymentInfo 传入,方向另处理 |
PoOrderPayInfo.amount/rebate/refund/... | 分 | 支付构成原始值直接写入 |
PoOrderPayInfo.service_amount | 分 | 累加原始服务费 |
RepaymentOrder.amount/interest/late_fee | 多数按外部分保存 | 展示/生成 PaymentInfo 时 /100 |
9.1 正确金额关系
Payment.totalAmount(元)
= (detailTotalAmount(分) + sum(serviceAmount分)) / 100
sum(PaymentInfo.amount元)
= sum(payAmount分 + serviceAmount分) / 100
PoOrderPayInfo 不应直接与 Payment 元字段数值相等,应先统一单位。
flowchart LR
CENT["支付中心金额 分"] --> DIV["除以100"]
DIV --> PAY["Payment 元"]
DIV --> INFO["PaymentInfo 元"]
INFO --> ACC["Account 元"]
CENT --> SNAP["PoOrderPayInfo 分"]
10. 支付成功回调定位
10.1 脱敏消息示例
{
"sourceOrderNo": "PO-DEMO-20260715-001",
"sourceOrderType": "01",
"payOrderNo": "PAY-DEMO-001",
"mainPayTypeCode": "02",
"payStatus": "02",
"payStatusMsg": "支付成功",
"existsCashDiscount": "0",
"cashDiscountRate": "100",
"cashDiscountAmount": "0",
"detailTotalAmount": "12345",
"payTime": "2026-07-15 10:00:00",
"details": [
{
"payAccountTypeCode": "02",
"payAccountTypeDesc": "示例付款账户",
"payAmount": "12345",
"serviceAmount": "0"
}
]
}
10.2 外部成功判断
payStatus 必须等于 '02'
非 02 当前返回 NACK;需要结合支付中心重试协议确认失败状态是否应该持续重投。
10.3 业务类型
sourceOrderType | 本地业务 |
|---|---|
01 | 采购单 |
04 | 预订单 |
11. 采购支付成功完整流程
sequenceDiagram
participant PC as 支付中心
participant N as PayCenterNotify
participant PO as 采购主单
participant P as Payment32分片
participant PI as PaymentInfo32分片
participant A as Account16分片
participant S as PoOrderPayInfo
PC->>N: pay_result payStatus=02
N->>PO: 按sourceOrderNo查采购
N->>N: 校验状态10或12
N->>P: 写付款主单
N->>PI: 按支付账户写明细
N->>A: 写账户流水
N->>S: 写支付构成快照(分)
N->>PO: 状态改为1并记录paymentTime
N->>N: 特殊来源后置处理
N-->>PC: ACK
11.1 可接受采购状态
支付成功回调只接受:
- 10 待支付。
- 12 支付超时。
其他状态被视为状态错误或重复消息,当前代码抛异常并 NACK。
11.2 落账字段
Payment 主单:
billType=PAYMENT/FKD路径。transType=153101付款。totalAmount为元,包含服务费。sid/uid/buId来自采购单。
PaymentInfo:
- 一种支付账户一条明细。
transType=150501采购付款明细。paymentType=1标识在线支付。stlId=采购单.id。stlNo=采购单.billNo。amount=(payAmount+serviceAmount)/100元。
Account:由 AccountService::saveAccounts() 根据 PaymentInfo 生成。
PoOrderPayInfo:保存主支付类型、折扣、返利、待退款账户、服务费等原始分值。
11.3 业务状态
回调末尾:
采购 billStatus -> 1 已提交
paymentTime -> payTime
auditOpinion -> payStatusMsg
秒杀来源 13 还会调用 FlashSaleSer::markPaidByPoOrder() 转活动数量。
12. 事务与后置副作用
支付主链在采购 Model 数据库事务中完成:
- Payment。
- PaymentInfo。
- Account。
- PoOrderPayInfo。
- 采购状态。
- 秒杀支付转量。
事务提交后才执行部分工单同步。因此:
| 失败点 | 财务/采购 | 后置工单 | 处理 |
|---|---|---|---|
| 事务内失败 | 回滚 | 未执行 | 消息 NACK 重试 |
| 提交成功、工单失败 | 已成功 | 失败 | 只补工单,不重放支付主链 |
| ACK 丢失 | 已成功 | 可能成功 | 重复消息需幂等识别 |
13. 幂等与重复回调
13.1 当前状态门槛
采购支付成功后状态从 10/12 改成 1。重复回调再次进入时,状态不在允许集合,会抛“状态错误或者消息重复”并 NACK。
这能阻止重复入账,但不一定是最佳 MQ 语义:已完成的重复消息更适合识别为幂等成功并 ACK,否则可能形成无意义重试/死信。线上策略需要确认。
13.2 数据库幂等键建议
| 数据 | 业务唯一键候选 |
|---|---|
| 外部支付 | payOrderNo |
| 采购支付 | sourceOrderType + sourceOrderNo |
| PaymentInfo | stlId + accId + 外部支付号 |
| PoOrderPayInfo | sid + iid + billNo + transType,需结合多次支付规则 |
| 余额调整 | sid + adjustNo |
| 授信还款 | bill_no |
| 提现退款 | 提现单业务号 |
13.3 重复测试
同一成功消息连续投递两次,预期:
- Payment 不新增第二张。
- PaymentInfo 不新增第二组。
- Account 不重复变化。
- PoOrderPayInfo 不重复。
- 采购状态保持正确。
- 秒杀
used_qty不重复增加。 - 第二次应有明确幂等日志和稳定 ACK 策略。
14. 迟到支付
采购状态 12 支付超时仍被允许处理成功回调。这是为支付中心迟到成功保留的恢复路径,但风险更高:
- 超时任务可能已释放活动锁量。
- 采购可能已经触发关闭/取消。
- 专属授信额度可能已释放。
- 页面已允许用户重新下单。
flowchart TD
A["状态12收到成功回调"] --> B["确认支付中心最终成功"]
B --> C["确认采购关闭副作用"]
C --> D["确认活动/库存/额度是否已释放"]
D --> E["事务内恢复采购和财务"]
E --> F["补回特殊来源占用"]
F --> G["检查是否重复新订单"]
专属授信超时后迟到支付代码会重新扣活动额度,注释已提示可能导致额度为负,这是已知高风险场景。
15. 零元订单
当主支付类型为零元订单:
- 回调会短暂等待以降低订单未落库竞态。
- 采购路径可跳过常规 Payment/PaymentInfo 构建,直接推进业务状态。
- 排查时“没有付款单”可能是符合设计,不应直接补财务单。
必须用 mainPayTypeCode 和订单金额共同证明零元语义。
16. 混合支付
16.1 支付账户构成
一笔支付可包含:
- 对公/对私账户。
- 授信/白条。
- 融资或银行账户。
- 待退款账户。
- 普通返利、专属返利。
- 现金折扣。
16.2 主支付类型修正
- 明细含多个主支付账户时,支付快照类型标记为混合支付。
- 授信与返利/待退款混合时,展示类型可能强制按授信。
- 主类型为待退款账户时,快照类型可转换为兼容值。
16.3 对账关系
外部 detailTotalAmount
= sum(details.payAmount)
本地 PaymentInfo 总额
= sum((payAmount + serviceAmount)/100)
Payment.totalAmount
= (detailTotalAmount + sum(serviceAmount))/100
折扣、返利和待退款账户要按支付中心合同判断是否包含在 detailTotalAmount,不能重复相加。
17. 预订单支付
17.1 与采购的差异
| 维度 | 采购 | 预订单 |
|---|---|---|
| sourceOrderType | 01 | 04 |
| 业务定位 | 采购主单 | PreOrderService |
| 主交易类型快照 | 170401 | 170001 |
| 财务单 | 一张付款单多账户明细 | 每个支付账户可生成一张其他支出单 |
| 状态推进 | 采购状态 1 | payedPreOrder() |
预订单可支付状态包含待支付、取消、自动取消,说明迟到支付同样需要特别核对释放副作用。
17.2 预订单账户方向
预订单其他支出写 Account 前会把 PaymentInfo 金额转为负数,表示账户支出;PaymentInfo 本身仍按正金额展示业务支出。
18. 支付异常
paycenterPayException:
- 用
sourceOrderNo查采购单。 - 调用
PoOrderSer::cancelWaitPayOrder(orderId, true, exceptionDesc)。 - 成功 ACK,异常 NACK。
sequenceDiagram
participant PC as 支付中心
participant N as PayCenterNotify
participant PO as PoOrderSer
participant SRC as 活动/预订单来源
PC->>N: pay_exception
N->>PO: cancelWaitPayOrder
PO->>PO: 关闭待支付采购
PO->>SRC: 释放来源占用
N-->>PC: ACK/NACK
排查时确认异常取消是否同时释放秒杀锁量、预订单占用和专属额度。
19. 退款结果
19.1 当前回调职责
paycenterRefundResult 遍历退款明细;当前静态代码重点处理:
- 退款账户类型为授信。
- 退款金额大于 0。
- 售后单是未履约退货类型。
- 找到原采购和专属授信活动。
- 把金额返还到专属授信活动额度。
它不是一套完整通用退款财务入账实现。看到普通退款回调 ACK,不代表 Payment/Account 已自动生成退款流水,需追踪发起退款的业务 Service。
19.2 退款排查
- 固定
afterSaleNo和退款业务号。 - 查售后/退货采购单和原采购单。
- 查支付中心最终退款状态和明细账户。
- 查退款财务单由哪个入口创建。
- 查 Account 方向和待退款账户。
- 授信退款再查活动额度。
- 重复回调不应重复返还额度。
20. 额度调整
20.1 幂等键
paycenterBalanceAdjust 先用 sid + adjustNo 查 PaymentInfo。已有记录时视为已处理。
20.2 方向
| 调整类型 | 本地业务 | 交易类型 |
|---|---|---|
| 调增 | 其他收入 | 153401 |
| 调减 | 其他支出 | 153402 |
每个子账户明细会创建/复用系统账户,授信额度调整不一定直接生成普通收入单,需按代码分支理解。
20.3 异常
adjustNo未落 PaymentInfo,重复回调无法识别。- 系统账户不存在时自动创建失败。
- 供应商映射不到时使用兼容客户,需评估报表口径。
- 多明细中途失败依赖事务整体回滚。
21. 提现退款结果
该事件连接:
提现申请 -> 审核结果 -> Payment/PaymentInfo -> 待退款账户 -> Account -> 通知
成功路径通常:
- 更新提现状态。
- 生成其他支出单。
- PaymentInfo 金额由分转元。
- 写 Account 前金额转负。
- 发送站内信。
注意:通知发送失败是否影响事务/重试,需要按具体位置判断;补偿通知时不要重放已落账主链。
22. 授信/白条还款
22.1 还款单状态
state | 含义 |
|---|---|
| 0 | 未还款 |
| 1 | 已还款 |
| 2 | 还款失败/取消 |
状态 1 设置 pay_time;状态 2 只允许从 0 更新并记录取消人/时间。
22.2 线上/自动还款
paycenterBaitiaoReturnPayResult:
- 用
sourceNo查还款单。 - 自动还款可在本地不存在时创建还款单。
- 已
state=1视为重复。 - 本金、利息、滞纳金按 details 拆 PaymentInfo。
- 外部分金额
/100写元。 - 写 Account 前转负数。
- 更新还款单金额和状态。
22.3 线下还款
paycenterBaitiaoOfflineReturnPayResult:
- 用
orderNo幂等。 - 创建已还款状态 RepaymentOrder。
- 生成其他支出 Payment/Info。
- 写负向账户流水。
22.4 幂等风险
当前重复还款被抛异常并可能 NACK。与采购支付相同,业务已完成的重复消息更适合稳定幂等 ACK,需确认生产重试协议。
sequenceDiagram
participant PC as 支付中心
participant N as PayCenterNotify
participant R as RepaymentOrder
participant P as Payment/Info
participant A as Account
PC->>N: 授信还款结果
N->>R: 按bill_no查状态
alt 已还款
N-->>PC: 幂等结果
else 未处理
N->>P: 本金/利息/滞纳金明细
N->>A: 负向账户流水
N->>R: state=1/pay_time
N-->>PC: ACK
end
23. 到期提醒与逾期锁站
23.1 到期提醒
- 授信到期消息查服务站和待还列表。
- 发送站内信和短信。
- 任一通知失败可能 NACK,导致重复提醒;需确认消费者重试和通知幂等。
- 分期到期金额字段可能直接是元,不能套用所有回调都按分的假设。
23.2 逾期菜单锁定
锁定状态:
| 外部状态 | 动作 |
|---|---|
| 01 未锁定 | 解锁菜单 |
| 02 锁定中 | 10:00 后锁定菜单 |
| 03 延期锁定 | 解锁菜单 |
单个站点异常会记录并继续处理列表中其他站点,整体消息可能仍 ACK,因此必须监控每站处理结果。
24. 销售收款、对账和核销
24.1 关联键
PaymentInfo.stlId = 销售出库单.id
PaymentInfo.stlNo = 销售出库单.billNo
PaymentInfo.sid = 出库单.sid
销售出库表按 _0_{sid%64},PaymentInfo 按 sid%32。
24.2 核销公式
出库 amount == 有效收款 payAmount + diffAmount
或出库 amount == 0
-> 出库状态5、hxStateCode=2
否则
-> 出库状态4 已对账
24.3 有效收款过滤
isDelete=0。billStatus<>6。transType属于销售收款/退款口径。stlId指向正确出库分片记录。- 日期区间与报表截止时间一致。
25. 一笔采购支付全景 SQL
仅在只读连接执行。字段和唯一键以目标环境 DDL 为准。
25.1 采购和支付快照
select id, sid, billNo, billStatus, paymentType, paymentTime,
srcOrderType, srcOrderId, srcOrderNo, amount, totalQty
from t_scm_po_order
where billNo = :po_bill_no;
select id, sid, iid, billNo, transType, type,
amount, discount, rebate, refund, exclusive_rebate,
service_amount
from t_scm_po_order_payinfo
where sid = :sid and iid = :po_order_id
order by id;
25.2 Payment/PaymentInfo
-- :pay_suffix = sid % 32
select id, sid, billNo, billType, transType, totalAmount,
buId, billStatus, isDisable, createTime, isDelete
from t_scm_payment_:pay_suffix
where sid = :sid
and id in (
select iid from t_scm_payment_info_:pay_suffix
where sid = :sid and stlId = :po_order_id and isDelete = 0
);
select id, iid, sid, billNo, billType, transType,
amount, diffAmount, accId, wayId, paymentType,
stlId, stlNo, stlDate, billStatus, createTime, isDelete
from t_scm_payment_info_:pay_suffix
where sid = :sid and (stlId = :po_order_id or stlNo = :po_bill_no)
order by iid, id;
25.3 Account
-- :account_suffix = sid % 16
select *
from t_scm_account_:account_suffix
where sid = :sid and iid in (:payment_ids)
order by createTime, id;
select *
from t_scm_account_info_:account_suffix
where sid = :sid and iid in (:account_ids)
order by createTime, id;
账户表实际关联字段需按线上 DDL 和 AccountService 写入结构确认。
26. 金额对账 SQL
26.1 Payment 与明细
select p.id, p.billNo, p.totalAmount,
coalesce(sum(case when i.isDelete=0 and i.billStatus<>6 then i.amount else 0 end),0) as info_amount
from t_scm_payment_:pay_suffix p
left join t_scm_payment_info_:pay_suffix i on i.iid = p.id and i.sid = p.sid
where p.sid = :sid and p.id in (:payment_ids)
group by p.id, p.billNo, p.totalAmount;
含服务费、多账户和特殊收入/支出拆单时,需要按同一业务单汇总多张 Payment,不能强制一张主单等于全部明细。
26.2 重复候选
select stlId, stlNo, transType, accId, amount, count(*) as cnt
from t_scm_payment_info_:pay_suffix
where sid = :sid and isDelete = 0 and billStatus<>6
group by stlId, stlNo, transType, accId, amount
having count(*) > 1;
混合支付、分次收付款可能合法,必须结合外部支付号和创建时间判断。
27. 支付成功故障树
flowchart TD
A["支付成功业务未推进"] --> B{"消息到达?"}
B -->|否| B1["查支付中心/routing/binding"]
B -->|是| C{"payStatus=02?"}
C -->|否| C1["失败消息NACK策略"]
C -->|是| D{"业务单存在?"}
D -->|否| D1["sourceOrderType/No错误或竞态"]
D -->|是| E{"状态为10或12?"}
E -->|否| E1["重复回调或非法状态"]
E -->|是| F{"Payment/Info写入?"}
F -->|否| F1["事务内异常"]
F -->|是| G{"Account/PayInfo完整?"}
G -->|否| G1["账户/支付构成断点"]
G -->|是| H{"业务状态已更新?"}
H -->|否| H1["事务回滚/跨连接"]
H -->|是| I["查特殊来源后置状态"]
28. 按现象执行 SOP
28.1 支付成功仍待支付
- 查回调日志和消息体摘要。
- 确认
payStatus='02'。 - 用
sourceOrderType/sourceOrderNo查业务单。 - 查回调前状态是否 10/12。
- 计算 32 分片查 Payment/Info。
- 计算 16 分片查 Account。
- 查 PoOrderPayInfo。
- 查事务异常和 NACK 重试。
- 特殊来源查秒杀/预订单状态。
28.2 本地有两张付款单
- 按
stlId/stlNo找所有 PaymentInfo。 - 反查 Payment 主单和创建时间。
- 区分正常混合支付附加收入单与重复主付款单。
- 查同一外部 payOrderNo 的回调次数。
- 查采购状态在第一次回调后是否及时改变。
- 查唯一键和事务提交/ACK 顺序。
28.3 金额相差 100 倍
- 标注每个字段单位。
- 外部原始值统一为分。
- Payment/Info/Account 统一换算成分比较,或全部换成元。
- PoOrderPayInfo 不先除 100 就不要与 Payment 比。
- 单独加入 serviceAmount。
- 折扣/返利/待退款确认是否包含在总额。
28.4 退款不到账
- 查发起退款的售后/关闭业务。
- 查支付中心退款最终状态。
- 查
afterSaleNo和原支付单关系。 - 查退款账户类型。
- 查实际创建退款 Payment/Account 的 Service,不只看
paycenterRefundResult。 - 授信退款查活动额度返还。
- 查重复回调和幂等结果。
28.5 授信还款重复
- 查
repayment_order.bill_no/state。 - 查自动、线上还是线下还款。
- 查 32 分片 PaymentInfo 的
stlId/stlNo。 - 查 16 分片 Account。
- 查本金、利息、滞纳金拆分。
- 查重复消息是 ACK 还是 NACK,是否持续重试。
28.6 销售已收款未核销
- 查 64 分片出库
amount/hxStateCode/billStatus。 - 查 32 分片 PaymentInfo。
- 排除状态 6 和软删。
- 计算有效
amount+diffAmount。 - 确认
stlId指向出库 ID。 - 查对账/核销回写日志。
29. 补偿与修复决策
flowchart TD
A["财务链不一致"] --> B["冻结业务单并保存六层快照"]
B --> C{"支付中心最终状态?"}
C -->|失败/未支付| D["不得补成功财务"]
C -->|成功| E{"本地业务状态?"}
E --> F{"财务单完整?"}
F -->|否| G["单支付号幂等补账"]
F -->|是| H{"账户流水完整?"}
H -->|否| I["通过AccountService补账户"]
H -->|是| J["只补业务/特殊来源状态"]
G --> K["金额单位和影响行数复核"]
I --> K
J --> K
29.1 修复优先级
- 原支付/退款回调的幂等补偿入口。
- 业务 Service 的状态恢复/取消接口。
- Payment/Account 领域 Service。
- 单支付号、带断言的修复脚本。
- 最后才直接 SQL,必须同步修正所有关联层。
29.2 禁止操作
- 只改采购
billStatus。 - 只插 Payment,不写 PaymentInfo/Account。
- 把 PoOrderPayInfo 分值当元写入 Payment。
- 删除重复财务单前不判断账户流水。
- 未确认支付中心最终状态就重放成功回调。
- 用随机 MQ 消息 ID 当支付幂等键。
30. 回归测试矩阵
30.1 采购支付
- [ ] 普通在线支付成功。
- [ ] 零元订单。
- [ ] 多账户混合支付。
- [ ] 待退款账户/返利/专属返利。
- [ ] 服务费支付。
- [ ] 重复成功回调。
- [ ] 状态 12 迟到支付。
- [ ] 支付异常取消。
- [ ] 秒杀来源支付转量。
30.2 预订单
- [ ] 正常待支付成功。
- [ ] 取消/自动取消后迟到支付。
- [ ] 多账户拆其他支出单。
- [ ] 重复回调不重复入账。
30.3 退款和调整
- [ ] 采购关闭退款。
- [ ] 采购退货退款。
- [ ] 普通账户退款和授信退款。
- [ ] 专属额度返还一次。
- [ ] 余额调增/调减。
- [ ] 同 adjustNo 重复回调。
- [ ] 提现成功/失败通知。
30.4 授信
- [ ] 线上还款、自动还款、线下还款。
- [ ] 本金/利息/滞纳金拆分。
- [ ] 重复还款消息。
- [ ] 到期/分期提醒。
- [ ] 逾期锁站、延期解锁、10点门槛。
30.5 销售财务
- [ ] 未收、部分收、全部收。
- [ ] 零金额核销。
- [ ] 对账和撤销对账。
- [ ] 销退退款。
- [ ] 64/32 分片关联。
31. 监控建议
| 指标 | 维度 | 告警 |
|---|---|---|
| 支付成功回调 NACK | sourceOrderType/原因 | 连续/重复状态突增 |
| 成功支付无 Payment | sid/业务单 | 超短延迟仍缺失 |
| Payment 无 Account | sid/paymentId | 任意新增 |
| 业务状态与财务不一致 | 业务类型 | 任意新增 |
| 金额单位异常 | 业务单 | 比例接近100倍 |
| 迟到支付 | sourceType | 状态12成功回调 |
| 重复财务明细 | stlId/accId | 超合法账户数 |
| 退款未完成 | afterSaleNo | 超 SLA |
| 还款回调 NACK | billNo | 重复积压 |
| 逾期锁站部分失败 | sid | 单站失败也告警 |
32. 已确认与待确认
32.1 静态代码已确认
- Payment/PaymentInfo 按
sid%32。 - Account/AccountInfo 按
sid%16。 - PoOrderPayInfo 和 RepaymentOrder 当前 Model 使用单表。
- Payment 状态为 0/1/2/6。
- 支付中心注册十类事件。
- 成功支付要求
payStatus='02'。 - 采购成功回调接受状态 10 和 12。
- 外部支付金额主要为分,Payment/Info/Account 主要按元。
- PoOrderPayInfo 主要保存原始分值。
- Payment 总额和明细包含服务费。
- 成功回调在一个事务中写财务、账户、支付快照和业务状态。
- 采购支付后状态改为 1,秒杀来源转 locked 到 used。
- 重复支付/还款当前多以异常/NACK 处理。
- 普通退款财务不由
paycenterRefundResult单独完整负责。 - 余额调整用
adjustNo幂等。 - 授信还款单状态为 0/1/2。
- 逾期锁站消息对列表内单站失败会继续处理。
32.2 环境待确认
- 支付中心各事件投递保证、重试和死信策略。
- 业务已完成的重复消息是否允许 ACK。
- Payment/Account 线上唯一键和历史双写边界。
th_scm_account归档策略。- 外部每个金额字段的正式单位合同,尤其分期到期元字段。
- 普通退款财务单的当前生产创建入口。
- 支付中心与 DGJ 对迟到支付的最终仲裁规则。
- 混合支付、服务费和折扣的报表口径。
- 全车件
QPayCenterNotify与主回调的业务边界。 - 财务报表 DWD/Hologres 同步 SLA。
33. 证据来源
| 主题 | 文件 |
|---|---|
| 支付事件和主流程 | application/controllers/tasks/PayCenterNotify.php |
| 支付状态 | application/KzData/Enums/PaymentEnums.php |
| 账户类型 | application/KzData/Enums/AccountEnums.php |
| 交易类型 | application/KzData/Enums/TransTypeEnums.php |
| 采购状态 | application/KzData/Enums/PoOrderEnums.php |
| Payment Model | application/models/payment/PaymentModel.php |
| PaymentInfo Model | application/models/payment/PaymentInfoModel.php |
| 采购支付快照 | application/models/orders/PoOrderPayInfoModel.php |
| Account 分片 | application/models/scm/ScmAccountSubModel.php |
| AccountInfo 分片 | application/models/scm/ScmAccountInfoSubModel.php |
| 账户写入 | application/service/scm/AccountService.php |
| 授信还款单 | application/models/payment/RepaymentOrderModel.php |
| 销售核销 | application/service/scm/InvSaService.php、ReceiptService.php |
| 秒杀支付 | application/Services/Activity/FlashSaleSer.php |
34. 一页式执行结论
先固定外部支付号、sourceOrderType/sourceOrderNo 和 sid。
Payment/Info 查 sid%32,Account/Info 查 sid%16,采购支付快照和还款单另查单表。
支付中心和PoOrderPayInfo主要是分,Payment/Info/Account主要是元,比较前先统一单位。
支付成功主链要同时核对业务单、Payment、PaymentInfo、Account、PoOrderPayInfo和特殊来源。
采购状态10/12可收成功回调;状态12迟到支付必须检查此前释放副作用。
重复回调不能重复落账;已完成重复消息的ACK/NACK策略需要环境确认。
普通退款不要只看paycenterRefundResult,它当前重点处理专属授信额度返还。
修复必须以支付中心最终状态为仲裁,优先用幂等补偿和领域Service。
请求-日志-数据变更追踪卡
多入口请求链路
| 场景 | 调用方与入口 | 请求载荷/上下文 | Controller/Consumer | Service/Provider | 汇合点 | 最终业务事实 |
|---|---|---|---|---|---|---|
| 付款/收款制单 | PC Payment/Receipt/采购销售入口 | 来源单、账户、金额、支付方式 | 财务/采购/销售 Controller | Payment/Receipt/Account Service | 财务单号 + 来源单号 | 付款、收款、应收应付分录 |
| 支付中心成功 | DEST_PAYCENTER_NOTIFY | payOrderNo、来源单、状态、金额 | PayCenterNotify | Payment/业务 Service | 支付单号 | 支付落账并推进采购/活动 |
| 快钱/其他通道 | QPayCenterNotify 等 | 通道单号、状态、金额 | 对应 Consumer | 通道适配/资金 Service | 外部通道单 + 本地支付单 | 通道结果映射本地财务状态 |
| 退款/还款 | 退款回调、RepaymentOrder 流程 | 原支付单、退款/还款单、金额 | Consumer/财务入口 | Refund/Repayment Service | 原支付关系 | 退款或授信额度返还一次完成 |
日志证据矩阵
| 链路段 | 日志来源 | 可检索锚点 | 成功信号 | 失败信号 | 与下一段关联方式 | | --- | --- | --- | --- | --- | --- | --- | | 发起支付 | Controller/Provider | request_id、来源单、payOrderNo、金额 | 支付中心受理且本地关系保存 | 调用超时、金额单位/账户错误 | payOrderNo 串联请求与回调 | | 支付回调 | PayCenterNotify | message ID、payOrderNo、来源单、payStatus=02 | ACK 且本地支付只记一次 | 非 02、重复落账、迟到支付 | 支付关系查来源订单状态 | | 账户分录 | Account Service/Model | 财务单、账户 ID、前后余额 | 分录和余额同事务一致 | 余额不足、借贷不平、部分提交 | 分录号与主单/账户关联 | | 退款还款 | Refund/Repayment Consumer/Service | 原支付单、退款单、授信单 | 原支付与返还金额闭合 | 重复返还、找不到原支付 | 原支付单贯穿正反两笔资金 |
环节数据变更台账
| 步骤 | 代码位置 | 事务 | 读取事实 | 写入表/缓存/MQ | 字段或数量变化 | 回查证据 |
|---|---|---|---|---|---|---|
| 创建财务单 | Payment.php/Receipt.php + Service | 财务事务 | 来源应付/应收、账户、金额 | SCM_PAYMENT*/收款及业务关系表 | status 初始化;金额和分摊明细 insert | 财务单、来源单、明细合计 |
| 外部受理 | 支付 Provider | DB 外部边界 | 待支付单和金额 | 支付中心、本地通道关系 | 本地待支付 -> 外部处理中;超时不等于失败 | payOrderNo、Provider 返回码 |
| 成功落账 | PayCenterNotify::paycenterPayResult | 回调事务 | 回调成功、当前支付/业务状态 | SCM_PAYMENT、SCM_PAYMENT_INFO、SCM_PO_ORDER_PAYINFO 等 | 首次 insert/confirmed;业务 10/12 -> 后续态;重复回调 0 增量 | payOrderNo、金额、状态、流水条数 |
| 账户核销 | AccountService | 账户事务 | 余额、未核销金额 | SCM_ACCOUNT*、分录/关系 | balance old +/- n;已核销 +n | 前后余额 + 分录净额 |
| 退款/还款 | refund/repayment Service | 反向资金事务 | 原支付成功事实、已退金额 | refund/repayment 表、账户/授信关系 | 已退 +n;额度/余额按规则返还,最大不超过原额 | 原支付、退款单、通道最终状态 |
子模块追踪:finance-pay-request 支付发起与受理
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 发起支付 | 采购/财务入口创建支付请求 | request ID、来源单、sid、账户/金额 | application/controllers/scm/Payment.php -> application/service/scm/AccountService.php | 来源应付、支付方式、账户可用额、已有支付关系 | 本地财务事务创建待支付主明细 none -> pending;支付中心调用在事务外 | request ID + sourceOrderNo + local/payOrderNo | 外部超时不能直接判失败;按 payOrderNo 查受理结果再重试 |
| 受理回查 | 支付中心返回或查询结果 | payOrderNo、外部 code、金额 | application/controllers/tasks/PayCenterNotify.php | 本地待支付关系和外部订单状态 | 查询阶段 DB 不变;受理仅表示处理中,不做成功落账 | payOrderNo + sourceOrderNo + provider code | 本地无关系但外部有单时先补关系,避免再次发起扣款 |
子模块追踪:finance-pay-success 支付成功回调
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 成功消费 | DEST_PAYCENTER_NOTIFY pay result | message ID、payOrderNo、payStatus=02、来源单 | application/controllers/tasks/PayCenterNotify.php | 本地支付状态、来源业务 10/12 等允许态、已有明细 | 回调本地事务首次写 SCM_PAYMENT*、采购支付关系并推进业务态 | message ID + payOrderNo + sourceOrderNo | 非 02 不走成功;重复消息不得再次插入明细或改变余额 |
| 全景回查 | 支付成功仍待支付 | payOrderNo、采购/秒杀/预订单号 | application/models/payment/PaymentModel.php | Payment/Info、Account、PoOrderPayInfo、来源状态 | 查询只读 不写;金额统一单位后闭环 | payOrderNo + all source billNos | 外部成功本地缺失用幂等回调补偿,禁止单独改来源状态 |
子模块追踪:finance-repeat-late 重复回调与迟到支付
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 幂等判断 | 同 payOrderNo 重复成功消息 | payOrderNo、sourceOrderNo、message ID | application/controllers/tasks/PayCenterNotify.php | 已有 Payment/Info/业务状态和金额 | 单消息本地事务命中已完成则 new -> new、新增明细 0 | multiple message IDs + same payOrderNo | 当前 ACK/NACK 生产策略需环境确认;业务幂等不依赖随机消息 ID |
| 迟到支付 | 采购已超时/关闭后收到成功 | payOrderNo、采购单、关闭/释放记录 | application/KzData/Enums/PoOrderEnums.php | 状态 12/关闭态、外部最终成功、库存/活动释放事实 | 不直接落账或按代码受理后进入补偿决策;跨域变化分事务 | payOrderNo + billNo + close/release IDs | 先冻结自动反向动作,核实资金、采购、秒杀数量账后按规则补偿 |
子模块追踪:finance-zero-mixed 零元与混合支付
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 零元支付 | 应付金额为 0 的订单确认 | sourceOrderNo、应付/优惠金额 | application/controllers/scm/InvPo.php -> application/service/scm/AccountService.php | 原价、优惠、应付和来源状态 | 本地事务直接完成零元资金事实 pending -> paid,不应产生实际扣款 | request ID + sourceOrderNo + amounts | 金额不为零不得走零元分支;重复提交不新增 PaymentInfo |
| 混合支付 | 余额/授信/在线等账户组合 | payOrderNo、账户明细、各渠道金额 | application/KzData/Enums/AccountEnums.php | 各账户可用额、主支付类型和分摊合计 | 财务本地事务写多条分摊,账户 balance/credit old -> new,合计等于应付 | payOrderNo + account IDs/types + amounts | 任一渠道失败按合同回滚/退款已成功部分;主类型不替代明细事实 |
子模块追踪:finance-preorder 预订单支付
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 预订单支付 | 预订单发起并收到支付成功 | preorderNo、payOrderNo、sid | application/controllers/tasks/PayCenterNotify.php | 预订单当前态、应付额、账户方向、关联采购 | 回调本地事务写预订单支付关系并 status: wait_pay -> paid/converted | message ID + preorder/pay/po orderNos | 不套用普通采购账户方向;重复成功不得重复转采购 |
| 售后回查 | 预订单取消或退款 | preorderNo、原支付/退款单 | application/models/payment/PaymentInfoModel.php | 原支付、已退额、售后状态和采购关系 | 反向资金本地事务 refunded +n;查询关系只读 | preorderNo + original/refund payOrderNo | 已转采购需按责任边界处理;不同时退预订单和采购两次 |
子模块追踪:finance-exception 支付异常
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 异常消费 | 支付中心 exception 事件 | message ID、payOrderNo、异常码、来源单 | application/controllers/tasks/PayCenterNotify.php | 当前支付/业务态、外部异常类型、是否已成功 | 单消息本地事务记录异常 normal -> exception;已成功单不被异常消息回退 | message ID + payOrderNo + exception code | 未知异常保留原态并告警;乱序消息先以支付中心最终态仲裁 |
| 人工排查 | 支付卡住、金额或状态不一致 | payOrderNo、sourceOrderNo、时间线 | application/models/payment/PaymentModel.php | 请求、受理、回调、Payment/Info/Account 六层事实 | 查询只读 不写;定位缺失层后只补该层 | request/message IDs + provider/local timestamps | 禁止凭错误文案直接重扣;生产补偿需授权和前后快照 |
子模块追踪:finance-refund 退款与提现退款
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 退款结果 | 普通退款/支付中心退款回调 | 原 payOrderNo、refundNo、金额、message ID | application/controllers/tasks/PayCenterNotify.php | 原成功支付、已退款额、业务关闭/退货事实 | 退款本地事务 refunded: old -> old+n 并写关系;不超过原支付额 | message ID + original/refundNo + amount | 当前专属授信职责与普通退款覆盖需按事件代码确认;重复返还 0 增量 |
| 提现退款 | 提现失败或退回结果 | withdrawNo、account ID、金额 | application/controllers/tasks/QPayCenterNotify.php | 原提现单、通道终态、账户分录 | 反向账户本地事务 balance: old -> old+n、提现态到 refunded | withdraw/refundNo + account entry | 通道超时先查最终态;余额已返只补状态/关系,不再加款 |
子模块追踪:finance-credit 额度调整、授信与白条还款
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 额度调整 | 支付中心额度调整或专属授信回调 | adjustmentNo、account ID、方向、金额 | application/controllers/tasks/PayCenterNotify.php -> application/service/scm/AccountService.php | 账户类型、当前额度、原业务和幂等键 | 账户本地事务 credit: old +/- n 并写分录,单键一次 | message ID + adjustmentNo + account/source ID | 方向错或结果重复不得二次变化;原支付关系缺失进入人工核对 |
| 白条还款 | 线上/自动/线下还款确认 | repaymentNo、授信单、金额、渠道 | application/models/payment/RepaymentOrderModel.php | 应还、已还、逾期状态和账户额度 | 还款本地事务 repaid +n、订单 pending -> partial/paid、额度按规则恢复 | repaymentNo + credit/source orderNo | 线上回调与线下确认必须共享幂等事实,防止同一金额双还 |
子模块追踪:finance-overdue 到期提醒与逾期锁站
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 到期扫描 | 定时任务扫描授信/白条到期记录 | task batch、sid、repaymentNo、dueAt | application/models/payment/RepaymentOrderModel.php | 未还金额、到期时间、上次提醒和站点状态 | 每单本地事务更新提醒/逾期标记 normal -> due/overdue;通知异步 | task + batch + sid/repaymentNo | 时区和调度配置需环境确认;已还清记录扫描零变化 |
| 锁站恢复 | 逾期锁菜单;还清后恢复 | sid、逾期单集合、菜单规则 | application/service/scm/AccountService.php | 站点所有逾期事实和当前白名单/菜单状态 | 权限本地事务 unlocked -> locked 或满足条件 locked -> unlocked | sid + repaymentNos + rule/action | 不因单笔还款恢复仍有其他逾期的站点;权限发布失败只补配置同步 |
子模块追踪:finance-receipt 销售收款、对账与核销
| 环节 | 入口/触发 | 请求/业务键 | 代码链路 | 读取事实 | 写入与字段变化 | 日志证据 | 异常与补偿 |
|---|---|---|---|---|---|---|---|
| 收款核销 | 财务对销售单制收款并核销 | sale/receipt billNo、账户、金额 | application/controllers/scm/Receipt.php -> application/service/scm/InvSaService.php | 销售应收、有效收款、已核/退款额和账户 | 财务本地事务写收款分录,received/verified: old -> old+n | request ID + sale/receipt billNo + transType | 超额、重复来源或账户非法零写入;金额单位先统一 |
| 对账回查 | 对账单金额与销售核销不一致 | statement ID、销售/收款单、时间窗 | application/controllers/scm/AccCheck.php | 有效未软删交易、退款反向、分片和报表口径 | 查询只读 不写;验证应收、已收、已核、未核等式 | statement ID + source/finance billNos | 报表延迟与业务不平分开处理;主账正确时仅补报表/对账任务 |