主题
应用管理 PRD(支付模块)
文档信息
| 项目 | 内容 |
|---|---|
| 产品名称 | PMForge - 应用管理(支付模块) |
| 文档版本 | v2.0 |
| 创建日期 | 2026-09-20 |
| 最后更新 | 2026-09-24 |
| 文档状态 | 评审中 |
| 优先级 | P0 |
| 所属模块 | 支付模块(pmforge-module-pay) |
修订记录
| 版本 | 日期 | 修订人 | 修订内容 |
|---|---|---|---|
| v1.0 | 2026-09-24 | PMForge 产品团队 | 初稿 |
| v2.0 | 2026-09-19 | PMForge 产品团队 | 增强业务场景、验收标准、跨模块联动、名词解释;替换附录为跨模块联动章节 |
一、功能概述
1.1 功能定位
如果把 PMForge 的支付能力比作一家"银行柜台",那么应用管理就是这个柜台的"总控室"——它决定了哪些业务线可以收款、通过哪些方式收款、每笔钱从哪里来到哪里去。
本模块是支付体系的地基,采用**"应用 → 渠道 → 订单"三层模型**:
| 层级 | 通俗理解 | 举例 |
|---|---|---|
| 应用(App) | 一条独立的业务收款线 | "在线课程"是一条线、"商城购物"是另一条线,各自独立核算 |
| 渠道(Channel) | 这条收款线支持的具体支付方式 | 微信 JSAPI、支付宝 PC、钱包余额、模拟支付…… |
| 订单(Order) | 每一次真实的收付款行为 | 学员小张花 99 元买了一门课程,这就产生了一笔订单 |
三层之间是"一对多"的关系:一个应用可以挂多个渠道,一个应用可以产生多笔订单,一笔订单可以有多次退款。
核心能力一览:
- 统一支付网关:新业务线接入支付只需"建应用 → 配渠道"两步,无需重复对接第三方 SDK
- 多渠道聚合:同一应用同时支持微信支付(6 种子类型)、支付宝(5 种子类型)、钱包支付、模拟支付共 13 种渠道
- 订单全生命周期:覆盖下单 → 支付 → 退款 → 转账 → 回调通知全流程
- 双保险对账:被动接收渠道回调 + 主动查询第三方结果,杜绝"掉单"
1.2 目标用户
| 用户角色 | 核心诉求 | 使用频率 |
|---|---|---|
| 支付配置人员(李姐) | 为新业务线创建应用、配置渠道参数,确保支付通道畅通 | 按需(新业务上线时) |
| 支付运营人员(小王) | 日常查看订单状态、排查掉单问题、处理渠道异常 | 每日 |
| 财务人员(老张) | 导出订单/退款报表进行月度对账,核对渠道手续费 | 每周/每月 |
| 业务开发者(小陈) | 调用支付 API 为自己的业务系统接入收款能力 | 按需(开发阶段) |
| C 端学员/会员 | 在收银台选择支付方式,完成付款 | 每日 |
1.3 业务价值
| 价值维度 | 具体收益 | 量化指标 |
|---|---|---|
| 降低接入成本 | 新业务线无需重复对接支付 SDK,统一网关一步接入 | 接入时间从 3 天 → 2 小时 |
| 提升运营效率 | 渠道状态热切换、费率灵活配置,无需开发介入 | 运营人员自主完成 100% 渠道调整 |
| 保障资金安全 | 订单状态机严格管控 + 主动同步对账 | 掉单率 < 0.01% |
| 支撑业务扩展 | 应用与渠道解耦,新增渠道只需实现 PayClient 接口 | 新渠道上线周期 < 1 天 |
1.4 功能范围
| 功能模块 | 后台管理端 | 前台用户端 | 优先级 |
|---|---|---|---|
| 应用管理(CRUD + 状态切换) | ✅ | — | P0 |
| 渠道管理(CRUD + 状态切换) | ✅ | — | P0 |
| 支付订单管理(列表/详情/同步/导出) | ✅ | ✅(仅本人) | P0 |
| 退款订单管理(列表/详情/同步/导出) | ✅ | — | P0 |
| 转账订单管理(列表/详情/导出) | ✅ | — | P1 |
| 回调通知管理(任务列表/日志查看) | ✅ | — | P1 |
| 支付演示(模拟下单/退款) | ✅ | — | P2 |
| 收银台(选支付方式/提交支付/结果展示) | — | ✅ | P0 |
二、用户场景
2.1 用户角色
| 角色 | 描述 | 典型操作 |
|---|---|---|
| 超级管理员 | 拥有支付模块全部权限 | 创建应用、配置渠道、审核退款 |
| 支付配置人员 | 负责应用与渠道的日常配置 | 建应用、填渠道参数、调费率 |
| 支付运营人员 | 日常支付运维与异常处理 | 查订单、同步状态、处理渠道异常 |
| 财务人员 | 资金对账与报表导出 | 导出订单/退款 Excel、核对手续费 |
| 业务开发者 | 接入支付能力的开发人员 | 模拟下单、测试支付流程 |
| C 端用户 | 前台支付操作 | 选支付方式、完成付款、查订单 |
2.2 使用场景
场景1:李姐为"在线课程"业务线接入支付
- 用户:支付配置人员 李姐
- 场景:公司新上线了"在线课程"业务 → 李姐登录后台 → 进入"支付管理 → 应用管理" → 点击"新建应用" → 填写应用名称"在线课程"、标识"course"、回调地址 → 提交后进入该应用的渠道管理 → 新建"微信 JSAPI 支付"渠道 → 填写商户号、AppID、API 密钥 → 再新建"支付宝 PC 网站支付"渠道 → 填写支付宝 AppID、私钥、公钥 → 完成配置
- 期望:课程系统通过统一 API 即可同时支持微信和支付宝收款,后续新增渠道无需改代码
场景2:小王排查"掉单"问题
- 用户:支付运营人员 小王
- 场景:用户反馈"微信已经扣款了但页面还显示未支付" → 小王进入"订单管理" → 通过商户订单号搜索定位到问题订单 → 进入详情页查看,发现订单状态仍为"未支付" → 点击"同步订单"按钮 → 系统主动向微信查询支付结果 → 订单状态更新为"支付成功" → 系统自动回调通知课程系统更新业务状态
- 期望:30 秒内完成订单状态同步,用户端实时看到最新状态
场景3:老张月末对账
- 用户:财务人员 老张
- 场景:月末老张需要核对本月所有支付和退款数据 → 进入"订单管理" → 筛选本月时间范围 → 点击"导出 Excel" → 获得包含订单号、金额、渠道手续费、状态的完整报表 → 同样操作导出退款报表 → 将两份报表与微信/支付宝商户后台的账单逐笔核对 → 发现一笔差异后通过订单详情中的"渠道订单号"去第三方后台核实
- 期望:导出的 Excel 字段完整、金额以"元"为单位展示,可直接用于对账
场景4:学员小陈在前台购买课程
- 用户:C 端学员 小陈
- 场景:小陈在课程详情页点击"立即购买" → 跳转到收银台页面 → 看到订单金额 99 元 → 页面展示可用支付方式(微信支付、支付宝、钱包余额) → 小陈选择"微信支付" → 点击"确认支付" → 微信弹出支付窗口 → 小陈输入密码完成支付 → 页面跳转到"支付成功"结果页
- 期望:支付流程流畅无中断,支付成功后结果页秒级展示
场景5:微信支付渠道临时故障
- 用户:支付运营人员 小王
- 场景:收到告警"微信支付渠道异常" → 小王进入"渠道管理" → 找到对应的微信渠道 → 紧急关闭该渠道 → 前台收银台立即不再展示微信支付选项 → 用户使用支付宝或钱包继续支付 → 故障修复后重新开启渠道 → 在"回调通知"页面检查异常期间的失败通知 → 手动重试失败的通知任务
- 期望:从发现异常到关闭渠道 < 1 分钟,不影响其他支付方式的正常使用
场景6:小陈开发阶段验证支付流程
- 用户:业务开发者 小陈
- 场景:小陈刚完成课程系统的支付对接 → 进入"支付演示"页面 → 创建一笔 0.01 元的示例订单 → 选择"模拟支付"渠道 → 订单立即支付成功 → 小陈验证回调通知是否正常 → 再对这笔订单发起退款 → 验证退款回调是否正常
- 期望:无需真实资金即可完成完整的"下单 → 支付 → 退款"流程验证
2.3 用户故事与验收标准
| 编号 | 用户故事 | 验收标准 |
|---|---|---|
| US-01 | 作为支付配置人员,我希望创建应用后能立即配置渠道,以便业务线快速上线 | ① 创建应用到开始配置渠道 < 3 步 ② 渠道创建后状态默认为"开启" ③ 应用标识创建后不可修改 |
| US-02 | 作为运营人员,我希望一键同步订单状态,以便快速解决掉单投诉 | ① 仅"未支付"状态订单可同步 ② 同步操作响应时间 < 3 秒 ③ 同步成功后订单状态立即更新 |
| US-03 | 作为财务人员,我希望导出包含渠道手续费的订单报表,以便高效对账 | ① 金额字段以"元"为单位、保留 2 位小数 ② 导出字段不少于 10 个 ③ 单次导出 < 10 秒(万条以内) |
| US-04 | 作为 C 端用户,我希望收银台只展示可用的支付方式,避免选择后才发现不可用 | ① 仅展示"开启"状态的应用和渠道 ② 渠道列表响应时间 < 200ms ③ 钱包支付展示当前余额 |
| US-05 | 作为运营人员,我希望关闭异常渠道后立即生效,以便快速隔离故障 | ① 渠道关闭后 < 5 秒前台不再展示 ② 已创建的订单不受影响 ③ 重新开启后自动恢复 |
| US-06 | 作为开发者,我希望通过演示功能验证完整支付流程,以便上线前充分测试 | ① 支持创建示例订单 ② 支持模拟支付和退款 ③ 示例数据与正式数据隔离 |
| US-07 | 作为运营人员,我希望查看回调通知的执行日志,以便排查通知失败原因 | ① 通知日志包含每次执行的时间、状态、响应内容 ② 失败通知支持手动重试 ③ 重试策略为指数退避 |
三、功能需求
3.1 应用管理
3.1.1 描述
应用是支付能力的基本管理单元。每个应用代表一条独立的业务收款线(如"商城"、"课程"、"会员"),拥有独立的渠道配置和回调地址。一个租户下可创建多个应用,各应用之间数据完全隔离。
3.1.2 页面原型

