1. 文档定位

本文说明 DGJ2.0 中“银行通道接入、支付中心结果落账、授信分期与分期还款”三层业务。它面向产品、前端、后端、测试、财务和运维,用于回答以下问题:

  1. 服务站为什么能看到某一种银行或授信通道,注册、签约和二维码分别由谁提供。
  2. 用户完成支付后,采购单、付款单、账户流水和还款单怎样变化。
  3. 分期申请、分期账单、主动还款、自动还款和到期提醒怎样串联。
  4. 外部系统已成功而 DGJ2 未落账时,怎样判断、补偿和验收。

本文依据当前仓库代码整理。外部支付中心、OPS Manager、银行网关的数据库表、生产路由、签名算法和重试策略不在本仓库中,均标为“待外部确认”。

2. 业务边界

2.1 本文包含

  • B2B、工行、工行 E 贷、民生、京东数科、拉卡拉、泰隆、小雨点、网商银行等适配入口。
  • 银行资料、贷款人资料和通道资格查询。
  • 注册、短信、签约、支付二维码、还款二维码、支付链接和状态查询。
  • 支付中心支付成功、支付异常、授信还款、分期到期和逾期锁站回调。
  • 分期签约、可分期判断、分期模型、token、提交、账单、服务费和合同。
  • 分期还款单创建、无页面支付、银联支付、B2B 支付和自动还款落账。
  • 本地付款单、付款明细、账户、采购支付快照和还款单的排查方法。

2.2 本文不包含

  • 专属授信资金池、专属返利、额度冻结、占用和释放的完整算法,见《32_专属授信_返利与资金池》。
  • 通用支付故障的全量排查清单,见《18_财务和支付排查手册》。
  • 采购单创建、支付前状态和支付后履约全流程,见《03_采购_采购退货与采购入库》。
  • 银行侧清结算、对账、拒付、证书轮换和真实商户配置。
  • 支付中心、OPS Manager 内部表结构及其定时任务。

2.3 三层职责

