简介《XX银行供应链金融业务平台需求说明书专业完整版》是一份面向银行产品经理、需求分析师、金融IT架构师及供应链金融业务人员的完整需求文档适合在平台规划、需求评审或系统设计前期作为对标参考。文档以该行供应链金融业务扩张为背景先解释了传统手工台账在操作成本、风险控制及流程规范上的不足再系统梳理预付款融资、动产质押授信、应收账款融资、国内保理等产品的全流程管理、风险预警、会计核算和数据信息管理要求并说明了与核心系统T24、信贷风险管理信息系统CRMS的接口集成方式以及未来通过网银实现B2B在线业务处理的演进路径。资源包内共1个PDF文件整体大小109.49MB属于专业完整版PDF内容结构清晰、覆盖面广可作为银行供应链金融平台项目规划、需求编写、系统设计或内部培训的参考蓝本目录框架对技术选型与需求评审也具有一定借鉴意义。目前已有131人学习浏览具备实践参考热度适合银行金融科技相关从业者按需查阅。1. 一份银行供应链金融需求说明书为什么值得当系统架构文档读某银行产品计划书里夹着一份《XX银行供应链金融业务平台需求说明书》全文没有代码却写清了平台必须解决的几件事多产品、多环节、多系统耦合以及手工台账无法承载的操作风险。不少项目把这类文档资料当成背景略过最终做成了在线填单系统而不是平台。说明书把平台定位成“业务总线”点名要接核心系统T24和信贷风险管理信息系统CRMS业务范围覆盖出口/进口保理、预付款融资、动产质押授信、应收账款融资、贸易信用保险融资和国内保理。对银行科技人员、产品经理和后端集成工程师而言值得拆成产品、接口、风控核算、验收联调四个层面来读。下面逐个展开。2. SCF平台的产品矩阵从五类业务到统一流程抽象需求说明书中的产品清单乍看很散但放在“采购—存货—销售”三个供应链环节里就清晰了预付款融资发生在采购环节动产质押授信发生在存货环节应收账款融资和保理发生在销售环节。平台建设的第一步是把这些产品的流程共性抽出来而不是先做菜单和页面。2.1 供应链金融产品对照预付、存货、应收、信用保险与保理先给一个粗略的产品分类地图用来对齐业务视角和系统视角产品类别供应链环节授信依托典型风控抓手预付款融资采购上游发货义务货权凭证、卖方回购动产质押授信存货存货价值仓储监管、价格盯市应收账款融资销售买方信用应收账款转让/质押登记贸易信用保险融资销售保险赔付保险权益转让出口/进口保理销售/采购买方/卖方信用应收账款催收、坏账担保这五类产品的“授信依托”差别很大但业务操作流程高度相似客户申请、资料核验、额度审查、放款、贷后管理、还款或解除担保。需求说明书之所以提“功能完整、操作灵活”就是因为产品多而流程共性大不能每上线一个产品就重做一套流程。我在实际项目中一般只建一张“融资申请主单据”每类产品只是主单据上的产品类型字段不同。预付款融资和应收账款融资的差别主要集中在额度占用时对应的“受托支付信息”和“回款路径”流程引擎本身不需要换。这样新增产品时只需要补充产品参数、科目映射和风控规则平台主干不动。2.2 从手工台账到状态机单据流转才是平台的地基手工台账的问题不在“没用Excel”而是没有状态约束。业务人员可以直接改上次记录审批链和审计线索也就失效了。平台要做的第一件事是用有限状态机约束单据生命周期。下面是融资单状态定义的 Python 示例from enum import Enum, auto class OrderState(Enum): DRAFT auto() # 草稿 SUBMITTED auto() # 已提交 APPROVED auto() # 审批通过 DISBURSED auto() # 已放款 SETTLED auto() # 已结清 REJECTED auto() # 已拒绝 # key为当前状态value为允许跳转的目标状态集合 TRANSITIONS { OrderState.DRAFT: {OrderState.SUBMITTED, OrderState.REJECTED}, OrderState.SUBMITTED: {OrderState.APPROVED, OrderState.REJECTED}, OrderState.APPROVED: {OrderState.DISBURSED}, OrderState.DISBURSED: {OrderState.SETTLED}, } def can_transition(current: OrderState, target: OrderState) - bool: return target in TRANSITIONS.get(current, set())这里的核心不是代码本身而是规则表达。任何写操作前先执行 can_transition不满足就拒绝数据库里同时保存上一状态和当前状态审计时能重建操作链。比如审批通过后不能直接结清必须经过放款拒绝是终态想继续融资只能重新发起申请。这些规则来自供应链金融的自偿逻辑不是产品经理拍脑袋。把状态机落到实现时我建议状态值使用枚举或统一编码不要用汉字“审批中”“已放款”。因为汉字在不同系统间容易出现“审批中”和“审批通过中”的不一致统一编码后下游报表、CRMS预警、T24记账才能直接关联。2.3 业务总线模式为什么不直接让T24和CRMS两两直连需求说明书原文说“作为一个业务总线将核心系统(T24)、信贷风险管理信息系统(CRMS)串接起来抽取相关信息从而完成他们之间的耦合风险控制”。这里的“业务总线”不是一个浮夸词。如果让T24直接调CRMS或者CRMS直接调T24每增加一个系统就要改两头的接口更麻烦的是额度占用、账务流水、业务单据三份数据对不上时根本说不清哪边先错。SCF作为总线后调用链变成这样# 模拟SCF总线发起放款先占用额度再通知T24记账 curl -X POST $CRMS_URL/api/quota/preoccupy \ -H Content-Type: application/json \ -d {req_id:Q20231207001,contract_no:HT001,amount:1000000} curl -X POST $T24_URL/api/disburse \ -H Content-Type: application/json \ -d {req_id:D20231207001,contract_no:HT001,amount:1000000}两个 curl 命令只是为了说明总线对外暴露的入口生产环境通常会走 MQ 或 ESB 适配器但顺序很重要先扣额度再放款如果放款失败SCF 再释放额度。只要这个顺序不乱额度与账务就不会明显偏离。总线模式的另一个收益是替换成本未来如果 T24 换成新核心SCF 只需要改适配器业务侧接口保持稳定反之如果上下游两两直连核心系统升级会变成全网改造。要避免的误用是把“总线”理解成所有业务逻辑都往 SCF 里塞把 T24 的核算规则、CRMS 的评分卡都搬进来。总线做的是流程编排和数据抽取不是领域逻辑的搬运工。需求说明书中写“抽取相关信息”目的就在于此。3. 落地集成T24核心账务与CRMS额度预警的接口设计流程抽象做得再好也要通过接口落到系统上。银行系统集成讲究契约先行先定报文、错误码和幂等策略再写代码否则联调阶段一定会被字段格式和超时问题拖住。3.1 接口清单与数据流向从需求说明书的目标能整理出最核心的五组接口接口名称方向触发方式关键字段客户信息查询/同步SCF - T24客户建立时客户号、证件号、开户行放款记账SCF - T24审批通过后合同号、金额、起息日还款到账通知T24 - SCF日终批量/实时账户、金额、原始交易流水额度预占/释放SCF - CRMS放款/结清客户号、额度协议号、金额风险预警推送CRMS - SCF事件触发预警级别、风险类型、建议动作数据流向要分清T24 是账务源头SCF 要把业务单据翻译成 T24 能处理的记账交易CRMS 是风险源头SCF 要在放款动作前拿到额度判断和风险信号并在动作后把结果回写。比如“还款到账通知”T24 回传的只是一笔账户流水SCF 要负责把它匹配到具体融资合同上匹配不上的要进异常池不能直接给客户做结清。3.2 T24放款与还款接口字段映射与幂等设计放款接口最容易踩坑的是“重复入账”。网络超时后重发指令如果 T24 重复记账资金就错了。解决办法是在报文中带一个幂等键服务端用这个键做去重。下面是一份常见放款报文{ req_id: SCF20231207001, biz_type: PREPAYMENT_FIN, contract_no: HT20231207001, customer_id: C01020304, currency: CNY, amount: 1000000.00, value_date: 2023-12-07, purpose: PREPAYMENT_TO_SUPPLIER, source_system: SCF }字段说明req_id 是幂等键不要用随机 UUID建议用“业务日期产品码流水号”生成这样排查问题时能直接定位到业务biz_type 决定 T24 走哪套核算科目预付款融资和应收账款融资的放款科目不同amount 用字符串而不是数字银行金额必须精确到分JSON 数字类型在 BigDecimal 转换时会引入精度噪音value_date 是起息日不传默认系统日会导致跨日账务错位。光有报文还不够调用方要有幂等重试逻辑。下面是基于 Redis 的幂等控制伪代码import redis cache redis.Redis(hostscf-cache, port6379, decode_responsesTrue) def disburse_with_idempotency(req_id: str, payload: dict) - dict: # nxTrue只有键不存在时才能写入实现并发去重 if cache.set(req_id, RUNNING, nxTrue, ex1800): try: result t24_client.disburse(payload) cache.set(req_id :RESULT, result) return result except Exception: cache.set(req_id :RESULT, ERROR) raise finally: cache.delete(req_id) # 释放运行标记 return cache.get(req_id :RESULT) or {status: PROCESSING}逻辑说明第一次请求进来时 set nx 返回 True执行业务并发重试请求进来时 nx 返回 False说明该请求正在处理或已有结果直接返回缓存结果。ex1800 是锁的过期时间防止业务方崩溃后锁永久占用。这里的 Redis 可以换成数据库唯一索引核心是加一个唯一约束但 Redis 的好处是可以同时缓存结果避免重试请求在结果写库前打爆业务系统。3.3 CRMS额度联动预占、扣减与回滚额度占用要严格按三步走预占、实际占用、释放。融资审批通过后SCF 调 CRMS“额度预占接口”传入客户号、授信协议号、金额CRMS 返回预占编号。此时额度被冻结其他渠道不能乱用。放款记账成功后SCF 调“额度实际占用接口”把预占额度转成已用额度。还款结清后SCF 调“额度释放接口”把额度归还给客户。网络异常会让这三步卡住所以还需要一张补偿表异常场景SCF 侧处理CRMS 侧处理预占成功但放款失败发送释放指令释放预占额度放款成功但占用通知丢失定时对账任务提供额度占用查询接口还款成功但释放失败推送异常工单保留人工释放入口注意额度占用失败时放款动作必须终止如果先放款再预占同一客户从多个渠道同时申请时CRMS 额度会被透支。生产中我还会加一个定时任务每 10 分钟核对 SCF 本地占用量与 CRMS 返回占用量差异超过一分钱就告警然后把差异单送到人工岗。这样即使接口异常也有第二条线兜底。4. 风控、会计分录与数据层让SCF平台从“能用”到“可靠”供应链金融平台只有流程和接口是不行的还得让业务“敢用”。敢用意味着风控能闭环、账能对上、数据能追溯。这一章把三件事放在一起说因为它们共用流程引擎产生的事件和数据。4.1 闭环风控回款专户、账期提醒与异常预警供应链金融区别于普通流贷的核心是自偿性还款来源不再依赖借款人还款意愿而是销售回款或存货处置款。平台必须让每笔融资对应一条回款路径。具体落地有三个动作放款时绑定或开立回款专户T24 的账户流水进入 SCF 后自动匹配融资单每天跑批扫描到期融资提前 7 天、3 天产生提醒对回款金额和应还款金额做差额比对偏差超过阈值就推送 CRMS 和客户经理。下面这个 SQL 可以直接用来生成“7天内到期但回款不足”的预警清单SELECT f.contract_no, f.customer_no, f.due_date, f.principal_balance, COALESCE(r.total_repay, 0) AS total_repay FROM scf.finance_order f LEFT JOIN ( SELECT contract_no, SUM(actual_repay_amount) AS total_repay FROM scf.repay_record WHERE biz_date CURRENT_DATE GROUP BY contract_no ) r ON f.contract_no r.contract_no WHERE f.state DISBURSED AND f.due_date CURRENT_DATE INTERVAL 7 DAY AND f.principal_balance COALESCE(r.total_repay, 0);逻辑说明left join 保证没有回款记录的单据也能查出来COALESCE 把 NULL 转换成 0避免金额比较失效。state 字段必须与第 2 章的状态机一致如果库里既有“已放款”又有“DISBURSED”这个 SQL 就会漏数据。due_date 判断的是“剩余期限不足 7 天”适合日终批处理贷前阶段则应该用应收账款的账龄分布来预警不能只看到期日。4.2 会计引擎从业务事件到科目映射需求说明书要求“自动完成各项金融交易的会计核算”落到设计上就是一个由事件驱动的分录生成器。放款、还款、利息计提、额度释放都是事件事件名称从流程引擎状态变化中产生再根据映射表生成借贷分录。业务事件借方科目贷方科目预付款融资放款预付款融资—本金企业活期存款应收账款融资放款应收账款融资—本金企业活期存款还款本金企业活期存款XX融资—本金还款利息企业活期存款利息收入—供应链金融科目编码要抽象成配置不要写死在代码里。以下是事件到科目映射的最小实现def entry_for(event: str, amount: float): mapping { PREPAY_DISBURSE: (22100101, 20110001), RECEIVABLE_DISBURSE: (22100201, 20110001), REPAY_PRINCIPAL: (20110001, 22100101), REPAY_INTEREST: (20110001, 60110101), } debit, credit mapping[event] return {debit: debit, credit: credit, amount: %.2f % amount}说明这里科目码是示意实际以银行科目表为准。关键在事件命名和科目映射一一对应新增融资产品时只需要在 mapping 里补一行。金额用格式化字符串保留两位避免浮点数尾巴。生产环境建议全程用 DecimalPython 的 float 做金额加减会出现 0.001 的误差对账时非常难查。分录生成后先写 SCF 本地会计流水表再打包送给 T24 总账两端都用同一笔业务流水号日终对账才有依据。4.3 数据信息管理把T24、CRMS和本地单据汇成一张可以分析的表数据管理不能等到报表阶段再做。SCF 运行期就要把 T24 账务、CRMS 额度和本地单据按合同号关联形成日快照。不要用 SCF 在线库直接做复杂报表OLTP 表索引和锁机制扛不住统计分析常见做法是搭一个轻量数据集市每天跑批生成宽表。CREATE TABLE dws_scf_finance_daily ( biz_date DATE, contract_no VARCHAR(32), customer_no VARCHAR(32), product_type VARCHAR(32), principal DECIMAL(20,2), quota_used DECIMAL(20,2), risk_level VARCHAR(8), state VARCHAR(16), PRIMARY KEY (biz_date, contract_no) );这张表是典型的事实表一行代表一张融资合同在某个业务日的快照。principal 是当日融资余额quota_used 来自 CRMS 额度实际占用risk_level 来自 CRMS 预警信号state 是 SCF 单据状态。主键用 biz_date contract_no 有两个作用一是每天跑批可以覆盖插入二是写分析 SQL 时不会因为多次跑批产生重复记录。金额字段必须 DECIMAL(20,2)不能用 FLOAT否则累计汇总总会差几分钱。除了解析报表这张表还有一个作用验证 T24 和 CRMS 的数据一致性。比如 principal 为 0 但 quota_used 仍大于 0说明还款后额度没释放平台要生成异常单据。5. 从需求说明书到上线需求追踪矩阵与接口联调清单需求说明书是静态文档但它要驱动的开发、测试、验收是一连串动态行为。我的习惯是先用“需求追踪矩阵”把每条功能目标翻译成可观察的验收用例再针对T24、CRMS的接口边界做联调模拟。这两件事做好了需求落地才不会被业务部门的“我感觉不对”推翻。5.1 需求追踪矩阵把文档资料变成可验收的用例比如需求说明书说“替代现行的手工台账”这句话没法直接测试。要拆成创建一笔预付款融资单单据状态可查询审批日志完整字段变更留痕。类似地“自动完成会计核算”要拆成放款事件发生后 1 分钟内生成借贷分录且 T24 账户余额与 SCF 流水一致。用表格维护需求说明验收步骤判定标准替代手工台账创建融资单并维护字段状态可查操作日志完整与T24对接调放款接口模拟失败重发T24账户余额与SCF流水一致风险预警注入不足额回款数据7天内生成预警记录追踪矩阵的粒度要控制在“每张表一个用例”。流程引擎的每个状态迁移是一个用例每条接口的每个错误码也是一个用例。这样需求说明书里“功能完整、操作灵活”的表述才会变成几百条可执行的验收项。5.2 联调技巧用模拟器注入超时和重复报文T24和CRMS在联调环境里通常很“稳定”很难真实触发网络超时或重复报文但生产事故大多发生在这种场景。我一般会在SCF测试环境前面部署一个WireMock模拟器用它代理T24/CRMS的接口专门注入异常。启动方式很简单java -jar wiremock-standalone.jar --port 8089 --global-templating这个命令会在 8089 端口启动一个独立的模拟服务。然后配置一条“先超时后成功”的放款响应curl -X POST http://localhost:8089/__admin/mappings \ -H Content-Type: application/json \ -d {request:{method:POST,url:/api/disburse},response:{status:200,jsonBody:{resp_code:TIMEOUT}}}设置完成后SCF 调用 /api/disburse 会立刻拿到 TIMEOUT触发幂等重试逻辑重新配置 stub 返回成功验证重试后不会重复入账。测试时重点观察 SCF 日志中的 req_id 是否一致以及 T24 侧有没有过滤掉重复请求。把这两条用例跑通接口联调才算真的结束。本文还有配套的精品资源点击获取