3.1.3 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| APP-001 | 应用标识(appKey)在租户内唯一,创建后不可修改 | 标识是业务系统调用 API 的凭证,变更会导致已有对接失败 |
| APP-002 | 应用名称不可为空,最大 32 字符 | 方便运营人员在列表中快速识别应用 |
| APP-003 | 删除应用前需校验:该应用下是否存在关联渠道或未完成订单 | 防止误删导致渠道配置丢失或订单数据断裂 |
| APP-004 | 关闭应用后,该应用下所有渠道在前台不可用(收银台不展示) | 一键紧急止血,应对应用级别的异常情况 |
| APP-005 | 关闭应用不影响后台管理端的查看和操作 | 运营和财务人员仍需查看历史数据 |
| APP-006 | 删除采用逻辑删除(deleted 字段标记) | 支付数据需永久保留用于审计和对账 |
| APP-007 | 回调地址需进行 URL 格式校验 | 无效 URL 会导致支付结果无法通知业务系统 |
3.1.4 接口列表
| 接口 | 方法 | 路径 | 权限标识 | 说明 |
|---|---|---|---|---|
| 创建支付应用 | POST | /pay/app/create | pay:app:create | 创建新应用,默认开启 |
| 更新支付应用 | PUT | /pay/app/update | pay:app:update | 修改应用信息(不含标识) |
| 更新应用状态 | PUT | /pay/app/update-status | pay:app:update | 开启/关闭应用 |
| 删除支付应用 | DELETE | /pay/app/delete | pay:app:delete | 逻辑删除,需校验无关联 |
| 获取应用详情 | GET | /pay/app/get | pay:app:query | 根据 ID 获取详情 |
| 获取应用分页 | GET | /pay/app/page | pay:app:query | 分页列表,含关联渠道 |
| 获取应用精简列表 | GET | /pay/app/list | pay:merchant:query | 下拉选择用 |
3.2 支付渠道管理
3.2.1 描述
渠道是应用下的具体支付方式配置。每个应用可配置多种渠道(如微信 JSAPI、支付宝 PC 等),每种渠道有独立的配置参数和费率。渠道管理是支付配置的核心——配置错误直接导致用户无法付款。
3.2.2 页面原型