层级主要职责DGJ2 代表代码是否直接认定资金成功
通道适配层查询资格、注册签约、获取二维码或链接、主动查询application/controllers/financial/*、application/Providers/OpsManager/Financial/*否
支付结果层消费支付中心消息,校验业务单,生成财务数据并推进订单application/controllers/tasks/PayCenterNotify.php是,以支付中心成功事件为准
授信分期层分期签约、分期申请、账单查询、还款单创建和还款落账BaitiaoInstallmentSer、两个 Baitiao Provider、RepaymentOrderModel申请成功不等于还款成功;还款以回调为准
flowchart LR
    U[服务站用户] --> C[DGJ2 金融 Controller]
    C --> S[Financial Service 或分期 Service]
    S --> O[OPS Manager / 支付中心]
    O --> B[银行或授信机构]
    B --> O
    O --> M[paycenter_notify]
    M --> N[PayCenterNotify]
    N --> P[付款单和账户流水]
    N --> R[采购单或还款单状态]

3. 参与角色与前置条件

角色主要动作必要上下文典型失败原因
服务站主账号/员工注册、签约、申请分期、发起支付或还款sid、user_id、手机号、菜单权限站点不存在、手机号不匹配、权限被锁
采购业务创建待支付采购单并请求支付billNo、供应商、金额、来源类型单据状态不是待支付、金额不一致
财务人员查看付款、账户和还款结果服务站数据权限、业务单号分表查错、只看主单未看明细
OPS Manager聚合银行和授信接口服务站、承运/供货方编码、账户标识通道未开通、参数映射错误
支付中心创建支付、接收银行结果、投递 MQ来源单号、支付单号、支付类型回调延迟、重复、乱序
银行/授信机构开户签约、收款、放款、分期和还款商户、主体、银行卡、风控材料风控拒绝、签名失败、渠道维护
DGJ2 MQ 消费者将成功结果落入本地账务和业务状态可查询到原单、账户和供应商原单缺失、状态异常、局部写入失败

通用前置条件:

  1. sid 必须对应有效服务站,当前用户必须属于该站点。
  2. 需要支付的采购单通常处于 PoOrderEnums::BILLSTATUS_WAIT_PAY;支付超时的特定预订单提货单有兼容处理。
  3. 银行通道必须完成准入或签约,且 OPS Manager 能查询到对应服务站配置。
  4. 分期业务还需要供货方编码 shipperCode、授信调整单号 adjustNo 或分期单号 installmentNo。
  5. 页面展示“已签约”“可支付”不等于资金已到账,最终必须核对支付中心事件和 DGJ2 财务落账。

4. 代码入口地图

4.1 银行与金融 Controller

Controller公开方法业务用途下游
financial/B2bPay.phpqueryWhite查询 B2B 版本或白名单资格B2bPayProvider
financial/BridgeBank.phpfindbyid、listpage、save、download桥接银行资料维护和下载BridgeBankSer
financial/OtherBank.phpdata、findbyid、listpage、loaner、save、download他行融资预加载、银行和贷款人资料OtherBankSer
financial/Cmbc.phpqueryRegister、sendSms、register民生注册状态、短信和注册CmbcProvider
financial/Icbc.phpgetQRCode、getQRCodeBaitiaoReturn、getQRCodeByActivity工行采购、授信还款和活动支付二维码IcbcProvider
financial/Icbc.phpgetLoanNotify、getQrCodeOfJumpPage放款通知和银行跳转页IcbcProvider
financial/IcbcE.phpableCreateIcbcEAccount、createIcbcEAccount、balance工行 E 账户资格、开户和余额FinancialProvider
financial/Jdsk.phpqueryStatus、queryRefundStatus、payUrl、domain京东数科状态、退款和支付链接JdskProvider
financial/Lakala.phpqueryStatus、sendSms、creditRegInfo、creditReg拉卡拉准入和授信注册LakalaProvider
financial/Lakala.phppayQrcode、repayQrcode拉卡拉支付与还款二维码LakalaProvider
financial/Mxsk.phpgetCreditUrl获取授信申请地址MxskProvider
financial/MyBank.phpgetQRCode、getQRCodeBaitiaoReturn、getQRCodeByActivity网商采购、还款和活动二维码MyBankProvider
financial/TaiLong.phpqueryStatus、textMessageForSign、sign泰隆状态、签约短信和签约TaiLongSer
financial/TaiLong.phptextMessageForPay、submitPayOrder支付短信和支付提交TaiLongSer
financial/Xiaoyudian.phpsendSms、registerStatus、registerInfo、registerQrcode小雨点注册链XiaoyudianProvider
financial/Xiaoyudian.phppayQrcode、repayQrcode小雨点支付与还款二维码XiaoyudianProvider

4.2 分期 Controller

application/controllers/financial/BtInstallment.php 是薄 Controller:读取 getThoroughData(),调用 BaitiaoInstallmentSer,再统一通过 splash() 返回成功或错误。

接口方法核心输入Service 方法结果含义
querySignStatussidgetSignStatus查询分期协议签约状态
sendSms用户、手机号sendSms发送 FQ签约 验证码
getSignUrlsid、手机号、验证码getSignUrl验证短信后返回签约 URL
queryEnableInstallmentsid、shipperCode、adjustNoList同名方法批量判断账单是否可分期
getInstallmentModeListadjustNo同名方法查询可选分期模型
queryInstallmentModeCreateTokenadjustNo、模型编码同名方法生成本次分期提交 token
installmentSubmittoken同名方法向 OPS Manager 提交分期申请
listInstallmentModelListV2adjustNo、模型列表同名方法新版模型批量查询
installmentTokenV2adjustNo、code、amount同名方法新版 token 与首还金额
queryInstallmentWaitPayListsid同名方法待还账单并补充聚合金额
queryBtInstallmentMoneysid同名方法聚合待还笔数和金额
installmentReturnSubmitorders、sid、user_id、shipperCode同名方法本地建还款单并远程批量登记
installmentReturnNoPagePay账户类型、站点、供货方、来源单号同名方法账户余额类无页面还款
installmentReturnUnionsourceNo同名方法银联还款二维码
installmentReturnB2B账户类型、站点、供货方、来源单号同名方法工行 B2B/B2C 还款
queryInstallmentOrderListsid、分页、adjustNo同名方法分期批次列表
queryInstallmentOrderDetailList分期号、账单号、逾期/支付状态同名方法分期明细列表
installmentServerFeeList客户、业务号、计费时间、分页installmentServerFee分期服务费
queryInstallmentContractsidgetContractUrl分期合同地址

5. 通道能力矩阵

通道资格/状态注册/签约支付入口还款入口主动退款查询备注
B2BqueryWhite外部完成支付中心预支付preparedPay/baitiaoReturn未在该 Controller 暴露需区分资格和真实付款结果
桥接银行列表/详情保存银行资料无直接二维码无无更接近资料管理适配器
他行融资预加载/详情/列表保存银行和贷款人由支付中心账户路由可走无页面支付无账户类型通常为他行融资
民生queryRegister短信、register外部聚合外部聚合无注册成功不等于支付成功
工行放款查询外部签约采购/活动二维码授信还款二维码无支持跳转页
工行 E可开户、余额创建 E 账户账户支付未暴露无账户标识见 10
京东数科支付状态外部准入支付 URL未暴露queryRefundStatus状态查询用于未知结果核验
拉卡拉queryStatus短信、资料、注册payQrcoderepayQrcode无还可查询注册余额
泰隆queryStatus签约短信、签约支付短信、提交支付单未暴露无提交后仍需查最终结果
小雨点注册状态/资料短信、注册二维码payQrcoderepayQrcode无二维码由 OPS Manager 返回
网商银行外部状态外部准入采购/活动二维码授信还款二维码无本地账户类型编码 18
授信分期签约、逾期、可分期短信和签约 URL分期申请 token三种还款方式由支付中心处理申请、还款是两张不同业务单

6. 外部接口边界

6.1 OPS Manager 分期接口

Provider 常量外部路径后缀本地用途
BAITIAO_ENABLE_INSTALLMENT/account/baitiao/installment/queryAdjustEnableInstallment批量判断账单是否可分期
BAITIAO_INSTALLMENT_MODE_LIST/installment/listInstallmentModelList查询旧版分期模型
BAITIAO_INSTALLMENT_MODE_CREATETOKEN/installment/selectInstallmentModelCreateToken选择模型并生成 token
BAITIAO_INSTALLMENT_SUBMIT/installment/submitApplyByTokentoken 提交分期
BAITIAO_INSTALLMENT_WAIT_APY_LIST/installment/listWaitingPayList查询待还列表,常量名保留历史拼写 APY
BAITIAO_INSTALLMENT_SIGN_STATUS/installment/querySignStatus查询签约状态
BAITIAO_INSTALLMENT_SIGN_URL/installment/openSignUrl获取签约地址
BAITIAO_INSTALLMENT_ORDER_LIST/installment/orderBatch/listPage分期批次分页
BAITIAO_INSTALLMENT_ORDER_DETAIL_LIST/installment/order/listPage分期明细分页
BAITIAO_INSTALLMENT_CONTRACT/installment/queryContract查询合同
BAITIAO_DELAY_LOCK/account/baitiao/delayLock申请延期锁定
BAITIAO_OVERDUE_INFO/account/baitiao/getOverdueInfo查询逾期信息
BAITIAO_INSTALLMENT_MODE_LIST_V2/installment/listInstallmentModelListV2新版模型列表
BAITIAO_INSTALLMENT_MODE_TOKEN_V2/installment/selectInstallmentModelCreateTokenV2新版 token
BAITIAO_INSTALLMENT_APPLY/account/baitiao/installment/Apply分期申请列表
BAITIAO_INSTALLMENT_SERVICE_FEE/paycenter/dgj/installment/service/fee/listpage查询服务费

6.2 分期还款接口

Provider 常量外部路径参数核心
BAITIAO_INSTALLMENT_RETURN_SUBMIT/account/baitiao/return/submitWhenInstallOrdersourceNo、installNo、returnAmount
BAITIAO_INSTALLMENT_RETURN_BATCH_SUBMIT/account/baitiao/return/batchSubmitWhenInstallOrder多笔还款数组
BAITIAO_INSTALLMENT_RETURN_NOPAGE_PAY/account/baitiao/return/noPagePayaccountKey、sourceOrderIds
BAITIAO_INSTALLMENT_RETURN_UNION/cashier/unionPayChannel/getQRCodeBaitiaoReturnsourceOrderIds
BAITIAO_INSTALLMENT_RETURN_B2Bpaycenter/preparedPay/baitiaoReturnaccountKey、sourceOrderIds

Provider 统一以外部响应 code == 0 作为成功;非零直接抛出外部 message。这只能说明接口调用成功,不能替代银行资金终态。

7. 请求字段与口径

7.1 分期申请核心字段

字段来源含义规则
sid登录上下文/请求服务站 IDProvider 中多数转字符串
shipperCode账单或页面供货方/货主编码可分期判断和还款必需
adjustNo授信账单授信调整单号分期模型查询的主业务键
adjustNoList页面选择多个授信账单号批量可分期判断
installmentModelCode模型列表分期方案编码旧版 token 接口使用
code页面新版模型编码Service 映射为外部模型字段
amount页面首还金额V2 映射为 firstReturnAmount,单位待外部合同确认
token外部模型接口一次性提交凭证不应复用或长期缓存
installmentNo外部分期单分期批次/订单号列表和还款关联

7.2 还款请求示例

{
  "sid": "10001",
  "user_id": "20001",
  "shipperCode": "SUPPLIER_DEMO",
  "orders": [
    {
      "installNo": "INSTALLMENT_DEMO_001",
      "returnAmount": 123400
    }
  ]
}

字段解释:

  • returnAmount 在还款单本地字段和回调处理中按“分”解释;展示付款单时除以 100 转“元”。联调必须再次核对外部契约。
  • sourceNo 不由前端传入,由 KzOrderNo::getHKDNo($sid) 加批次内索引生成。
  • uid 记录发起人,自动还款没有本地原单时会取服务站主账号,取不到则为 0。
  • shipperCode 用于匹配供应商和组成账户键,传错会导致财务往来对象错误。

7.3 还款账户键

无页面支付和 B2B 还款使用:

accountKey = accountType + "-" + sid + "-" + shipperCode

这是跨系统业务键,不是本地账户表主键。任何一段错误都可能出现“支付中心找不到账户”或资金进入错误账户域。

8. 账户类型与支付状态

8.1 系统账户编码

AccountEnums 用支付中心账户类型拼成本地 number:SYSTEM_NUMBER_PREFIX('10') + payTypeCode。

支付类型编码业务名称典型用途
01企业付款账户对公付款
02个人付款账户对私付款
05返利账户返利抵扣
06待退款账户退款暂存、无页面支付
07快准授信账户白条/授信支付
08他行融资账户外部融资资金
09原路退回标识退款路由兼容
10工行 E 贷标识工行 E 贷支付
11信 E信 E 通道
12银联付款账户银联支付
15专属返利账户专属返利抵扣
18网商付款账户网商银行
20预充值账户预存余额
100混合支付多账户组合
99零元订单过滤标识不生成真实资金付款

8.2 本地付款状态

PaymentEnums 值名称使用提醒
0已确认历史确认态
1已提交已提交、未完全确认
2已确认 V2新确认态
6已取消撤销或失效

这些状态是本地付款单状态,不等价于支付中心 payStatus。支付回调代码明确要求 payStatus == '02' 才进入成功落账。

8.3 分期配置枚举

值含义
01不分期
02下单即分期
03下单后指定天数开始分期
isInstallment = 1开启分期,映射到 03
isInstallment = 0不分期,映射到 01

9. 银行注册与签约流程

sequenceDiagram
    participant U as 服务站用户
    participant C as Financial Controller
    participant S as Service/Provider
    participant O as OPS Manager
    participant B as 银行
    U->>C: 查询资格/状态(sid)
    C->>S: 映射登录上下文
    S->>O: 查询通道状态
    O->>B: 查询主体或协议
    B-->>O: 未注册/处理中/已开通/拒绝
    O-->>S: code/message/data
    S-->>C: data 或抛异常
    C-->>U: 统一 splash 响应
    U->>C: 短信/注册/签约
    C->>S: 主体资料+验证码
    S->>O: 注册或签约
    O->>B: 实际开户/签约
    B-->>U: 可能跳转银行页面

业务判断:

  1. “发送短信成功”只代表验证码请求成功。
  2. “返回签约 URL”只代表获得签约入口。
  3. 用户从银行页面返回后,应再次查询签约/注册状态,不能只信前端跳转结果。
  4. 状态“处理中”不可重复提交敏感资料,除非外部明确允许。
  5. 注册资料包含身份证、银行卡、营业执照等敏感信息,日志和文档必须脱敏。

10. 采购支付主流程

flowchart TD
    A[采购单进入待支付] --> B[请求支付中心预支付]
    B --> C{选择账户和银行通道}
    C --> D[获取二维码/链接/短信]
    D --> E[用户完成银行操作]
    E --> F[银行通知支付中心]
    F --> G[支付中心投递 paycenter_pay_result]
    G --> H{payStatus == 02?}
    H -- 否 --> I[NACK并告警]
    H -- 是 --> J{原单类型}
    J -- 预订单 --> K[校验预订单可支付状态]
    J -- 采购单 --> L[校验待支付或兼容超时状态]
    K --> M[创建付款主单与明细]
    L --> M
    M --> N[写账户流水和采购支付信息]
    N --> O[推进原单后续状态]
    O --> P[事务提交后ACK]

10.1 支付成功事件关键字段

字段作用本地使用方式
sourceOrderNo来源业务单号查询预订单或采购单
sourceOrderType来源类型04 预订单,01 采购单
payOrderNo支付中心单号支付追踪和幂等核对
mainPayTypeCode主支付类型零元订单和主账户判断
payStatus支付结果必须为 02
payStatusMsg状态说明失败日志和告警
payTime资金完成时间缺失时回退当前时间
detailTotalAmount支付明细总额外部资金单位需按接口合同核对
details分账户支付明细按 payAccountTypeCode 绑定

10.2 原单校验

  • 预订单允许状态来自 PreOrderEnums 的待支付、取消、自动取消兼容集合。
  • 普通采购单只接受待支付和特定支付超时状态。
  • 原单不存在、状态不允许或重复成功消息会抛异常并返回 NACK。
  • mainPayTypeCode == 99 时走零元订单兼容,不应按普通资金明细入账。

10.3 本地落账结果

一次正常支付至少需要核对:

  1. 采购/预订单状态是否推进。
  2. SCM_PAYMENT 主单是否生成。
  3. SCM_PAYMENT_INFO 是否按账户拆出明细。
  4. SCM_ACCOUNT 是否存在支付类型对应的系统账户。
  5. SCM_ACCOUNT_INFO 是否产生正确方向和金额的账户流水。
  6. SCM_PO_ORDER_PAYINFO 是否记录采购支付快照。
  7. 支付中心单号、来源单号和本地付款单号是否能互相追踪。

11. 分期签约与申请流程

flowchart TD
    A[查询签约状态] --> B{已签约?}
    B -- 否 --> C[发送 FQ签约 短信]
    C --> D[校验验证码]
    D --> E[获取外部签约URL]
    E --> F[用户完成签约]
    F --> A
    B -- 是 --> G[批量查询账单可分期]
    G --> H[选择 adjustNo]
    H --> I[查询分期模型]
    I --> J[选择期数/首还金额]
    J --> K[生成一次性 token]
    K --> L[按 token 提交]
    L --> M[查询分期批次和明细]

11.1 短信签约安全边界

BaitiaoInstallmentSer::getSignUrl 先使用本地短信服务校验 user_id + code,再请求外部签约地址。需要回归:

  • 验证码错误、过期、已使用。
  • 同一用户连续发送和频率限制。
  • A 用户的验证码不能给 B 用户使用。
  • 页面手机号和服务站主体手机号不一致。
  • 外部签约 URL 超时后重取,旧 URL 是否失效。

11.2 可分期判断

queryEnableInstallment 同时传 sid、shipperCode 和 adjustNoList。因此“某账单可分期”至少取决于:

  • 服务站授信资格。
  • 该供货方是否支持分期。
  • 账单是否满足金额、期限和状态条件。
  • 账单是否已经分期或正在处理。

页面不能仅凭金额大于零显示“可分期”,必须使用外部返回结果。

11.3 token 语义

token 是“分期方案快照”的一次性凭证,可能固化账单、期数、费率、首还金额和有效期。高风险行为:

  • token 生成后修改账单选择再直接提交。
  • 重复点击导致同一 token 多次提交。
  • 缓存旧 token,跨用户或跨站点复用。
  • 前端自行计算服务费并覆盖外部结果。

12. 分期待还金额口径

queryInstallmentWaitPayList 对外部返回的每个分组补充六个聚合字段:

字段计算方式单位
pendingMoney所有 installmentOrderList.totalAmount 求和先按分汇总,再转元
pendingNum所有待还明细数量笔
weekPendingMoney到期日小于等于当前日期后第 7 天的金额元
weekPendingNum上述明细数量笔
allExpireAmountexpiredStatus == '02' 的金额元
allExpireNumexpiredStatus == '02' 的数量笔

代码的“未来七天”截止值由当天零点时间戳加 7 * 24 * 60 * 60 计算。需要注意:

  • 包含截止日零点及之前的记录,若到期时间含时分秒,边界可能与产品理解不同。
  • 代码对 totalAmount 使用分转元,而 queryBtInstallmentMoney 汇总 totalAmountYuan;两个接口的源字段不同。
  • 页面合计应使用接口聚合值,不要混加“分”和“元”。
flowchart LR
    A[外部待还分组] --> B[遍历 installmentOrderList]
    B --> C[全部待还金额/笔数]
    B --> D[未来7天金额/笔数]
    B --> E[expiredStatus=02 金额/笔数]
    C --> F[分转元]
    D --> F
    E --> F
    F --> G[返回页面]

13. 分期还款单创建

13.1 调用链

BtInstallment::installmentReturnSubmit
  -> BaitiaoInstallmentSer::installmentReturnSubmit
  -> BaitiaoInstallmentValidate::scene('installmentReturnSubmit')
  -> KzOrderNo::getHKDNo(sid)
  -> RepaymentOrderModel::cancelUnpayByShipperCodeAndSid
  -> RepaymentOrderModel::addBatch
  -> InstallmentRepayProvider::installmentReturnBatchSubmit

13.2 逐步写入

步骤动作本地/外部关键结果
1校验 shipperCode 和 orders本地缺少则终止
2逐笔校验 installNo、returnAmount本地非法金额终止
3生成 HKD 还款单号并追加批次索引本地每笔有 sourceNo
4开启还款单数据库事务本地事务开始
5取消同站点、同供货方未支付旧还款单本地防止多个待支付单并存
6批量新增还款单本地保存金额、账单、供货方
7调用外部批量创建还款单外部OPS Manager 登记
8外部成功后提交本地事务本地返回逗号分隔 sourceNo

13.3 分布式事务窗口

sequenceDiagram
    participant S as BaitiaoInstallmentSer
    participant DB as DGJ2 DB
    participant O as OPS Manager
    S->>DB: BEGIN
    S->>DB: 取消旧未支付还款单
    S->>DB: 批量插入新还款单
    S->>O: 批量创建外部还款单
    alt 外部失败
        O-->>S: error
        S->>DB: ROLLBACK
    else 外部成功
        O-->>S: success
        S->>DB: COMMIT
    end

高风险点:外部调用在本地数据库事务内。若外部已成功,但本地连接在提交时失败,外部存在还款单而本地没有;直接重试可能生成新的 sourceNo 和重复外部单。恢复前必须同时查询两端,不能只重跑接口。

14. 三种主动还款方式

方式本地方法关键参数用户交互最终结果来源
账户无页面还款installmentReturnNoPagePayaccountKey、sourceNo无二维码支付中心 MQ
银联在线还款installmentReturnUnionsourceNo返回二维码支付中心 MQ
工行 B2B/B2CinstallmentReturnB2BaccountKey、sourceNo跳转/二维码依外部返回支付中心 MQ

发起成功只表示支付中心受理。页面应显示“处理中”并轮询业务状态或等待回调,不应立即把本地还款单改为已还款。

15. 授信还款回调

PayCenterNotify::paycenterBaitiaoReturnPayResult 消费 paycenter_baitiao_return_pay_result。

flowchart TD
    A[收到授信还款成功事件] --> B[按 sourceNo 查询本地还款单]
    B --> C{本地存在?}
    C -- 否 --> D{returnMethod == 03?}
    D -- 否 --> E[NACK: 单号不存在]
    D -- 是 --> F[按 sid/shipperCode/adjustNo 补建自动还款单]
    C -- 是 --> G[检查 state]
    F --> G
    G --> H{state == 1?}
    H -- 是 --> I[当前实现抛异常并NACK]
    H -- 否 --> J[查询供应商和支付账户]
    J --> K[生成其他支出付款单]
    K --> L[本金/利息/滞纳金付款明细]
    L --> M[写账户流水并更新还款单]
    M --> N[事务成功 ACK]

15.1 自动还款补单

当本地不存在 sourceNo 且 returnMethod == '03' 时,消费者允许按事件中的:

  • sid
  • shipperCode
  • adjustNo

补建本地还款单。发起人优先取站点主账号,取不到为 0。其他还款方式找不到本地单时直接失败。

15.2 财务拆分

回调 details 按 code 区分并映射到付款类别:

费用组成本地用途付款明细
本金更新还款单本金金额其他支出本金类别
利息更新 interest其他支出利息类别
滞纳金更新 late_fee其他支出滞纳金类别

外部金额除以 100 写入付款主明细的“元”字段;还款单原始金额保留“分”口径。排查总额时必须统一单位后再比较。

15.3 重复消息风险

当前代码发现 repaymentOrderInfo.state == 1 时抛异常,外层返回 NACK。若 MQ 以 NACK 重投且没有死信上限,已经成功的重复消息可能持续重试。待环境确认消费者重试和死信策略;代码优化方向是将“同一业务结果已成功”识别为幂等 ACK,同时核对金额和支付单号是否一致。

16. 支付异常与未知结果

paycenter_pay_exception 会按来源单号查询采购单,并调用 PoOrderSer::cancelWaitPayOrder 取消待支付订单。处理原则:

  1. 支付异常消息不能只看错误文案,要核对银行是否真实扣款。
  2. 若支付中心返回失败但银行已扣款,先冻结人工重试,交由支付中心对账。
  3. 若采购单已被取消,随后又收到支付成功事件,当前状态校验可能 NACK,属于迟到成功风险。
  4. 资金结果未知时,优先主动查询支付中心/银行状态,再决定是否补消息。
flowchart TD
    A[页面支付失败或超时] --> B{银行是否扣款?}
    B -- 否 --> C[查支付中心支付单状态]
    B -- 是/不确定 --> D[禁止重复支付]
    C --> E{支付中心终态?}
    E -- 成功 --> F[查 DGJ2 是否落账]
    E -- 失败 --> G[确认采购单取消或可重新支付]
    E -- 处理中 --> H[等待回调/对账]
    D --> C
    F --> I{本地完整?}
    I -- 否 --> J[按幂等键补消息或人工补账审批]

17. 到期提醒与逾期锁站

17.1 分期到期提醒

paycenter_installment_expire:

  1. 按 sid 查询服务站联系人。
  2. 统计 installmentOrderList 数量和 stayTotalAmountYuan。
  3. 发送账户主题站内信。
  4. 发送分期到期短信。
  5. 站内信或短信失败均返回 NACK。

提醒事件不会直接扣款,也不会更新还款状态。

17.2 逾期锁站状态

lockStatus含义DGJ2 动作
01未锁定MenuRuleSer::unLockMenu(sid)
02锁定中10:00 之后执行 lockMenu(sid);10:00 前跳过
03延期锁定当前实现执行解锁
stateDiagram-v2
    [*] --> 正常可用
    正常可用 --> 延期锁定: lockStatus=03
    延期锁定 --> 正常可用: DGJ2执行解锁
    正常可用 --> 已锁站: lockStatus=02且时间不早于10:00
    延期锁定 --> 已锁站: 后续收到02且时间满足
    已锁站 --> 正常可用: lockStatus=01

批量事件逐站处理;单个站点异常只记录并继续,外层仍可能 ACK。因此必须从日志核对每个 sid 的实际结果,不能只看整条 MQ 是否消费成功。

18. 核心表与分片

常量/表关键键读取时机写入时机主要字段/作用
SCM_PO_ORDERid、billNo、sid支付回调查原单支付成功/异常推进状态采购主单
SCM_PO_ORDER_PAYINFO采购单、支付单支付详情支付成功新增采购支付快照
SCM_PAYMENTid、billNo、sid财务查询、回调幂等核验支付/还款成功新增付款主单;按站点落分片
SCM_PAYMENT_INFOiid、stlNo、sid付款详情按支付账户或费用项新增付款明细
SCM_PAYMENT_LOG来源单、动作支付审计特定支付动作写入支付日志
SCM_ACCOUNTsid、number查系统账户缺少支付类型时创建账户主数据
SCM_ACCOUNT_INFOaccId、来源单财务流水支付/还款成功新增账户收支流水
SCM_REPAYMENT_ORDERbill_no、adjust_no、sid还款发起和回调发起新增、成功更新授信/分期还款单
BS_CONTACT供应商编码回调匹配 shipperCode本流程通常只读付款往来单位
SYS_ADMINsid、主账号自动还款补单、提醒只读联系人和发起人

SCM_PAYMENT_SUB_NUM = 32,付款相关表查询必须使用项目 Model 的 setSid() 或按 sid 正确路由,不能只查一个物理表后认定“没有付款单”。账户表的具体分片规则应以 Model 为准。

erDiagram
    SCM_PO_ORDER ||--o{ SCM_PO_ORDER_PAYINFO : has
    SCM_PO_ORDER ||--o{ SCM_PAYMENT_INFO : source
    SCM_PAYMENT ||--o{ SCM_PAYMENT_INFO : contains
    SCM_ACCOUNT ||--o{ SCM_ACCOUNT_INFO : records
    SCM_PAYMENT_INFO }o--|| SCM_ACCOUNT : uses
    SCM_REPAYMENT_ORDER ||--o{ SCM_PAYMENT_INFO : settles
    BS_CONTACT ||--o{ SCM_PAYMENT : counterparty

19. 业务键追踪

业务键产生方贯穿位置排查价值
billNo/sourceOrderNo采购/预订单支付中心事件、付款明细、采购支付信息支付主链第一入口
payOrderNo支付中心MQ、支付日志或支付快照判断是否同一笔资金
sourceNo/bill_noDGJ2 还款 Service 或自动还款中心还款单、还款回调、付款明细 stlNo还款主链第一入口
adjustNo/adjust_no授信账单中心分期模型、还款单、回调说明追踪原授信账单
installmentNo/installNo分期中心分期列表、还款请求追踪分期批次
sid服务站所有本地分片和外部客户编码分片与数据权限
shipperCode供货方可分期、账户键、供应商匹配往来对象与授信域

20. 事务与一致性矩阵

场景本地事务外部调用位置主要一致性风险
采购支付结果付款、明细、账户、订单在事务中MQ 已在事务前到达本地回滚后消息重试;需幂等
分期还款单创建还款单事务外部批量创建在本地事务内外部成功、本地提交失败
授信还款结果还款单、付款和账户流水事务消费外部成功消息重复消息当前 NACK
到期通知无资金事务站内信和短信两次外部调用站内信成功、短信失败导致重投和重复通知
逾期锁站按站点逐个调用菜单规则/下线链部分站点失败但整批 ACK

21. 幂等设计检查

当前排查必须至少核对以下幂等键:

  • 支付:sourceOrderNo + payOrderNo + payStatus。
  • 还款:sourceNo,并附加 adjustNo、金额和 payTypeCode 校验。
  • 分期提交:token 或外部分期申请号。
  • 还款单创建:本地 bill_no 与外部 sourceNo 一致。
  • 到期提醒:sid + 到期日 + installmentOrderNo,当前代码未见本地提醒去重表。
  • 锁站:sid + lockStatus + 事件时间,菜单锁/解锁操作应具备重复执行安全性。

只用“状态已成功”判断幂等还不够,还要检查金额、账户类型和来源单是否一致;否则可能掩盖同单号不同金额的脏消息。

22. MQ 事件地图

Destination:paycenter_notify。

Routing key本地方法对本文的作用失败返回
paycenter_pay_resultpaycenterPayResult采购/预订单支付成功落账NACK
paycenter_pay_exceptionpaycenterPayException取消待支付采购单并记录原因NACK
paycenter_baitiao_return_pay_resultpaycenterBaitiaoReturnPayResult授信/分期还款落账NACK
paycenter_baitiao_offline_returnpaycenterBaitiaoOfflineReturnPayResult线下授信还款落账NACK
paycenter_installment_expirepaycenterInstallmentExpire分期到期站内信和短信NACK
paycenter_baitiao_expirepaycenterBaitiaoExpire普通授信到期提醒NACK
paycenter_baitiao_service_overdue_changepaycenterBaitiaoServiceOverdueChange逾期锁站/解锁外层异常 NACK,单站异常继续
paycenter_refund_resultpaycenterRefundResult退款及额度恢复相关NACK
sequenceDiagram
    participant PC as 支付中心
    participant MQ as paycenter_notify
    participant C as PayCenterNotify
    participant DB as DGJ2 DB
    PC->>MQ: routing key + message
    MQ->>C: 投递
    C->>DB: 查业务单和状态
    alt 可处理且事务成功
        C->>DB: 付款/账户/业务状态
        C-->>MQ: ACK
    else 暂时失败或数据不完整
        C->>DB: ROLLBACK
        C-->>MQ: NACK
    end

23. 故障树:二维码获取失败

flowchart TD
    A[二维码/支付链接获取失败] --> B{Controller 是否收到请求}
    B -- 否 --> C[查路由、登录态、菜单权限]
    B -- 是 --> D{参数校验是否通过}
    D -- 否 --> E[核对 sid、单号、手机号、shipperCode]
    D -- 是 --> F{Provider 是否调用外部}
    F -- 否 --> G[查本地异常和前置状态]
    F -- 是 --> H{外部 code 是否为0}
    H -- 否 --> I[按通道错误码查准入/签约/风控]
    H -- 是 --> J{data 是否含URL/二维码}
    J -- 否 --> K[外部响应契约或字段兼容问题]
    J -- 是 --> L[前端展示/CORS/二维码过期问题]

24. 故障树:已扣款但订单未变化

排查顺序必须是资金优先:

  1. 用银行流水或支付中心单号确认是否真实成功。
  2. 查支付中心是否生成 paycenter_pay_result。
  3. 查 RabbitMQ 消费日志是否进入 paycenterPayResult。
  4. 核对 sourceOrderNo 是否能查到正确站点和分片原单。
  5. 核对 payStatus 是否为 02。
  6. 核对原单是否仍在允许支付的状态。
  7. 查事务异常,确认付款主单、明细、账户流水是否全部回滚。
  8. 查消息是否 NACK 重试、进入死信或被人工丢弃。
  9. 未确认外部幂等前,不重新发起支付。

25. 故障树:分期还款后仍显示未还

检查点预期异常分支
本地还款单bill_no = sourceNo 存在创建阶段本地回滚或分片查错
外部还款单sourceNo 存在且金额一致外部批量创建失败/部分成功
支付结果支付中心终态成功银行处理中、失败或对账延迟
MQ收到还款结果binding、积压、NACK、死信
本地 state已还款回调事务失败或重复消息逻辑
付款单其他支出主单存在财务落账失败
付款明细本金/利息/滞纳金匹配details.code 映射异常
账户流水金额和账户类型正确系统账户缺失或流水写入失败

26. 只读 SQL 模板

以下 SQL 仅为排查模板。先确认实际物理分表、字段名和环境;禁止直接在生产执行更新。

26.1 按采购单号查主单

SELECT id, sid, billNo, billStatus, totalAmount, srcOrderType, create_time, modify_time
FROM t_scm_po_order
WHERE billNo = 'PO_DEMO';

26.2 按站点计算付款分表

SELECT MOD(10001, 32) AS payment_shard;

再按项目实际命名规则查询对应物理表:

SELECT id, sid, billNo, billType, transType, totalAmount, isDisable, create_time
FROM t_scm_payment_XX
WHERE sid = 10001
  AND billNo = 'PAYMENT_DEMO';

26.3 查付款明细来源

SELECT id, iid, sid, stlId, stlNo, amount, accId, wayId, paymentType, create_time
FROM t_scm_payment_info_XX
WHERE sid = 10001
  AND stlNo IN ('PO_DEMO', 'HKD_DEMO')
ORDER BY create_time, id;

26.4 查还款单

SELECT id, sid, uid, bill_no, adjust_no, shipper_code,
       amount, interest, late_fee, state, create_time, modify_time
FROM t_scm_repayment_order
WHERE sid = 10001
  AND (bill_no = 'HKD_DEMO' OR adjust_no = 'ADJUST_DEMO')
ORDER BY create_time DESC;

26.5 查系统账户

SELECT id, sid, number, name, type, create_time
FROM t_scm_account_XX
WHERE sid = 10001
  AND number IN ('1006', '1007', '1008', '1012', '1018', '1020');

26.6 对账守恒检查

SELECT stlNo,
       COUNT(*) AS detail_count,
       ROUND(SUM(amount), 2) AS detail_amount
FROM t_scm_payment_info_XX
WHERE sid = 10001
  AND stlNo = 'HKD_DEMO'
GROUP BY stlNo;

将结果与:还款单 (amount + interest + late_fee) / 100、付款主单 totalAmount、支付中心成功明细统一到元后比对。

27. 日志与代码定位命令

rg -n "paycenter_pay_result|paycenter_baitiao_return_pay_result|paycenter_installment_expire" \
  application/controllers/tasks application/KzData/Enums/MqEventEnums.php

rg -n "sourceOrderNo|payOrderNo|sourceNo|adjustNo|installmentNo" \
  application/controllers/tasks/PayCenterNotify.php \
  application/Services/ExclusiveBaitiao

rg -n "getQRCode|payQrcode|repayQrcode|submitPayOrder|queryRefundStatus" \
  application/controllers/financial application/Providers/OpsManager/Financial

rg -n "SCM_PAYMENT|SCM_REPAYMENT_ORDER|SCM_PO_ORDER_PAYINFO|SCM_ACCOUNT" \
  application/config/tables.php application/models

日志建议同时检索:

  • PayCenterNotify
  • payCenterPayResult
  • paycenterBaitiaoReturnPayResult
  • 支付消息通知开始/失败/结束
  • 授信还款消息通知
  • 来源采购单号、还款单号、支付中心单号和 sid

28. 允许的补偿与禁止动作

28.1 补偿前置检查

  1. 确认外部支付/还款终态和唯一支付单号。
  2. 确认本地原单、付款、明细、账户流水和还款单的实际状态。
  3. 确认原消息是否仍在队列、重试或死信中。
  4. 确认消费者对重复成功是否幂等。
  5. 制定补偿后的资金守恒验收 SQL。

28.2 可选恢复路径

场景优先恢复方式
MQ 未投递由支付中心按原事件 ID/支付单号补投
MQ 在死信审核 payload 后按原消息重放
本地事务完整回滚修复根因后重放原消息
外部还款单有、本地无按外部 sourceNo 补齐本地映射后消费结果;不可重新生成新单
只有提醒失败在确认无重复轰炸风险后重发通知,不触碰资金数据
单站锁站失败核对最新锁定状态后单站重放/人工执行,不重放过期旧状态

28.3 禁止动作

  • 未确认银行扣款前让用户再次支付。
  • 直接修改采购单为已支付而不生成财务数据。
  • 只补付款主单,不补付款明细和账户流水。
  • 删除已成功还款单后重新发起。
  • 用新 sourceNo 替代外部已有的旧还款单。
  • 在文档、工单或群聊粘贴完整银行卡、身份证、手机号、签名密钥和证书。

29. 监控建议

指标维度告警建议
支付成功回调 NACK 数routing key、异常类型连续增长立即告警
支付成功到本地落账延迟通道、来源类型超业务 SLA 告警
待支付订单超时量通道、站点与支付中心处理中数量联动
重复成功消息量来源单号、支付单号识别幂等问题
外部还款单与本地还款单差异sourceNo非零告警
已还款无付款单sid、sourceNo资金数据完整性告警
分期到期通知失败短信/站内信分渠道统计
锁站部分失败sid、lockStatus每站记录,不能只看批次
Provider 非零 code银行、接口按通道错误码聚合
分期 token 提交失败模型、错误码关注重复和过期

30. 安全与合规

  • 请求和日志中的银行卡仅保留后四位,身份证仅保留必要掩码。
  • 短信验证码不得持久化明文,不得进入普通业务日志。
  • 签约 URL、支付 URL 和二维码通常包含短期凭证,不应长期保存或公开。
  • Provider 配置中的密钥、证书、商户号不写入知识库。
  • 人工补账必须有审批、操作人、原始支付凭证、SQL 前后快照和双人复核。
  • 生产查询默认只读,先按 sid 定位分片,再限制单号和时间范围。

31. 回归清单:通道接入

  • [ ] 未开通、审核中、已开通、拒绝四类状态展示正确。
  • [ ] 短信发送成功、频控、错误手机号、验证码错误、验证码过期。
  • [ ] 重复注册和重复签约不产生冲突主体。
  • [ ] 银行跳转成功、取消、超时、返回页刷新。
  • [ ] 二维码生成、过期、重复获取和跨账号隔离。
  • [ ] 单一银行维护不影响其他银行 Provider。
  • [ ] 外部 code != 0 时前端显示可理解错误,不泄露敏感响应。
  • [ ] 服务站被锁定后金融菜单和接口权限一致。

32. 回归清单:采购支付

  • [ ] 普通采购单待支付成功。
  • [ ] 预订单支付成功。
  • [ ] 零元订单不生成错误资金流水。
  • [ ] 企业、个人、返利、待退款、授信、银联、网商和混合账户拆分。
  • [ ] 支付失败和支付异常取消待支付订单。
  • [ ] 用户中途取消或二维码过期。
  • [ ] 银行成功、回调延迟期间页面状态。
  • [ ] 相同成功消息重复投递。
  • [ ] 同来源单不同支付单号冲突。
  • [ ] 支付成功和支付异常乱序到达。
  • [ ] 支付超时后迟到成功。
  • [ ] 付款主单、明细、账户流水和采购支付信息金额守恒。
  • [ ] 32 分片路由正确。
  • [ ] 消费事务中任一步失败后完整回滚。

33. 回归清单:分期申请

  • [ ] 未签约不可直接分期。
  • [ ] 签约短信与当前用户绑定。
  • [ ] 单账单和多账单可分期判断。
  • [ ] 不同 shipperCode 不混选。
  • [ ] 不可分期原因正确展示。
  • [ ] 旧版和 V2 模型列表兼容。
  • [ ] 首还金额边界、最小金额、最大金额和精度。
  • [ ] token 过期、重复使用、跨用户使用。
  • [ ] 重复点击提交只产生一笔外部分期申请。
  • [ ] 分期批次、明细、服务费和合同可追踪。
  • [ ] 未来七天与到期日边界。
  • [ ] 分/元聚合无百倍误差。

34. 回归清单:分期还款与逾期

  • [ ] 单笔和多笔还款单创建。
  • [ ] 同站点同供货方旧未支付单取消。
  • [ ] 不同供货方待还款单互不影响。
  • [ ] 外部创建失败时本地回滚。
  • [ ] 外部成功、本地提交失败的人工恢复演练。
  • [ ] 无页面、银联、B2B 三种还款。
  • [ ] 主动还款和自动还款回调。
  • [ ] 自动还款本地无单时按事件补建。
  • [ ] 本金、利息、滞纳金分别落账。
  • [ ] 重复还款成功消息的 ACK/NACK 行为。
  • [ ] 到期站内信成功、短信失败的重复通知风险。
  • [ ] 01/02/03 三种逾期锁定状态。
  • [ ] 09:59 与 10:00 锁站边界。
  • [ ] 批量锁站中单个站点失败仍有可观察记录。
  • [ ] 解锁后菜单、接口和登录态一致。

35. 改动风险分级

风险级别改动示例最低回归范围
P0PayCenterNotify、账户类型、金额单位、还款状态、MQ ACK/NACK全支付、全还款、重复/乱序、财务守恒、死信恢复
P0RepaymentOrderModel、本地与外部创建顺序多笔还款、事务失败、外部成功本地失败
P1单个银行 Provider 请求字段或成功码该银行注册、签约、支付、查询、失败码
P1分期 token、模型或聚合金额全分期申请、账单、金额边界
P1MenuRuleSer 锁站逻辑权限、菜单、接口、登录态、延期和解锁
P2页面文案、列表字段或下载展示对应页面、兼容字段、无敏感泄露

36. 已确认事实与待确认项

36.1 已从当前代码确认

  • 金融通道 Controller 和方法清单。
  • 分期 Provider 的外部路径和 code == 0 成功判断。
  • 分期签约短信、本地验证码校验和签约 URL 顺序。
  • 可分期、模型、token、提交、待还列表、服务费和合同调用链。
  • 还款单在本地事务内新增并调用外部批量接口。
  • 还款账户键由 accountType-sid-shipperCode 组成。
  • 支付中心 destination 和本文涉及的 routing key。
  • 支付成功要求 payStatus == '02'。
  • 自动还款可在本地无原单时补建还款单。
  • 还款金额按分转元写付款数据。
  • 重复已还款消息当前会抛异常并 NACK。
  • 分期到期发送站内信和短信。
  • 锁站状态 02 在 10:00 前被跳过,01/03 解锁。

36.2 待环境或外部系统确认

  • 各银行生产路由、商户配置、签名算法、证书轮换和超时。
  • 外部注册、签约、支付、退款和分期状态全集。
  • 分期 token 有效期、幂等约束和重复提交返回。
  • firstReturnAmount 等金额字段的正式单位合同。
  • 支付中心 publisher confirm、重试次数、死信和消息保留时间。
  • 本地付款、账户和还款表的生产唯一索引。
  • 支付中心对迟到成功、重复成功和支付异常乱序的责任边界。
  • 逾期批量事件是否保证同一站点有序。
  • 通知中心短信去重和频控。

37. 证据来源

  • application/controllers/financial/B2bPay.php
  • application/controllers/financial/BridgeBank.php
  • application/controllers/financial/BtInstallment.php
  • application/controllers/financial/Cmbc.php
  • application/controllers/financial/Icbc.php
  • application/controllers/financial/IcbcE.php
  • application/controllers/financial/Jdsk.php
  • application/controllers/financial/Lakala.php
  • application/controllers/financial/Mxsk.php
  • application/controllers/financial/MyBank.php
  • application/controllers/financial/OtherBank.php
  • application/controllers/financial/TaiLong.php
  • application/controllers/financial/Xiaoyudian.php
  • application/Services/Financial/*
  • application/Providers/OpsManager/Financial/*
  • application/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.php
  • application/Providers/OpsManager/Baitiao/BaitiaoInstallmentProvider.php
  • application/Providers/OpsManager/Baitiao/InstallmentRepayProvider.php
  • application/controllers/tasks/PayCenterNotify.php
  • application/controllers/tasks/QPayCenterNotify.php
  • application/KzData/Enums/AccountEnums.php
  • application/KzData/Enums/PaymentEnums.php
  • application/KzData/Enums/InstallmentEnums.php
  • application/KzData/Enums/MqEventEnums.php
  • application/config/tables.php

38. 一页式交接结论

  1. 银行 Controller 只负责“能否用、怎样签、怎样拿入口”,不能据此认定资金成功。
  2. 采购支付以 paycenter_pay_result 且 payStatus == '02' 为资金成功入口。
  3. 支付成功后必须同时核对原单、付款主单、付款明细、账户流水和采购支付快照。
  4. 分期申请围绕 adjustNo -> model -> token -> submit;token 是一次性方案快照。
  5. 分期还款围绕 installmentNo -> sourceNo -> repayment_order -> paycenter callback。
  6. 外部金额多为分,本地财务展示多为元,任何修改先做单位表。
  7. 还款单创建存在“外部成功、本地提交失败”的分布式事务窗口。
  8. 重复已还款消息当前可能持续 NACK,是生产重试风险点。
  9. 到期提醒失败会重投,逾期锁站批量中单站失败可能被整批 ACK 掩盖。
  10. 所有人工恢复都必须以原支付单号/还款单号为幂等键,并完成资金守恒验收。

请求-日志-数据变更追踪卡

多入口请求链路

场景调用方与入口请求载荷/上下文Controller/ConsumerService/Provider汇合点最终业务事实
分期配置/签约/financial/BtInstallment站点、授信、分期模式、签约参数Financial ControllerOpsManager Financial Providerstation/application ID获取模式、签约 URL 和签约状态
分期申请PC 金融页面来源订单、期数、金额、服务费Financial ControllerBAITIAO Providerapply/order ID外部授信分期订单受理
支付回调PayCenter MQ支付单、来源单、支付/白条事件PayCenterNotifyPayment/Baitiao ServicepayOrderNo本地支付和授信占用落账
退款/还款Financial 页面/回调原订单、退款/还款单、金额Financial Controller/ConsumerProvider/Repayment Serviceoriginal pay/order ID外部退款还款与本地额度恢复

日志证据矩阵

| 链路段 | 日志来源 | 可检索锚点 | 成功信号 | 失败信号 | 与下一段关联方式 | | --- | --- | --- | --- | --- | --- | --- | | 签约申请 | Financial Controller/Provider | request_id、sid、application/token ID | 返回受理/签约 URL | 配置关闭、token 过期、外部拒绝 | application ID 查签约状态 | | 分期下单 | Provider | 来源单、installment order ID、金额/期数 | 外部订单 accepted | 超时、金额/期数不支持、重复 | 外部订单号关联本地来源单 | | 支付回调 | PayCenterNotify | payOrderNo、来源单、event/message ID | 支付/授信记录一次落库 | 重复占额、迟到/乱序 | payOrderNo 查本地资金表 | | 退款还款 | Provider/Consumer | original pay、refund/repayment ID | 外部成功且额度/余额一次恢复 | 外部成功本地失败、重复返还 | 原支付单串联正反向流水 |

环节数据变更台账

步骤代码位置事务读取事实写入表/缓存/MQ字段或数量变化回查证据
获取模式/签约BtInstallment + Financial Provider外部边界站点开关、授信状态外部签约、本地关系/状态unsigned -> pending/signedstation/application ID、外部状态
分期申请Financial Service本地事务 + 外部非原子可用额度、来源订单、金额本地申请/关系、外部分期订单available old -> old-n 或进入冻结;申请 pending来源单、外部订单、额度前后值
支付落账PayCenterNotify回调事务成功事件、当前支付状态支付表、业务/授信关系payment -> confirmed;冻结 -> 已用;重复 0 增量payOrderNo、金额、额度流水
退款还款Refund/Repayment Service外部与本地非原子原支付/已退/未还金额退款还款表、授信额度refunded/repaid +n;available +n,不超过原占用原支付+反向单、资金守恒
人工补偿幂等补偿入口小批事务外部最终态、本地差异缺失本地记录或重查外部只补断点;同原单重跑 0 变化前后快照、原支付/还款键

子模块追踪:bank-pay 银行与聚合支付

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
发起通道选择银行/聚合渠道支付sourceOrderNo、payOrderNo、channel、amountapplication/controllers/financial/B2bPay.php、application/controllers/financial/Icbc.php、application/controllers/financial/Lakala.php待支付关系、渠道配置名、金额和重复单本地资金事务 none -> pending;银行调用事务外request ID + pay/source order + channel/codetimeout 先查渠道最终态,不切通道重复扣款
结果落账Pay/QPay 回调message ID、payOrderNo、channel statusapplication/controllers/tasks/QPayCenterNotify.php外部成功、已有 Payment/Info 和来源态回调本地事务 pending -> confirmed/failed,首次成功记账message ID + payOrderNo + channel result重复 0 增量;失败后换通道前确认原单已终结

子模块追踪:installment-config 授信分期模式配置

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
获取/保存模式站点配置可用期数和模式sid、config/mode ID、operatorapplication/controllers/financial/BtInstallment.php -> application/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.php站点授信、外部支持模式和原配置配置本地事务 old modes -> new modesrequest ID + sid + mode/version外部不支持的模式零写入;敏感配置值不入文档
运行读取下单展示/校验分期选项sid、order amount、sceneapplication/KzData/Enums/InstallmentEnums.phpenabled、额度、期数门槛和服务费规则查询只读 不写request ID + sid + selected mode页面选项不等于最终可申请;提交必须重验

子模块追踪:installment-sign 分期签约

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
发起签约未签约站点开通分期sid、application/sign IDapplication/Providers/OpsManager/Baitiao/BaitiaoInstallmentProvider.php授信资格、本地签约态和外部合同字段外部调用事务外;本地关系 unsigned -> pendingrequest ID + sid/application ID + provider codetimeout 按申请键回查;禁止重复签约流程
状态确认外部签约结果查询/回调external sign ID、statusapplication/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.php两端签约态、版本和幂等键本地事务 pending -> signed/failed,重复结果 0 变化external/local sign IDs + status乱序不回退 signed;合同细节需目标环境验证

子模块追踪:installment-apply 分期申请与服务费

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
提交申请已签约订单选择期数sourceOrderNo、installmentOrderNo、period、principalapplication/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.phpsigned、available、期数、服务费率和已有申请本地申请事务写关系 none -> pending,额度 available -n, frozen +nrequest ID + source/installment order + amount额度不足/重复来源零写入;服务费与本金分别保存
外部受理提交 OpsManager 分期local/external application IDapplication/Providers/OpsManager/Baitiao/BaitiaoInstallmentProvider.php本地 pending 快照和外部受理结果外部调用事务外;受理号回写本地关系request ID + both IDs + provider codetimeout 查外部申请;拒绝按规则释放 frozen

子模块追踪:installment-pay 分期支付回调

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
成功回调支付中心分期结果message ID、payOrderNo、installment/source orderapplication/controllers/tasks/PayCenterNotify.phppayStatus=02、frozen、已有支付和来源态回调本地事务 payment pending -> confirmed、frozen -n, used +nmessage ID + three order IDs + amount重复 0 增量;支付成功但额度未转只补额度段
对账回查资金或额度不平payOrderNo、额度流水 IDapplication/KzData/Enums/PaymentEnums.phpPayment/Info、申请、额度前后和服务费查询只读;本金+服务费与支付明细守恒payOrderNo + ledger IDs外部最终态为仲裁;禁止只改余额无流水

子模块追踪:installment-lock 延迟、逾期与锁定

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
到期扫描定时任务检查未还分期batch、sid、installment order、dueAtapplication/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.php未还本金/服务费、到期时间和现有锁因每单本地事务 normal -> due/overdue/lockedtask + sid/order + dueAt/status已还清扫描 0 变化;时区和调度需环境确认
解锁全部逾期还清sid、open overdue ordersapplication/KzData/Enums/AccountEnums.php所有有效逾期和站点锁态条件满足才本地事务 locked -> unlockedsid + overdue IDs + action不因一单还清解锁其他逾期;菜单缓存另同步

子模块追踪:installment-refund 分期退款

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
发起/结果订单退货取消分期支付original payNo、refundNo、principal/feeapplication/controllers/tasks/PayCenterNotify.php原支付、已退本金/服务费、used/frozen退款本地事务 refunded +n、used/frozen -n, available +nmessage ID + original/refund/order IDs不超过原占用;服务费退款规则按外部合同确认
退款回查外部成功本地额度未恢复refundNo、ledger IDsapplication/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.php外部终态、退款关系和额度流水查询只读;幂等补缺失额度/状态refundNo + ledger before/after不重复发起退款;禁止余额直改无反向流水

子模块追踪:installment-repay 分期还款与额度恢复

环节入口/触发请求/业务键代码链路读取事实写入与字段变化日志证据异常与补偿
发起还款线上/自动/线下确认还款repaymentNo、installment order、amountapplication/Providers/OpsManager/Baitiao/InstallmentRepayProvider.php应还、已还、逾期、通道和重复键本地关系 none -> pending,外部还款调用事务外request ID + repayment/installment IDstimeout 查外部终态;线上线下共享幂等键
还款落账还款结果确认external repayment ID、statusapplication/Services/ExclusiveBaitiao/BaitiaoInstallmentSer.php成功金额、used、已还和锁态回调本地事务 repaid +n, used -n, available +n、partial/paidboth repayment IDs + ledger不超过应还/原占额;全还后再解锁,重复 0 增量