创建渠道表单(选择渠道类型后动态渲染配置项):

3.2.3 支持的渠道类型
| 渠道编码 | 渠道名称 | 渠道分组 | 适用场景 | 通俗解释 |
|---|---|---|---|---|
| wx_pub | 微信 JSAPI 支付 | 微信支付 | 微信公众号网页内支付 | 用户在公众号里点"付款"弹出来的微信支付 |
| wx_lite | 微信小程序支付 | 微信支付 | 小程序内支付 | 小程序里买东西时的微信支付 |
| wx_app | 微信 App 支付 | 微信支付 | 移动 App 内支付 | 打开 App 后调起微信来付款 |
| wx_native | 微信 Native 支付 | 微信支付 | PC 网站扫码支付 | 电脑上显示一个二维码,用手机微信扫码付 |
| wx_wap | 微信 H5 支付 | 微信支付 | 手机浏览器支付 | 用手机浏览器打开网页时的微信支付 |
| wx_bar | 微信付款码支付 | 微信支付 | 线下门店 | 用户出示付款码,商家用扫码枪扫 |
| alipay_pc | 支付宝 PC 网站支付 | 支付宝 | PC 浏览器支付 | 电脑上跳转到支付宝网页去付款 |
| alipay_wap | 支付宝 Wap 支付 | 支付宝 | 手机浏览器支付 | 手机上跳转到支付宝去付款 |
| alipay_app | 支付宝 App 支付 | 支付宝 | 移动 App 内支付 | 在 App 里调起支付宝来付款 |
| alipay_qr | 支付宝扫码支付 | 支付宝 | 扫码支付 | 展示支付宝二维码供用户扫 |
| alipay_bar | 支付宝条码支付 | 支付宝 | 线下门店 | 用户出示支付宝付款码,商家扫 |
| wallet | 钱包支付 | 内部支付 | 使用平台余额 | 直接扣用户钱包里的钱,不用跳第三方 |
| mock | 模拟支付 | 测试渠道 | 开发测试 | 不花真钱,模拟一下支付成功 |
3.2.4 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| CH-001 | 同一应用下,同一渠道编码只能配置一个 | 避免同一支付方式出现多个配置导致歧义 |
| CH-002 | 渠道编码创建后不可修改 | 渠道编码是系统识别支付方式的关键标识 |
| CH-003 | 渠道费率取值 [0, 100],支持小数(如 0.6 表示 0.6%) | 用于计算渠道手续费,便于财务核算 |
| CH-004 | 渠道配置参数以 JSON 格式存储 | 不同渠道类型的参数差异大,JSON 提供灵活性 |
| CH-005 | 渠道状态变更后,系统自动刷新 PayClient 缓存 | 确保配置变更立即生效 |
| CH-006 | 前台收银台只展示"开启"状态的渠道 | 关闭的渠道不应出现在用户选择列表中 |
3.2.5 接口列表
| 接口 | 方法 | 路径 | 权限标识 | 说明 |
|---|---|---|---|---|
| 创建支付渠道 | POST | /pay/channel/create | pay:channel:create | 为指定应用创建渠道 |
| 更新支付渠道 | PUT | /pay/channel/update | pay:channel:update | 修改渠道配置和费率 |
| 删除支付渠道 | DELETE | /pay/channel/delete | pay:channel:delete | 逻辑删除渠道 |
| 获取渠道详情 | GET | /pay/channel/get | pay:channel:query | 按 ID 或 appId+code 获取 |
| 获取渠道列表 | GET | /pay/channel/list | pay:channel:query | 获取指定应用下所有渠道 |
| 获取启用渠道编码 | GET | /pay/channel/get-enable-code-list | 内部接口 | 前台收银台获取可用渠道 |
3.3 支付订单管理
3.3.1 描述
支付订单是每一次收付款行为的核心记录。订单从创建到终结,经历完整的状态流转。系统提供"被动回调 + 主动同步"双保险机制,确保订单状态与第三方支付渠道保持一致。
3.3.2 订单状态机

状态转换条件:
| 起始状态 | 目标状态 | 触发条件 | 通俗解释 |
|---|---|---|---|
| 未支付(0) | 支付成功(10) | 渠道回调确认到账 / 主动同步确认 | "钱到了" |
| 未支付(0) | 支付关闭(30) | 超过过期时间未支付 | "等太久,自动作废了" |
| 支付成功(10) | 已退款(20) | 累计退款金额 = 支付金额 | "全额退了" |
注意:部分退款后订单状态仍为"支付成功(10)",只有全额退款才变为"已退款(20)"。
3.3.3 页面原型

订单详情页分区展示:
| 信息分区 | 包含字段 |
|---|---|
| 基本信息 | 订单编号、应用名称、商户订单号、商品标题、支付金额、订单状态 |
| 渠道信息 | 渠道名称、渠道编码、手续费率、手续费金额、渠道订单号 |
| 用户信息 | 用户编号、用户类型、用户 IP |
| 时间信息 | 创建时间、支付成功时间、过期时间 |
| 扩展信息 | 每次渠道调用的记录(外部订单号、调用状态、通知数据) |
| 退款信息 | 已退款总金额 |
3.3.4 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| ORD-001 | 支付金额以"分"为单位存储,展示时转换为"元"(保留 2 位小数) | 避免浮点精度问题导致金额计算错误 |
| ORD-002 | 商户订单号在同一应用内唯一 | 防止同一业务订单重复创建支付订单 |
| ORD-003 | 订单创建时需设置过期时间,过期后自动关闭 | 避免长期挂起的无效订单占用资源 |
| ORD-004 | 仅"未支付"状态的订单可执行同步操作 | 已支付/已关闭的订单无需再查询第三方 |
| ORD-005 | 每次提交支付请求生成一条扩展记录 | 记录每次渠道调用的详情,便于排查问题 |
| ORD-006 | 支付成功后,手续费 = 支付金额 × 费率 / 100 | 用于财务核算渠道成本 |
| ORD-007 | 订单的渠道信息在支付提交时冗余存储 | 后续渠道配置变更不影响历史订单数据 |
| ORD-008 | 前台查询订单时校验当前用户与订单归属一致 | 防止越权查看他人订单 |
3.3.5 接口列表
| 接口 | 方法 | 路径 | 权限标识 | 说明 |
|---|---|---|---|---|
| 获取订单详情 | GET | /pay/order/get | pay:order:query | 支持同步参数 |
| 获取订单扩展详情 | GET | /pay/order/get-detail | pay:order:query | 含扩展记录和渠道信息 |
| 提交支付订单 | POST | /pay/order/submit | 业务系统调用 | 返回渠道支付参数 |
| 获取订单分页 | GET | /pay/order/page | pay:order:query | 多维度筛选 |
| 导出订单 Excel | GET | /pay/order/export-excel | pay:order:export | 按筛选条件导出 |
| 用户端-获取订单 | GET | /pay/order/get(App) | 登录即可 | 自动校验用户归属 |
| 用户端-提交支付 | POST | /pay/order/submit(App) | 登录即可 | 返回渠道支付参数 |
3.4 退款订单管理
3.4.1 描述
退款管理处理"把钱退回去"的场景。支持同一笔订单多次部分退款,退款总额不超过原始支付金额。退款状态由第三方支付渠道的退款结果决定。
3.4.2 退款状态机

3.4.3 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| REF-001 | 商户退款号在同一应用内唯一 | 防止重复退款 |
| REF-002 | 同一笔订单的累计退款金额不能超过原始支付金额 | 避免多退导致资金损失 |
| REF-003 | 退款单创建后自动异步调用渠道退款接口 | 减少用户等待时间 |
| REF-004 | 退款成功后更新订单的累计退款金额 | 用于判断是否全额退款 |
| REF-005 | 累计退款金额 = 支付金额时,订单状态变为"已退款" | 标记订单的退款终态 |
| REF-006 | 退款失败时记录渠道错误码和错误信息 | 便于排查退款失败原因并重试 |
3.4.4 接口列表
| 接口 | 方法 | 路径 | 权限标识 | 说明 |
|---|---|---|---|---|
| 获取退款详情 | GET | /pay/refund/get | pay:refund:query | 含渠道退款信息 |
| 获取退款分页 | GET | /pay/refund/page | pay:refund:query | 多维度筛选 |
| 导出退款 Excel | GET | /pay/refund/export-excel | pay:refund:export | 按筛选条件导出 |
3.5 转账订单管理
3.5.1 描述
转账是"平台主动给用户打钱"的能力,适用于佣金提现、奖励发放、奖学金等场景。支持微信转账和支付宝转账。
3.5.2 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| TRF-001 | 商户转账号在同一应用内唯一 | 防止重复转账导致资金损失 |
| TRF-002 | 转账单创建后异步调用渠道转账接口 | 转账不需要用户实时等待 |
| TRF-003 | 微信转账存在 channelPackageInfo 字段 | 用于前端调起用户确认收款 |
| TRF-004 | 转账成功后记录渠道转账单号和成功时间 | 便于追溯和审计 |
3.5.3 接口列表
| 接口 | 方法 | 路径 | 权限标识 | 说明 |
|---|---|---|---|---|
| 获取转账详情 | GET | /pay/transfer/get | pay:transfer:query | 含渠道信息 |
| 获取转账分页 | GET | /pay/transfer/page | pay:transfer:query | 多维度筛选 |
| 导出转账 Excel | GET | /pay/transfer/export-excel | pay:transfer:export | 按筛选条件导出 |
3.6 回调通知管理
3.6.1 描述
回调通知是第三方支付渠道"主动告诉我们结果"的机制。系统收到回调后创建通知任务,异步通知业务系统更新状态。如果通知失败,系统按指数退避策略自动重试。
通俗理解:就像快递柜给你发短信说"快递到了"——如果短信没发出去,系统会隔一会儿再发一次。
3.6.2 通知重试策略
| 通知次数 | 间隔时间 | 累计等待 |
|---|---|---|
| 第 1 次 | 立即 | 0 |
| 第 2 次 | 15 秒后 | 15 秒 |
| 第 3 次 | 30 秒后 | 45 秒 |
| 第 4 次 | 1 分钟后 | 1 分 45 秒 |
| 第 5 次 | 2 分钟后 | 3 分 45 秒 |
| 第 6 次 | 4 分钟后 | 7 分 45 秒 |
| 第 7 次 | 8 分钟后 | 15 分 45 秒 |
| 第 8 次 | 16 分钟后 | 31 分 45 秒 |
最多重试 8 次,超过后标记为"通知失败",需人工介入处理。
3.6.3 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| NTF-001 | 渠道回调接口无需登录认证(@PermitAll) | 第三方支付渠道无法携带用户 Token |
| NTF-002 | 渠道回调需验证签名 | 确保回调数据确实来自微信/支付宝,防止伪造 |
| NTF-003 | 通知地址来自应用配置的回调地址 | 不同业务线可配置不同的通知接收地址 |
| NTF-004 | 通知失败按指数退避策略重试 | 平衡通知及时性和系统压力 |
3.6.4 接口列表
| 接口 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 支付渠道回调 | POST | /pay/notify/order/ | 渠道调用,无需认证 |
| 退款渠道回调 | POST | /pay/notify/refund/ | 渠道调用,无需认证 |
| 转账渠道回调 | POST | /pay/notify/transfer/ | 渠道调用,无需认证 |
| 获取通知详情 | GET | /pay/notify/get-detail | 含通知日志列表 |
| 获取通知分页 | GET | /pay/notify/page | 查看通知任务列表 |
3.7 支付演示
3.7.1 描述
支付演示是开发和测试阶段的"沙盒",通过创建示例订单走通完整的"下单 → 支付 → 退款"流程,验证渠道配置是否正确,无需真实资金。
3.7.2 业务规则
| 规则编号 | 规则描述 | 设计原因 |
|---|---|---|
| DEMO-001 | 示例订单数据与正式订单数据隔离 | 避免测试数据污染生产环境 |
| DEMO-002 | 支持模拟支付和模拟退款 | 全流程验证无需真实资金 |
| DEMO-003 | 示例订单支持分页查询 | 方便查看历史测试记录 |
3.8 用户前台(收银台)
3.8.1 描述
收银台是 C 端用户完成支付的核心界面。用户在这里看到订单信息和可用的支付方式,选择后完成付款。
3.8.2 收银台页面原型

3.8.3 各渠道支付交互方式
| 渠道类型 | 用户看到的交互 | 通俗解释 |
|---|---|---|
| 微信 JSAPI | 微信内弹出支付密码框 | 在公众号里买东西,直接输密码 |
| 微信小程序 | 小程序内弹出支付框 | 小程序里买东西 |
| 微信 App | 跳转到微信 App 支付 | 打开 App 后自动跳到微信 |
| 微信 Native | 页面显示二维码 | 电脑上扫码付款 |
| 微信 H5 | 跳转到微信支付页 | 手机浏览器里跳出来 |
| 支付宝 PC | 跳转到支付宝网页 | 电脑上跳到支付宝 |
| 支付宝 Wap | 跳转到支付宝手机版 | 手机上跳到支付宝 |
| 支付宝 App | 跳转到支付宝 App | App 里调起支付宝 |
| 支付宝扫码 | 显示支付宝二维码 | 用支付宝扫一下 |
| 钱包支付 | 直接扣余额,无跳转 | 最快,不用跳来跳去 |
| 模拟支付 | 直接显示成功 | 测试用的,不花真钱 |
3.8.4 接口列表
| 接口 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 获取可用渠道编码 | GET | /pay/channel/get-enable-code-list | 仅返回开启状态的渠道 |
| 获取订单 | GET | /pay/order/get | 校验用户归属 |
| 提交支付 | POST | /pay/order/submit | 返回渠道支付参数 |
四、非功能需求
4.1 性能需求
| 指标 | 要求 | 说明 |
|---|---|---|
| 订单创建响应 | ≤ 200ms(P99) | 用户不应感知到创建延迟 |
| 支付提交响应 | ≤ 500ms(P99) | 不含渠道侧耗时 |
| 订单列表查询 | ≤ 500ms(P99) | 含多维度筛选条件 |
| 渠道回调处理 | ≤ 200ms | 快速响应渠道,避免渠道超时重试 |
| 并发处理能力 | ≥ 1000 TPS | 支撑高峰期支付请求 |
| 回调重试 | 最多 8 次 | 指数退避策略,总耗时约 32 分钟 |
4.2 安全需求
| 安全项 | 要求 | 实现方式 |
|---|---|---|
| 接口认证 | 后台接口需登录 | Token 认证 |
| 权限控制 | 每个接口配独立权限标识 | @PreAuthorize 注解 |
| 回调验签 | 验证渠道回调签名 | 微信/支付宝 SDK 内置验签 |
| 数据隔离 | 多租户数据隔离 | tenant_id 字段 + MyBatis 拦截器 |
| 越权防护 | 用户只能查自己的订单 | 接口层校验 userId 归属 |
| 敏感数据 | 渠道私钥/密钥加密存储 | AES 加密 + 密钥管理 |
| 幂等性 | 防止重复支付 | 商户订单号应用内唯一 |
| 日志审计 | 关键操作记录日志 | 创建应用、配置渠道、退款等 |
4.3 兼容性需求
| 兼容项 | 要求 |
|---|---|
| 数据库 | MySQL 5.7+、PostgreSQL 12+ |
| 前端浏览器 | Chrome 80+、Safari 13+、微信内置浏览器 |
| 微信 API | V3 版本 |
| 支付宝 API | 开放平台最新 SDK |
| 金额精度 | 整数(分),展示时转元(2 位小数) |
五、数据设计
5.1 核心表关系

5.2 数据表清单
| 表名 | 用途 | 核心字段 | 索引 |
|---|---|---|---|
| pay_app | 支付应用 | id, name, app_key, status, order_notify_url | uk_app_key(app_key, tenant_id) |
| pay_channel | 支付渠道 | id, app_id, code, name, status, config, fee_rate | uk_app_code(app_id, code, tenant_id) |
| pay_order | 支付订单 | id, app_id, channel_id, merchant_order_id, price, status | idx_app_id, idx_merchant_order_id, idx_user_id, idx_status |
| pay_order_extension | 订单扩展 | id, no, order_id, channel_id, status, channel_error_code | idx_order_id, uk_no(no) |
| pay_refund | 退款订单 | id, no, app_id, order_id, merchant_refund_id, refund_price, status | idx_order_id, uk_no(no), uk_merchant_refund(app_id, merchant_refund_id) |
| pay_transfer | 转账订单 | id, no, app_id, channel_id, merchant_transfer_id, price, status | uk_no(no), uk_app_merchant(app_id, merchant_transfer_id) |
| pay_notify_task | 通知任务 | id, app_id, type, data_id, status, notify_times | idx_status_next_time(status, next_execute_time) |
| pay_notify_log | 通知日志 | id, task_id, notify_times, response, status | idx_task_id(task_id) |
5.3 数据字典
订单状态枚举(pay_order.status):
| 状态码 | 状态名 | 说明 |
|---|---|---|
| 0 | 未支付 | 初始状态,等待用户付款 |
| 10 | 支付成功 | 渠道已确认到账 |
| 20 | 已退款 | 全额退款完成 |
| 30 | 支付关闭 | 超时未支付,系统自动关闭 |
退款状态枚举(pay_refund.status):
| 状态码 | 状态名 | 说明 |
|---|---|---|
| 0 | 未退款 | 退款单已创建,等待渠道处理 |
| 10 | 退款成功 | 渠道确认退款到账 |
| 20 | 退款失败 | 渠道退款处理失败,可重试 |
通知类型枚举(pay_notify_task.type):
| 类型码 | 类型名 | 说明 |
|---|---|---|
| 1 | 支付通知 | 支付结果通知业务系统 |
| 2 | 退款通知 | 退款结果通知业务系统 |
| 3 | 转账通知 | 转账结果通知业务系统 |
订单号生成规则:
| 号码类型 | 格式 | 示例 |
|---|---|---|
| 支付外部订单号 | P + yyyyMMddHHmmss + 4位序号 + 4位随机数 | P2026092415301200018372 |
| 退款外部退款号 | R + yyyyMMddHHmmss + 4位序号 + 4位随机数 | R2026092415301200015621 |
| 转账单号 | T + yyyyMMddHHmmss + 4位序号 + 4位随机数 | T2026092415301200013845 |
六、跨模块联动
6.1 联动关系总览
| 关联模块 | 联动方式 | 数据流向 | 触发场景 |
|---|---|---|---|
| 钱包管理(04-02) | 钱包支付渠道直接扣减用户钱包余额 | 支付订单 → 钱包流水 | 用户选择"钱包支付"时 |
| 会员管理(05-01) | 订单关联会员用户信息 | 支付订单.user_id → member_user.id | 所有支付场景 |
| 商城/课程/企业应用 | 支付成功后回调通知业务系统更新订单状态 | 支付回调 → 业务系统 | 支付成功/退款成功 |
| 通知模块 | 支付/退款/转账结果通过站内信/短信通知用户 | 支付事件 → 通知模块 | 状态变更时 |
| 日志审计(01-08) | 关键操作记录操作日志 | 操作 → 操作日志表 | 创建应用、配置渠道、退款等 |
| 定时任务(02-03) | 订单超时自动关闭、通知重试定时扫描 | 定时触发 → 订单/通知 | 每分钟扫描过期订单 |
6.2 关键联动流程
流程1:钱包支付 → 钱包余额扣减

流程2:支付成功 → 多模块状态同步

6.3 数据一致性要求
| 一致性场景 | 保障机制 | 说明 |
|---|---|---|
| 支付订单与第三方渠道状态一致 | 被动回调 + 主动同步双保险 | 回调失败时通过定时任务主动查询 |
| 钱包支付扣款与订单状态一致 | 数据库事务 + Redis 分布式锁 | 扣款和订单更新在同一事务内 |
| 退款金额与订单累计退款一致 | 数据库事务 | 退款成功回调中更新累计退款金额 |
| 业务系统状态与支付状态一致 | 回调通知 + 指数退避重试 | 最多 8 次重试,总耗时约 32 分钟 |
七、附录
7.1 名词解释
| 名词 | 通俗解释 | 在本系统中的含义 |
|---|---|---|
| 支付应用(Pay App) | 一条独立的收款业务线 | 如"商城"、"课程"各自独立核算 |
| 支付渠道(Pay Channel) | 具体的支付方式 | 微信 JSAPI、支付宝 PC、钱包余额等 |
| 支付订单(Pay Order) | 一次收付款行为的记录 | 包含金额、状态、渠道等信息 |
| 订单扩展(Order Extension) | 每次调用支付渠道时的"通话记录" | 记录渠道调用的详细参数和结果 |
| 退款订单(Pay Refund) | 一次退款行为的记录 | 关联原始支付订单 |
| 转账订单(Pay Transfer) | 平台给用户打款的记录 | 佣金提现、奖励发放等场景 |
| 渠道回调(Channel Notify) | 第三方"主动告诉我们结果" | 微信/支付宝支付完成后发来的通知 |
| 商户订单号 | 业务系统给的"内部编号" | 在同一应用内唯一 |
| 外部订单号 | 系统生成的"对外的编号" | 格式 P + 时间戳 + 序号,用于对接第三方 |
| 渠道费率(Fee Rate) | 第三方收的"手续费比例" | 如 0.6% 表示每笔交易收 0.6% 手续费 |
| PayClient | 每种支付方式的"驱动程序" | 每个渠道一个实现类,负责调用渠道 API |
| 钱包支付(Wallet Pay) | 直接扣平台余额 | 不用跳第三方,最快 |
| 模拟支付(Mock Pay) | 测试用的"假支付" | 不花真钱,走一遍流程 |
| 指数退避(Exponential Backoff) | "重试间隔越来越长"的策略 | 15秒 → 30秒 → 1分钟 → 2分钟… |
| 收银台 | 用户选择支付方式的页面 | 就像超市收银台上问你"微信还是支付宝" |
| 掉单 | 用户付了钱但系统显示"未支付" | 通过主动同步机制解决 |
| 逻辑删除 | 数据不真正删掉,只标记为"已删除" | 支付数据需永久保留用于审计 |
| 租户隔离 | 不同客户的数据互相看不到 | SaaS 平台的基本安全要求 |
7.2 权限标识汇总
| 权限标识 | 说明 | 所属子模块 |
|---|---|---|
| pay:app:create | 创建支付应用 | 应用管理 |
| pay:app:update | 更新支付应用(含状态切换) | 应用管理 |
| pay:app:delete | 删除支付应用 | 应用管理 |
| pay:app:query | 查询支付应用 | 应用管理 |
| pay:merchant:query | 查询商户应用列表(下拉) | 应用管理 |
| pay:channel:create | 创建支付渠道 | 渠道管理 |
| pay:channel:update | 更新支付渠道 | 渠道管理 |
| pay:channel:delete | 删除支付渠道 | 渠道管理 |
| pay:channel:query | 查询支付渠道 | 渠道管理 |
| pay:order:query | 查询支付订单 | 订单管理 |
| pay:order:export | 导出支付订单 | 订单管理 |
| pay:refund:query | 查询退款订单 | 退款管理 |
| pay:refund:export | 导出退款订单 | 退款管理 |
| pay:transfer:query | 查询转账订单 | 转账管理 |
| pay:transfer:export | 导出转账订单 | 转账管理 |
| pay:notify:query | 查询回调通知 | 回调通知 |
7.3 错误码定义
| 错误码 | 错误信息 | 触发场景 | 处理建议 |
|---|---|---|---|
| PAY_APP_001 | 支付应用不存在 | 操作的应用 ID 无效 | 检查应用是否已删除 |
| PAY_APP_002 | 支付应用已关闭 | 应用状态为关闭 | 联系管理员开启应用 |
| PAY_CHANNEL_001 | 支付渠道不存在 | 指定的渠道未配置 | 检查渠道配置 |
| PAY_CHANNEL_002 | 支付渠道已关闭 | 渠道状态为关闭 | 联系管理员开启渠道 |
| PAY_CHANNEL_003 | 渠道编码重复 | 同应用下已存在相同编码 | 每个渠道编码只能配一个 |
| PAY_CHANNEL_004 | 渠道配置参数错误 | 配置参数不合法 | 检查商户号、密钥等参数 |
| PAY_ORDER_001 | 支付订单不存在 | 指定的订单 ID 无效 | 检查订单号是否正确 |
| PAY_ORDER_002 | 支付订单状态异常 | 当前状态不允许该操作 | 检查订单当前状态 |
| PAY_ORDER_003 | 支付订单已过期 | 超过过期时间 | 重新创建订单 |
| PAY_ORDER_004 | 支付金额不匹配 | 实际金额与订单不一致 | 检查金额计算 |
| PAY_ORDER_005 | 商户订单号已存在 | 同应用下订单号重复 | 使用不同的商户订单号 |
| PAY_REFUND_001 | 退款订单不存在 | 指定的退款单 ID 无效 | 检查退款单号 |
| PAY_REFUND_002 | 退款金额超出 | 累计退款超过支付金额 | 检查退款金额 |
| PAY_REFUND_003 | 商户退款号已存在 | 同应用下退款号重复 | 使用不同的商户退款号 |
7.4 变更日志
| 版本 | 日期 | 变更内容 |
|---|---|---|
| v1.0 | 2026-09-24 | 初稿:8 个子模块的完整功能定义 |
| v2.0 | 2026-09-19 | 增强:① 6 个命名用户场景 ② 7 个可量化验收标准 ③ 页面原型 ④ 业务规则增加设计原因 ⑤ 新增跨模块联动章节 ⑥ 18 条名词解释 ⑦ 14 个错误码含处理建议 |
本文档为 PMForge 支付模块应用管理 PRD v2.0,后续将随项目迭代持续更新。