更新一下
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 7月迭代技术方案(标准评审稿)
|
||||
|
||||
> 状态:待评审
|
||||
> 最后更新:2026-07-17
|
||||
> 最后更新:2026-07-20
|
||||
> 分支:`Iteration/7-11`
|
||||
> 系统:`junhong_cmp_fiber` 及配套后台、代理端、C 端前端
|
||||
> 负责人:待指定
|
||||
@@ -38,7 +38,7 @@
|
||||
- 套餐临期企业微信消息推送;本期先完成站内通知和防重记录。
|
||||
- 全仓 MVC/贫血模型一次性重构。
|
||||
- 为旧退款和线下充值审批接口建设长期兼容层。
|
||||
- 后端提供 Excel 模板下载接口;模板由前端静态资源随版本发布。
|
||||
- 后端提供批量导入模板下载接口;CSV 模板由前端静态资源随版本发布。
|
||||
- 微信/支付宝自动退款,以及基于套餐规则的自动限速。
|
||||
- 运营商解除实名后自动回滚本地实名状态;第一版只保留防腐层入口和集成记录。
|
||||
- 禅道草稿 #41“代理查询限制”和 #51“不同品类资产换货”;草稿不进入本期开发、工时和验收。
|
||||
@@ -52,18 +52,18 @@
|
||||
| D-03 | 不建设本地审批流;节点、审批人、意见和审批附件全部由企微模板及审批详情负责 | 18、20、21 |
|
||||
| D-04 | 本系统保存提交业务快照、本地业务资料和企微审批详情快照,审批人能够看到审批对象、备注和附件 | 18、20、21 |
|
||||
| D-05 | 平台员工不建立钱包信用额度,信用额度只属于代理主钱包 | 17、19 |
|
||||
| D-06 | 批量订购支付方式整批统一,Excel 不包含支付方式 | 19 |
|
||||
| D-07 | 角色级导出字段权限本期落地,服务端取角色授权与用户选择的交集 | 14 |
|
||||
| D-08 | Gateway 只按 `cardNo` 手动设置/取消限速;设备入口先解析当前绑定卡,不做套餐自动限速 | 10 |
|
||||
| D-06 | 批量订购使用 CSV,支付方式整批统一,CSV 不包含支付方式 | 19 |
|
||||
| D-07 | 角色级导出字段权限本期落地;前端不选择、不提交字段,服务端按代码字段目录与当前账号有效角色授权并集自动解析全部导出列 | 14 |
|
||||
| D-08 | Gateway 只按 `cardNo` 手动设置固定限速等级或恢复不限速;设备入口先解析当前绑定卡,不做套餐自动限速 | 10 |
|
||||
| D-09 | 需求16整体移出本期,不创建相关表、API、流程、页面和迁移 | 16 |
|
||||
| D-10 | 退款金额在发起时固定;非代理钱包退款由财务人工处理,代理钱包仅回退原扣款主钱包;线下充值企微通过后自动入账 | 20、21 |
|
||||
| D-11 | 采用停机发布,同时切换数据库、API、Worker 和前端,旧审批接口同步下线 | 20、21 |
|
||||
| D-12 | 企微模板 ID 和控件 ID 均按不可变版本映射;编辑模板前暂停场景,发布新映射后原子切换 | 企微审批 |
|
||||
| D-13 | 设备批量分配代理与套餐系列拆为两个独立命令 | 08 |
|
||||
| D-13 | 设备批量分配代理与套餐系列拆为两个独立 CSV 命令,文件先直传私有对象存储,业务接口只接收 `file_key` 和唯一目标 | 08 |
|
||||
| D-14 | 排队套餐使用购买时长快照推算预计最终到期时间;资产详情、临期和导出共用实时 Query,定时任务仅发送通知 | 06、11、22 |
|
||||
| D-15 | 行业卡是否需要实名由运营商 `realname_link_type` 决定,`card_category` 不参与实名、复机和轮询判断 | 01、02、数据同步 |
|
||||
| D-15 | 卡是否需要实名由运营商 `realname_link_type` 决定,`card_category` 不参与实名和复机判断;本期不重新设计现有周期轮询资格 | 01、02、数据同步 |
|
||||
| D-16 | 数据同步保留轮询兜底,关键业务事件按立即、3 分钟、5 分钟触发;超频不建立退避状态 | 数据同步 |
|
||||
| D-17 | 企微账号由已登录平台员工扫码自助绑定,普通运营不录入 `userid` | 企微审批 |
|
||||
| D-17 | 企微发起身份按账号类型分流:平台/超级管理员必须扫码绑定并使用本人 `userid`,代理使用部署配置中的固定企微账号代提交;真实业务提交人始终独立进入审批表单、通知和审计 | 企微审批 |
|
||||
| D-18 | 全系统审计本次一次性切换到 Audit Event + Integration Log,多视角 API 和前端同时发布 | 全局 |
|
||||
| D-19 | 代理在线充值最低 100 元,支持微信 Native 和支付宝 PreCreate,支付成功直接入主钱包且不审批 | 21、新增充值 |
|
||||
| D-20 | 资产层只展示一个预计最终到期时间;当前套餐和全部排队主套餐共同参与推算,临期也使用同一结果 | 06、11、22 |
|
||||
@@ -72,10 +72,11 @@
|
||||
| D-23 | 代理主钱包现金可用余额降至 100 元及以下时,向代理主账号和店铺业务员发送一次站内通知;信用额度不参与预警计算 | 禅道 #97 |
|
||||
| D-24 | 客户角色只提供新建店铺的默认信用配置;修改角色配置不更新任何已有店铺,已有店铺额度只能单独调整 | 17 |
|
||||
| D-25 | 代理系列套餐授权复用现有批量接口;前端批量选择,已授权套餐明确标记并置灰 | 禅道 #43 |
|
||||
| D-26 | 一张退款单只对应一条企微审批;企微拒绝同时终结审批和退款单,原单不可修改或重提,后续仍需退款时必须重新创建退款单 | 20、企微审批 |
|
||||
|
||||
### 1.4 本期边界
|
||||
|
||||
本期包含企业微信审批、账号扫码绑定、回调与轮询补偿;不再保留“先做站内审批、以后切企微”的中间态。套餐临期的企业微信消息推送仍属于后续扩展,本期只实现站内通知及外部渠道可扩展边界。
|
||||
本期包含企业微信审批、平台账号扫码绑定、代理固定企微账号代提交、回调与轮询补偿;不再保留“先做站内审批、以后切企微”的中间态。套餐临期的企业微信消息推送仍属于后续扩展,本期只实现站内通知及外部渠道可扩展边界。
|
||||
|
||||
---
|
||||
|
||||
@@ -252,8 +253,8 @@ sequenceDiagram
|
||||
|
||||
| 类型 | 接收人 |
|
||||
|------|--------|
|
||||
| `wecom.approval.approved/rejected/cancelled` | 申请人账号 |
|
||||
| `wecom.approval.revoked_after_approved` | 申请人和财务角色账号 |
|
||||
| `wecom.approval.approved/rejected/cancelled` | 真实业务提交人账号 |
|
||||
| `wecom.approval.revoked_after_approved` | 真实业务提交人和财务角色账号 |
|
||||
| `wecom.template.invalid` | 平台超管 |
|
||||
| `package.expiring` | 代理/企业相关账号 |
|
||||
| `card_sync.failed` | 平台运维角色 |
|
||||
@@ -281,18 +282,18 @@ API:
|
||||
|
||||
企业微信负责模板、审批节点、审批人、会签/或签、通过、驳回、撤销、审批意见、审批附件和企业微信端待办。本系统不保存本地审批任务,也不提供审批按钮,只负责:
|
||||
|
||||
- 创建退款和平台员工线下充值业务单。
|
||||
- 创建退款(允许现有平台/超级管理员/代理发起)和平台员工线下充值业务单。
|
||||
- 保存提交时业务快照和本地业务资料,上传企微附件副本。
|
||||
- 以稳定场景码映射企微模板版本和控件 ID。
|
||||
- 保存 `sp_no`、审批状态、审批人/意见/附件详情快照。
|
||||
- 接收回调并以 `getapprovaldetail` 查询作为状态权威来源。
|
||||
- 审批终态后幂等执行退款或线下充值业务处理。
|
||||
|
||||
Viper 配置包含 `corp_id`、`agent_id`、`agent_secret`、回调 Token/EncodingAESKey、审批回调路径、账号绑定回调 URL、2 分钟审批轮询和 10 分钟模板验证间隔。Secret 只允许环境变量覆盖,后台只返回“是否配置”和最近连通结果。Access Token 缓存在 Redis,TTL 使用 `expires_in-300秒` 并通过锁避免并发刷新。
|
||||
Viper 配置包含 `corp_id`、`agent_id`、`agent_secret`、回调 Token/EncodingAESKey、审批回调路径、账号绑定回调 URL、代理代提交固定成员 `agent_approval_creator_userid`、2 分钟审批轮询和 10 分钟模板验证间隔。Secret 和代理代提交身份只允许通过部署配置提供,后台只返回“是否就绪”、固定成员显示名和最近连通结果,不提供在线修改固定 `userid`。Access Token 缓存在 Redis,TTL 使用 `expires_in-300秒` 并通过锁避免并发刷新。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor Staff as 平台员工
|
||||
actor Submitter as 业务提交人
|
||||
participant App as Refund/Recharge Application
|
||||
participant DB as PostgreSQL
|
||||
participant Outbox as Outbox
|
||||
@@ -301,10 +302,10 @@ sequenceDiagram
|
||||
participant Sync as Approval Sync
|
||||
participant Biz as 业务终态用例
|
||||
|
||||
Staff->>App: 创建退款/线下充值
|
||||
Submitter->>App: 创建退款/线下充值
|
||||
App->>DB: 业务单+企微实例(submitting)
|
||||
App->>Outbox: SubmissionRequested
|
||||
Worker->>WeCom: 上传附件并applyevent
|
||||
Worker->>WeCom: 按账号类型解析userid并applyevent
|
||||
WeCom-->>Worker: sp_no
|
||||
WeCom->>Sync: 加密状态回调
|
||||
Sync->>WeCom: getapprovaldetail
|
||||
@@ -337,34 +338,25 @@ sequenceDiagram
|
||||
|
||||
退款至少映射店铺、退款单号、申请金额、原因、附件和提交人;线下充值至少映射店铺、充值单号、金额、备注、附件和提交人。后台每 10 分钟验证启用版本,模板不可访问或 fingerprint 变化时暂停场景并发送系统告警。
|
||||
|
||||
#### 3.3.3 系统账号扫码绑定企微成员
|
||||
场景处于暂停中、已暂停,或当前模板版本失效时,新的退款/线下充值创建请求必须在写入任何业务单、审批实例或 Outbox 之前失败,并返回明确的“审批场景当前不可用”。前端保留用户已经填写的表单,待场景恢复后由用户重新提交;后端不为失败请求保留待补提的孤儿业务单。暂停前已经成功创建的审批实例继续接收回调、执行 2 分钟兜底同步和终态业务处理,不受场景暂停影响。
|
||||
|
||||
普通运营不录入 `userid`。员工先登录本系统,再点击“绑定企业微信”,后端生成一次性 `state` 和企微 Web 登录 URL;扫码回调后使用自建应用 Access Token 调用 `auth/getuserinfo` 获取 `userid`。
|
||||
#### 3.3.3 平台账号绑定、代理固定代提交与真实业务提交人
|
||||
|
||||
```text
|
||||
系统登录账号
|
||||
→ 创建5分钟绑定会话
|
||||
→ 打开企微Web登录二维码
|
||||
→ 回调code+state
|
||||
→ 原子消费state
|
||||
→ 换取userid并校验企业成员
|
||||
→ 保存一对一绑定
|
||||
```
|
||||
企微 `applyevent.creator_userid` 按当前登录账号类型解析:平台账号和超级管理员必须使用其系统账号扫码绑定的本人企微 `userid`;代理账号发起退款时使用部署配置中的 `agent_approval_creator_userid` 代提交。退款或线下充值的真实业务提交人始终取当前登录账号,并独立保存账号 ID、名称、角色和店铺快照。
|
||||
|
||||
约束:
|
||||
|
||||
- `state` 与前端查询 `session_id` 分开存 Redis;`state` 单次使用,绑定结果会话保留 10 分钟。
|
||||
- 回调不接受 `account_id`,目标账号只能来自服务端绑定会话。
|
||||
- `account_id` 和 `wecom_userid` 均唯一;成员已绑定其他账号时拒绝覆盖。
|
||||
- 自助解绑和管理员强制解绑不影响历史审批快照,但会阻止新审批。
|
||||
- 管理员只查看绑定状态和强制解绑,不提供 `userid` 输入框。
|
||||
- 企微自建应用可信域名和可见范围必须覆盖需要发起审批的平台员工。
|
||||
|
||||
`tb_account_wecom_mapping` 保存账号、`userid`、成员名称、CorpID、AgentID、绑定来源和验证时间。
|
||||
- 平台/超级管理员通过 5 分钟一次性会话扫码绑定;`account_id` 与 `wecom_userid` 均一对一唯一,普通运营不手工录入 `userid`。
|
||||
- 平台/超级管理员未绑定、绑定失效或成员不可用时,拒绝其新申请并原地提供绑定入口;代理账号不要求绑定企微。
|
||||
- 代理代提交固定成员必须属于当前 CorpID、处于可用状态并在自建应用可见范围内;未配置或失效时拒绝代理新申请。以上校验都在任何业务单、审批实例或 Outbox 落库前完成。
|
||||
- 企微模板中的 `submitter` 必填字段始终写入真实业务提交人名称和账号标识;代理审批单不能只展示固定代提交账号。
|
||||
- 审批实例同时保存真实业务提交人快照、本次实际使用的企微 `userid` 快照及身份来源 `self_binding/agent_proxy`;列表、详情、通知、权限与审计中的“提交人/申请人”均指真实业务提交人。
|
||||
- 平台账号换绑、解绑以及代理固定成员变更只影响新审批;历史实例保留提交时身份快照,不改写历史记录。
|
||||
- 后台账号绑定列表只允许查看和强制解绑;代理固定身份只展示就绪状态及成员显示名,不提供在线修改 `userid`。
|
||||
|
||||
#### 3.3.4 审批实例与状态同步
|
||||
|
||||
`tb_wecom_approval_instance` 保存:业务类型/ID/编号、轮次、场景、模板版本和映射快照、创建人本地账号与企微 `userid`、`sp_no`、提交业务快照、企微详情和审批人快照、业务处理结果、轮询时间、乐观锁版本。
|
||||
`tb_wecom_approval_instance` 的每条记录表示一次独立审批申请,保存:业务类型/ID/编号、场景、模板版本和映射快照、真实业务提交人账号及显示快照、实际企微发起 `userid` 快照、身份来源 `self_binding/agent_proxy`、`sp_no`、提交业务快照、企微详情和审批人快照、业务处理结果、轮询时间、乐观锁版本。退款和线下充值业务表使用 `approval_instance_id` 明确指向唯一审批申请,审批实例以 `(biz_type, biz_id)` 唯一约束保证一张业务单只有一条审批;不使用 `round_no`,也不存在从同一业务单推算“当前轮次”的逻辑。
|
||||
|
||||
状态:
|
||||
|
||||
@@ -378,16 +370,45 @@ sequenceDiagram
|
||||
| 通过后撤销 | `sp_status=6` |
|
||||
| 已删除 | `sp_status=7` |
|
||||
|
||||
`applyevent` 请求已发送但响应超时必须标记“提交结果未知”,禁止盲目重试产生重复审批。管理员在企微核对后选择“确认未创建并重新提交”或手工绑定已有 `sp_no`,后者记录高风险审计。
|
||||
`applyevent` 请求已发送但响应超时必须标记“提交结果未知”,禁止盲目重试产生重复审批。异常恢复同时提供两个受控动作:
|
||||
|
||||
- “绑定已有 `sp_no`”:先调用 `getapprovaldetail`,核对企业、模板版本、实例保存的实际企微发起 `userid`、身份来源、业务场景、真实业务提交人字段和提交业务快照;全部匹配后才允许绑定,禁止只校验编号存在。
|
||||
- “确认企微未创建并重新发送”:保留原未知尝试和 Integration Log,在同一审批申请下记录新的技术提交尝试;它不是一条新的业务审批申请。企微已经拒绝或进入其他明确业务终态后,原业务单不得再次发送;后续确有业务需要时只能重新创建新的业务单和审批申请。
|
||||
|
||||
两个动作只允许超级管理员或具备独立“企微审批异常恢复”权限的平台账号执行,并记录操作人、依据、审批申请、技术尝试或绑定 `sp_no`、校验结果和前后状态的高风险 Audit Event。
|
||||
|
||||
回调只负责验签、解密、保存 Integration Log 并触发统一 `SyncApprovalStatus`。审批中实例每 2 分钟兜底查询,回调和轮询共用状态同步用例;首次进入终态时同事务写业务 Outbox,`business_processed_at` 保证资金动作只执行一次。
|
||||
|
||||
#### 3.3.5 DDD 边界与 API
|
||||
#### 3.3.5 权限边界
|
||||
|
||||
企微能力拆分授权,禁止用一个泛化权限同时覆盖配置和异常操作:
|
||||
|
||||
| 能力 | 超级管理员 | 平台账号 | 代理账号 |
|
||||
|------|------------|----------|----------|
|
||||
| 查询连接、场景和模板版本 | 允许 | 不允许 | 不允许 |
|
||||
| 暂停/恢复场景、读取/发布模板映射 | 允许 | 不允许 | 不允许 |
|
||||
| 管理平台账号绑定列表、强制解绑 | 允许 | 不允许 | 不允许 |
|
||||
| 查询、重新绑定、解绑本人企微 | 允许 | 仅本人 | 不提供绑定能力 |
|
||||
| 审批运行列表和详情 | 允许 | 仅具备独立“企微审批运营”权限 | 不允许 |
|
||||
| 立即同步审批详情 | 允许 | 仅具备独立“企微审批运营”权限 | 不允许 |
|
||||
| 提交未知异常恢复 | 允许 | 仅具备独立“企微审批异常恢复”权限 | 不允许 |
|
||||
| 业务退款详情中的审批区块 | 按业务查看权限 | 按业务查看权限 | 按现有店铺层级数据范围 |
|
||||
|
||||
平台账号的“企微审批运营”权限只允许查看运行记录和触发 `getapprovaldetail` 同步,不包含场景、模板、账号绑定管理或提交未知恢复。所有接口以后端角色与权限校验为准,前端隐藏入口不能替代鉴权。
|
||||
|
||||
审批详情按查看主体投影,禁止把平台内部审批资料随业务详情或导出泄露给代理:
|
||||
|
||||
- 代理在其店铺层级数据范围内只能看到真实业务提交人、审批状态、状态更新时间、业务处理结果,以及代理自己提交的退款资料和业务凭证。
|
||||
- 代理不得看到企微审批人名单、内部审批意见和审批人在企微上传的附件。
|
||||
- 平台账号和超级管理员在具备对应退款查看权限时可查看完整审批详情,包括审批人、意见、时间线和审批附件。
|
||||
- 审批附件详情、受保护下载解析与导出必须复用同一主体权限投影;不得因持有 `attachment_ref` 或历史导出文件而绕过当前权限。
|
||||
|
||||
#### 3.3.6 DDD 边界与 API
|
||||
|
||||
```text
|
||||
domain/wecomapproval 场景、模板版本、审批状态和终态幂等
|
||||
application/wecomapproval 发布模板、提交审批、回调、同步和异常恢复
|
||||
domain/wecomidentity 系统账号与企微成员一对一绑定
|
||||
domain/wecomidentity 平台系统账号与企微成员一对一绑定
|
||||
application/wecomidentity 创建绑定会话、完成绑定和解绑
|
||||
infrastructure/adapter/wecom Token、模板、附件、审批、身份和回调加解密
|
||||
query/wecomapproval 审批运行列表、详情和业务摘要
|
||||
@@ -402,7 +423,7 @@ query/wecomapproval 审批运行列表、详情和业务摘要
|
||||
| POST | `/api/admin/wecom/approval-templates/inspect` | 读取企微模板 |
|
||||
| POST | `/api/admin/wecom/approval-templates/publish` | 发布控件映射版本 |
|
||||
| GET | `/api/admin/wecom/approval-templates` | 模板版本列表 |
|
||||
| POST | `/api/admin/wecom/account-binding/sessions` | 当前账号创建扫码绑定会话 |
|
||||
| POST | `/api/admin/wecom/account-binding/sessions` | 当前平台账号创建扫码绑定会话 |
|
||||
| GET | `/api/admin/wecom/account-binding/sessions/{session_id}` | 查询扫码绑定结果 |
|
||||
| GET/DELETE | `/api/admin/wecom/account-binding/me` | 查询或解绑自己 |
|
||||
| GET | `/api/admin/wecom/account-bindings` | 超管查询绑定列表 |
|
||||
@@ -411,8 +432,10 @@ query/wecomapproval 审批运行列表、详情和业务摘要
|
||||
| GET/POST | `/api/callback/wecom/approval` | 企微审批回调校验和事件 |
|
||||
| GET | `/api/admin/wecom/approvals*` | 审批运行列表和详情 |
|
||||
| POST | `/api/admin/wecom/approvals/{id}/sync` | 立即同步详情 |
|
||||
| POST | `/api/admin/wecom/approvals/{id}/bind-sp-no` | 提交结果未知时校验并绑定已有审批单 |
|
||||
| POST | `/api/admin/wecom/approvals/{id}/confirm-not-created-and-resend` | 确认企微未创建后重新发送同一审批申请 |
|
||||
|
||||
### 3.4 数据同步触发与轮询优化
|
||||
### 3.4 卡状态公共写入、事件触发与运营商回调
|
||||
|
||||
#### 3.4.1 三条自动通道
|
||||
|
||||
@@ -420,7 +443,7 @@ query/wecomapproval 审批运行列表、详情和业务摘要
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Polling[活跃/不活跃轮询] --> Request[RequestCardObservation]
|
||||
Polling[现有周期轮询] --> Request[RequestCardObservation]
|
||||
Event[关键业务埋点] --> Series[立即/3分钟/5分钟]
|
||||
Series --> Request
|
||||
Manual[现有手动刷新] --> Request
|
||||
@@ -434,11 +457,11 @@ flowchart LR
|
||||
ACL --> Integration
|
||||
```
|
||||
|
||||
- 轮询始终兜底,只保留 `enable_polling` 总开关,按活跃/不活跃使用不同间隔。
|
||||
- 现有周期轮询继续兜底,其 PostgreSQL 配置、Redis 分片队列、同步类型间隔、卡级开关、失败重排、并发控制和监控保持现状;本期只把查询成功后的状态应用收口到公共用例。
|
||||
- 业务事件不是新接口,而是在查询资产、获取实名链接、停复机、支付、套餐激活、切卡、重启等用例成功边界埋点。
|
||||
- 每个事件序列默认创建立即、3 分钟、5 分钟三个无自动重试任务;达到预期状态后剩余任务提前完成。
|
||||
- 现有手动刷新接口保持响应契约并直接同步,不再额外创建阶梯任务。
|
||||
- Gateway 超频只记录当前 `rate_limited`,不维护 `blocked_until` 或 30/60/120 秒退避,后续阶梯任务和轮询保持原计划。
|
||||
- 事件阶梯任务遇到 Gateway 超频只记录当前 `rate_limited`,不为事件序列维护 `blocked_until` 或 30/60/120 秒退避;后续阶梯任务和现有周期轮询保持各自原计划。
|
||||
|
||||
#### 3.4.2 实名判断与状态应用
|
||||
|
||||
@@ -454,11 +477,9 @@ flowchart LR
|
||||
|
||||
`ApplyCardObservation` 是唯一允许写入实名、流量和网络状态的入口:加载并锁定卡聚合,应用标准观测值,状态变化时同事务保存领域事件和 Audit Event,外部调用始终写 Integration Log。旧轮询 Handler、手动实名修改和刷新 Service 必须改为调用该用例,不保留双实现。
|
||||
|
||||
#### 3.4.3 活跃调频和请求协调
|
||||
#### 3.4.3 事件序列请求协调
|
||||
|
||||
卡维护活跃级别、最后活跃时间/场景和最后上游变化时间。C 端/后台/OpenAPI 查询、实名、停复机、支付、套餐、切卡、回调和轮询发现变化均标记活跃;持续无业务活动且轮询无变化后转为不活跃。
|
||||
|
||||
第一版建议 `inactive_after=30m`;活跃卡沿用现有实名/流量/状态默认间隔,不活跃卡三类查询初始均为 15 分钟。上线前按生产卡量只读测算 QPS 后再调整,数值进入轮询配置而不是写死代码。
|
||||
本期不引入活跃/不活跃卡、不增加活跃状态字段、不调整周期轮询间隔或 QPS,也不合并现有多套轮询配置。以下协调规则只作用于业务事件产生的 `0/3/5` 观测序列:
|
||||
|
||||
重复控制拆为:
|
||||
|
||||
@@ -472,7 +493,7 @@ flowchart LR
|
||||
|
||||
ICCID 必须按原始长度精确路由:19 位只查 `iccid_19`,20 位只查 `iccid_20`,禁止截断、补位或跨列降级。发布前检查 `iccid_19` 重复并建立未删除数据范围内的部分唯一索引。解除实名回调第一版只写 Integration Log 并返回约定成功报文,不修改卡实名状态。
|
||||
|
||||
本需求不新增同步按钮和显式同步 API。资产详情只增加自动轮询状态和“查看同步轨迹”,跳转 `/operations/audit?tab=integrations&resource_type=iot_card&resource_key=...`。
|
||||
本需求不新增同步按钮、显式同步 API、活跃状态或下次轮询字段。资产详情只增加“查看同步轨迹”,跳转 `/operations/audit?tab=integrations&resource_type=iot_card&resource_key=...`;现有手动刷新和轮询监控页面保持原契约。
|
||||
|
||||
### 3.5 全局多视角审计
|
||||
|
||||
@@ -532,8 +553,8 @@ POST /api/admin/audit/exports
|
||||
| 模块/页面 | 建议路由 | 主要能力 |
|
||||
|-----------|----------|----------|
|
||||
| 企微审批运行 | `/operations/wecom-approvals` | 状态、业务单号、模板版本、异常恢复和详情抽屉 |
|
||||
| 企微配置 | `/system/wecom` | 连接状态、模板映射版本、账号绑定和异常审批 |
|
||||
| 账号企微绑定 | 当前用户个人中心 | 扫码绑定、查看成员名称、重新绑定和解绑 |
|
||||
| 企微配置 | `/system/wecom` | 连接状态、代理固定代提交账号状态、模板映射版本、平台账号绑定和异常审批 |
|
||||
| 账号企微绑定 | 当前平台用户个人中心 | 扫码绑定、查看成员名称、重新绑定和解绑;代理不展示绑定入口 |
|
||||
| 站内消息 | `/notifications` | 未读数、列表、已读和受控业务跳转 |
|
||||
| 全局审计 | `/operations/audit` | 全局、人员、资源、链路、资金、风险和外部集成多视角 |
|
||||
| 系统配置 | `/settings/system-config` | 受控单选、复选和开关 |
|
||||
@@ -575,17 +596,19 @@ stateDiagram-v2
|
||||
- 网络错误不等于业务失败,展示“状态获取失败,点击重试”。
|
||||
- 必须展示总数、成功数、失败数和部分成功状态。
|
||||
- 页面刷新后根据任务 ID 恢复进度。
|
||||
- Excel 模板由前端静态资源提供;后端仍严格校验表头、版本和内容。
|
||||
- 批量文件模板由前端静态资源提供;设备批量分配和批量订购均只接受 CSV,但各自使用独立表头契约。后端仍严格校验表头、编码、文件大小和内容。
|
||||
|
||||
### 4.4 企业微信审批交互
|
||||
|
||||
- 删除本系统待我审批、流程节点配置、审批人配置、通过/驳回/退回按钮,审批操作全部在企业微信完成。
|
||||
- 退款和线下充值创建成功后先显示“正在提交企业微信审批”,取得 `sp_no` 后显示“企业微信审批中”。
|
||||
- 业务详情的企微审批区块展示审批单号、状态、模板版本、申请人、审批人、意见、审批附件、状态时间线和本地业务处理结果。
|
||||
- 平台/超级管理员的业务详情企微区块展示审批单号、状态、模板版本、真实业务提交人、审批人、意见、审批附件、状态时间线和本地业务处理结果;代理视图只展示真实业务提交人、审批状态、状态时间和业务处理结果,不返回平台内部审批人、意见或审批附件。
|
||||
- “立即同步”只调用 `getapprovaldetail`,不提供任何本地审批动作。
|
||||
- 通过后撤销且资金动作已执行时使用高风险异常提示,明确说明不会自动冲正。
|
||||
- 未绑定企微账号时,创建页原地展示“绑定企业微信”按钮;扫码成功后继续当前表单,不要求用户先跳转配置页。
|
||||
- 平台/超级管理员未绑定企微时,创建页原地展示“绑定企业微信”按钮,绑定成功后继续当前表单;代理不展示绑定入口,后端使用固定企微账号代提交。
|
||||
- 代理固定代提交账号未配置、失效或不在应用可见范围时,代理创建页展示后端返回的场景不可用原因并保留当前表单。
|
||||
- 模板发布使用业务字段与企微控件的可视化映射,不向运营暴露 JSON;场景暂停时创建页提前展示维护原因。
|
||||
- `/system/wecom` 仅超级管理员可访问;平台账号只在个人中心维护本人绑定,具备“企微审批运营”权限时才显示审批运行页;代理只在自己有权查看的退款详情中查看审批区块。
|
||||
|
||||
### 4.5 审批与业务处理状态
|
||||
|
||||
@@ -601,7 +624,8 @@ stateDiagram-v2
|
||||
|
||||
### 4.6 权限与敏感数据
|
||||
|
||||
- 企微配置、账号绑定、导出字段、审计视角和数据范围均以后端为准。
|
||||
- 企微连接、平台账号绑定与代理固定代提交账号状态、导出字段、审计视角和数据范围均以后端为准。
|
||||
- 审批附件的详情展示、下载解析和导出沿用审批详情主体权限:代理提交的业务凭证可按业务权限访问,平台内部审批附件仅平台/超级管理员按权限访问。
|
||||
- 通知跳转使用前端受控 `ref_type` 路由表,不接受任意 URL。
|
||||
- 退款凭证、充值凭证、身份证、营业执照和审批附件均走对象存储,不保存永久公开地址。
|
||||
- 角色导出字段配置只控制列,不扩大已有店铺或企业数据范围。
|
||||
@@ -621,7 +645,7 @@ stateDiagram-v2
|
||||
| 需求 06/11 套餐到期时间 | 资产层只展示当前生效及排队主套餐全部接续后的预计最终到期时间;当前套餐自身到期时间只保留在套餐明细 | 资产详情 Query 按队列顺序使用购买时长快照推演;无套餐返回 `null`,等待未知实名激活时返回不可预计状态 | 文案使用“预计套餐到期时间”;高亮和临期统一使用最终剩余天数,不维护第二套资产汇总字段 |
|
||||
| 需求 07 实名筛选 | 卡按自身实名状态;设备任一有效绑定卡实名即视为设备实名 | 设备增加 `real_name_status` 快照;实名变化、绑定、解绑、换卡均刷新旧/新设备 | 卡和设备列表增加全部/已实名/未实名筛选 |
|
||||
| 需求 12 换货显示与搜索 | 卡的新旧资产标识统一快照 ICCID;设备维持设备号;历史数据不回填 | 创建快照逻辑修正;列表增加 `old_asset_keyword/new_asset_keyword`,支持 ICCID、接入号、虚拟号 | 搜索框拆为旧资产和新资产;验收大结果集查询性能 |
|
||||
| 需求 13 列表字段 | 提交人写业务快照;企微审批摘要动态读取 | 换货、退款、充值增加 `submitter_name`;按本页企微实例批量查询状态和审批人摘要,禁止 N+1 | 展示企微状态、当前审批人摘要、处理状态和历史审批标识 |
|
||||
| 需求 13 列表字段 | 提交人写业务快照;企微审批摘要动态读取 | 换货、退款、充值增加 `submitter_name`;按本页企微实例批量查询状态,平台视角可查询审批人摘要,代理视角摘要固定为空,禁止 N+1 | 展示企微状态和处理状态;当前审批人仅平台/超级管理员按业务权限展示 |
|
||||
| 需求 15 下架套餐续费 | 禁用套餐始终不可购买;下架套餐只允许资产所有人基于有效历史使用记录续费,禁止代理代购 | 复用统一套餐可售策略;后端根据资产和登录主体判定续费资格 | C 端当前套餐旁展示“续费”,复用购买流程;新购入口隐藏,后台代购禁用 |
|
||||
|
||||
### 5.2 需求 02:H5 实名与充值顺序配置
|
||||
@@ -699,18 +723,18 @@ PATCH /api/admin/shop-package-allocations/{id}/expiry-base
|
||||
|
||||
### 5.4 需求 08:设备批量分配
|
||||
|
||||
“分配代理”和“分配套餐系列”是两个业务命令,不允许一个任务同时修改两个字段。两者复用 Excel 解析、任务轮询和失败明细基础设施,但每个任务只携带一种 `operation_type` 和一个目标值。
|
||||
“分配代理”和“分配套餐系列”是两个业务命令,不允许一个任务同时修改两个字段。两者只接受单列 UTF-8 CSV,复用任务轮询和失败明细基础设施,但使用两个独立创建接口且每个任务只携带一个目标值。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor User as 平台员工
|
||||
actor User as 平台或代理
|
||||
participant Web as 设备管理页
|
||||
participant API as Batch Allocation API
|
||||
participant DB as PostgreSQL
|
||||
participant Worker as Asynq Worker
|
||||
|
||||
User->>Web: 选择一种分配操作并上传 Excel
|
||||
Web->>API: POST batch-assign-shop 或 batch-assign-series
|
||||
User->>Web: 选择一种操作并上传 CSV 到对象存储
|
||||
Web->>API: 提交 file_key 和 shop_id 或 series_id
|
||||
API->>DB: 保存任务和文件 Key
|
||||
API-->>Web: task_id
|
||||
Worker->>DB: 分批查询、条件更新、记录失败
|
||||
@@ -722,8 +746,12 @@ sequenceDiagram
|
||||
处理规则:
|
||||
|
||||
- 设备号去重后批量查询,禁止逐行查询。
|
||||
- CSV 固定一列“设备号”,支持虚拟号或 IMEI 精确匹配;不接受 Excel、multipart 文件字节、号段或模糊搜索。
|
||||
- 前端复用受控预签名上传,业务接口只接收 `file_key` 和对应目标 ID;Asynq 载荷只传结构化 `task_id`。
|
||||
- `assign_shop`:已属于其他代理的设备失败并提示先回收;已属于目标代理的按幂等成功。
|
||||
- `assign_shop`:平台只能分配平台库存设备;代理只能把自己名下设备分配给直属下级。
|
||||
- `assign_series`:已属于目标套餐系列的按幂等成功;不修改 `shop_id`。
|
||||
- `assign_series`:代理只能操作自己名下设备并选择自己当前有效授权的系列。
|
||||
- 临时本地路径和文件字节不得进入 Asynq 载荷。
|
||||
- 模板由前端提供,后端不实现下载接口。
|
||||
- 限制:文件最大 10MB、最多 1000 行、Worker 每批 200 条、失败明细最多保存 1000 条。
|
||||
@@ -739,7 +767,9 @@ sequenceDiagram
|
||||
| 设备 | 微信、钱包 |
|
||||
|
||||
- C 端支付页只展示接口返回的允许方式。
|
||||
- 创建订单和支付接口必须再次校验,不能依赖前端隐藏。
|
||||
- 创建订单时 `payment_method` 必填,后端校验后固化为订单不可变快照;强充在创建流程中立即按该方式拉起渠道,钱包不能用于给自身强充。
|
||||
- 后续支付接口不允许重新选择或替换 `payment_method`,只能执行订单快照方式,并在真正支付前按最新资产配置再次校验。需要换方式时先取消待支付订单再重新创建。
|
||||
- 普通资产钱包充值只展示并接受资产允许集合与 `wechat|alipay` 的交集,不能把 `wallet` 当成充值渠道。
|
||||
- 配置异常时使用上述安全默认值并记录错误,不得放开全部方式。
|
||||
- 后台配置使用复选框,不直接编辑 JSON。
|
||||
|
||||
@@ -757,17 +787,155 @@ flowchart TD
|
||||
Binding --> Exists{当前卡有效?}
|
||||
Exists -->|否| Reject[拒绝操作并记录原因]
|
||||
Exists -->|是| ICCID
|
||||
ICCID --> Gateway[SetSpeedLimit cardNo, speedKbps]
|
||||
ICCID --> Gateway[SetSpeedLimit cardNo, speedLevel]
|
||||
Gateway --> Audit[记录操作审计和 Gateway 结果]
|
||||
```
|
||||
|
||||
#### 5.6.1 CMP 业务契约
|
||||
|
||||
数据和契约:
|
||||
|
||||
- 应用层只接收 `speed_kbps`:正数为设置,`0` 为取消;内部单位固定为 `kbps`。
|
||||
- 应用层只接收语义化 `speed_level`,前端只能从固定档位中选择,禁止输入任意速率,也不得接触 Gateway 渠道 `code`。
|
||||
- 统一接口:`POST /api/admin/assets/{identifier}/speed-limit`。资产为设备时解析当前绑定卡,不存在当前卡则拒绝,绝不把设备 IMEI 传给 Gateway。
|
||||
- Gateway 端口只有 `SetSpeedLimit(cardNo, speedKbps)`;取消仍调用同一端口,适配器按上游最终契约转换取消参数。
|
||||
- Gateway 端口只有 `SetSpeedLimit(cardNo, speedLevel)`;Infrastructure Adapter 根据 Gateway 账户和运营商把业务等级映射为上游字符串 `code`,映射不得进入 Handler、前端或领域模型。
|
||||
- “恢复不限速”和“限到 0kbps”是两个不同业务等级,必须分别映射为上游 `code=-1` 和 `code=0`,禁止继续用数值 `0` 表示取消限速。
|
||||
- 上游说明只有广电和电信直接支持限速接口,联通通过通信计划调整,移动不支持限速。调用前必须按卡的运营商能力校验;不支持或缺少账户档位映射时返回明确业务错误,不得猜测 `code` 或盲目调用。
|
||||
- 不新增 `tb_package.speed_limit_kbps`、`SpeedLimitApplyRequested` Outbox 或自动补偿 Worker。本期也不宣称能展示 Gateway 当前实际限速,除非上游另提供查询接口。
|
||||
- 卡详情和设备详情都提供设置/取消入口;设备入口明确显示“当前使用卡 ICCID”。每次操作记录资产、最终 `cardNo`、目标值、操作人、请求结果和错误摘要。
|
||||
- 卡详情和设备详情都提供固定档位选择及恢复不限速入口;设备入口明确显示“当前使用卡 ICCID”。每次操作记录资产、最终 `cardNo`、业务 `speed_level`、实际发送的渠道 `code`、Gateway 返回的 `appliedSpeed/channelRawValue`、操作人、请求结果和错误摘要。
|
||||
|
||||
CMP 固定业务等级如下。枚举名称属于本系统稳定契约;展示文案和上游默认 `code` 仅用于表达当前已知映射,实际调用仍须按 Gateway 账户和运营商查找映射。
|
||||
|
||||
| `speed_level` | 展示文案 | 当前上游默认 `code` |
|
||||
|---------------|----------|----------------------|
|
||||
| `unlimited` | 恢复不限速 | `-1` |
|
||||
| `zero_kbps` | 限到 0kbps | `0` |
|
||||
| `limit_128_kbps` | 128Kbps | `1` |
|
||||
| `limit_512_kbps` | 512Kbps | `2` |
|
||||
| `limit_1_mbps` | 1Mbps | `3` |
|
||||
| `limit_2_mbps` | 2Mbps | `4` |
|
||||
| `limit_10_mbps` | 10Mbps | `5` |
|
||||
| `limit_20_mbps` | 20Mbps | `6` |
|
||||
| `limit_50_mbps` | 50Mbps | `7` |
|
||||
| `limit_100_mbps` | 100Mbps | `8` |
|
||||
|
||||
#### 5.6.2 Gateway 上游接口文档
|
||||
|
||||
上游正式环境地址为 `https://open.whjhft.com/openapi`,限速接口为 `POST /flow-card/speedLimit`。统一 Gateway 客户端发送时使用 `params` 包装业务参数:
|
||||
|
||||
```json
|
||||
{
|
||||
"params": {
|
||||
"cardNo": "89861124221081232235",
|
||||
"code": "-1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
以下为上游提供的原始 OpenAPI 文档。文档中的成功响应 `example` 实际是错误页面文案,不是有效 JSON;实现和自动化测试不得据此构造成功响应,响应字段以 schema 及真实环境联调结果为准。
|
||||
|
||||
```yaml
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: ''
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/flow-card/speedLimit:
|
||||
post:
|
||||
summary: 流量卡限速接口
|
||||
deprecated: false
|
||||
description: |
|
||||
只有广电接口和电信接口存在限速 联通是通过通信计划调整 不同账户相同速率的编码不一致 移动无限速
|
||||
| 字段名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| cardNo | string | 是 | 流量卡ICCID号码 |
|
||||
| code | string | 是 | 限速档位,取值见下表 |
|
||||
|
||||
**code 档位对照表:**
|
||||
|
||||
| code | 速率 |
|
||||
|------|------|
|
||||
| -1 | 限速恢复(取消限速) |
|
||||
| 0 | 0kbps |
|
||||
| 1 | 128Kbps |
|
||||
| 2 | 512Kbps |
|
||||
| 3 | 1Mbps |
|
||||
| 4 | 2Mbps |
|
||||
| 5 | 10Mbps |
|
||||
| 6 | 20Mbps |
|
||||
| 7 | 50Mbps |
|
||||
| 8 | 100Mbps |
|
||||
tags:
|
||||
- 流量卡
|
||||
- flow-card
|
||||
parameters: []
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties: {}
|
||||
example:
|
||||
params:
|
||||
cardNo: '89861124221081232235'
|
||||
code: '-1'
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: 200成功
|
||||
msg:
|
||||
type: string
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
appliedSpeed:
|
||||
type: string
|
||||
description: 实际限速值
|
||||
channelRawValue:
|
||||
type: string
|
||||
description: 对应运营商过去的值
|
||||
iccid:
|
||||
type: string
|
||||
required:
|
||||
- appliedSpeed
|
||||
- channelRawValue
|
||||
- iccid
|
||||
x-apifox-orders:
|
||||
- appliedSpeed
|
||||
- channelRawValue
|
||||
- iccid
|
||||
required:
|
||||
- code
|
||||
- msg
|
||||
- data
|
||||
x-apifox-orders:
|
||||
- code
|
||||
- msg
|
||||
- data
|
||||
example: 抱歉,您访问的页面不存在。
|
||||
headers: {}
|
||||
x-apifox-name: 成功
|
||||
x-apifox-ordering: 0
|
||||
security: []
|
||||
x-apifox-folder: 流量卡
|
||||
x-apifox-status: developing
|
||||
x-run-in-apifox: https://app.apifox.com/web/project/6930706/apis/api-487496525-run
|
||||
components:
|
||||
schemas: {}
|
||||
responses: {}
|
||||
securitySchemes: {}
|
||||
servers:
|
||||
- url: https://open.whjhft.com/openapi
|
||||
description: 正式环境
|
||||
security: []
|
||||
```
|
||||
|
||||
### 5.7 需求 14:统一导出与字段权限
|
||||
|
||||
@@ -787,18 +955,17 @@ flowchart TD
|
||||
|
||||
```text
|
||||
POST /api/admin/export-tasks
|
||||
body: scene + format + query + fields
|
||||
body: scene + format + query
|
||||
```
|
||||
|
||||
字段权限:
|
||||
|
||||
```text
|
||||
resolved_fields = 用户申请字段
|
||||
∩ 角色授权字段并集
|
||||
resolved_fields = 角色授权字段并集
|
||||
∩ 场景支持字段
|
||||
```
|
||||
|
||||
新增 `tb_role_export_field_permission(role_id, scene, field_key)`,三列唯一。超级管理员拥有全部字段;普通角色从授权并集计算。数据行范围继续使用现有权限,字段授权不能扩大数据范围。
|
||||
新增 `tb_role_export_field_permission(role_id, scene, field_key)`,三列唯一。超级管理员拥有代码目录内全部字段;普通账号从当前有效角色的授权并集计算。数据行范围继续使用现有权限,字段授权不能扩大菜单、接口、场景或数据行范围。前端不得提交 `fields`,也不提供导出字段选择器;账号获授权的代码目录字段全部导出。
|
||||
|
||||
API:
|
||||
|
||||
@@ -810,11 +977,32 @@ PUT /api/admin/roles/{role_id}/export-fields
|
||||
|
||||
- 创建任务时快照最终字段和表头,Worker 不能因后续角色变化扩大字段。
|
||||
- 权限解析失败时拒绝导出,不能回退到全字段。
|
||||
- 普通账号解析成功但最终字段为空时不创建任务;查询当前账号字段时返回空数组,前端据此禁用导出入口。
|
||||
- 不存在 `default_selected`、`required` 或后端自动补列。角色配置是代码目录内字段能否导出的权威来源;密码、密钥、Token、对象存储 Key、企微 `media_id` 等永久禁止导出的字段不得注册进代码目录。
|
||||
- Count 和 Fetch 必须使用相同权限及查询条件。
|
||||
- 退款和充值审批摘要按本批实例批量查询,禁止 N+1。
|
||||
- 导出审批附件只输出数量,不输出对象 Key 或永久 URL。
|
||||
- 退款/充值业务凭证和企微审批附件可按字段权限导出受保护的稳定业务链接,但字段权限不能突破审批主体可见性:代理可导出其有权查看的业务凭证,不能导出或解析平台内部企微审批附件;不得输出对象 Key、企微 `media_id`、当前预签名 URL 或公开 Bucket URL。平台审批摘要仍可保留附件数量。
|
||||
- `scene=iot_card` 支持按预计最终到期时间筛选 30 天内资产;该导出条件独立于页面 15 天临期定义,复用需求 06/11/22 的最终到期 Query。
|
||||
|
||||
受保护附件访问流程:
|
||||
|
||||
```text
|
||||
导出单元格中的后台前端绝对 URL
|
||||
→ /export-attachments/{attachment_ref}
|
||||
→ 未登录时进入后台登录并保存当前站内返回地址
|
||||
→ 登录成功返回附件落地页
|
||||
→ 前端携带 Bearer Token 请求 GET /api/admin/attachments/{attachment_ref}/download-url
|
||||
→ 后端按附件所关联退款单、充值单或审批业务重新校验当前查看权限、数据范围和附件种类可见性
|
||||
→ 返回短期 download_url、expires_at、file_name
|
||||
→ 前端在当前页跳转短期地址,浏览器打开或下载私有文件
|
||||
```
|
||||
|
||||
- `attachment_ref` 是不可变、不可枚举的稳定引用;业务附件被替换时旧引用不得改指新文件。
|
||||
- 附件仍保存在私有 Bucket。稳定的是后台前端落地页地址,不是对象存储地址;每次访问都重新鉴权并生成短期地址。
|
||||
- 无权与引用不存在对外使用统一错误,避免探测;角色或数据范围在导出后被收回时,旧导出文件中的链接也不能继续下载。
|
||||
- 企微审批附件必须先保存到本地私有对象存储并建立稳定引用,不能依赖临时 `media_id`。历史确无本地附件事实时输出空;匹配记录仍处于应有附件但尚未本地化的异常状态时,导出任务明确失败。
|
||||
- 前端附件落地页必须覆盖登录恢复、加载中、无权限/不存在、对象文件不可用、解析失败和成功跳转状态;不得把后端 API URL直接写进导出文件,因为浏览器无法为普通文件链接自动附加后台 Bearer Token。
|
||||
|
||||
### 5.8 需求 22:套餐临期提醒
|
||||
|
||||
临期定义:按 `Asia/Shanghai` 自然日计算,资产当前生效主套餐与全部排队主套餐连续接续后的**预计最终剩余天数**为 `0~15` 天。已过期资产不按 0 天计入临期;没有生效套餐且队首仍等待无法确定时间的实名激活时,不伪造到期日期,也不进入临期。需求 06、11、22 共用同一个最终到期 Query。
|
||||
@@ -906,19 +1094,13 @@ cash_available = balance - frozen_balance
|
||||
|
||||
#### 5.9.5 #43 代理系列套餐批量授权
|
||||
|
||||
现有 `PUT /api/admin/shop-series-grants/{id}/packages` 已接受套餐数组,继续作为批量写接口。新增套餐候选 Query:
|
||||
不新增套餐候选 API。首次授权使用现有 `GET /api/admin/packages?series_id=...` 选择套餐,并由 `POST /api/admin/shop-series-grants` 在同一事务创建系列授权和至少一条套餐授权;不允许创建没有套餐的空系列授权。
|
||||
|
||||
```text
|
||||
GET /api/admin/shop-series-grants/{id}/package-options
|
||||
```
|
||||
后续管理并行读取现有套餐列表和 `GET /api/admin/shop-series-grants/{id}`,由前端按 `package_id` 合并:已授权项置灰,未授权项可多选,存量已授权但当前不再可售/可见的项目仍通过授权详情只读展示。
|
||||
|
||||
返回 `package_id`、名称、编码、公司成本价、当前代理授权成本价、建议售价和 `is_authorized`。首次授权系列和后续管理套餐都使用同一候选列表:
|
||||
保留 `PUT /api/admin/shop-series-grants/{id}/packages`,但请求必须用 `operation_type=authorize|update_cost|remove` 明确表达一种批量命令,单次最多 100 个套餐、事务内全成全败。新增授权同价重复幂等,不同价重复冲突;调价和移除不能伪装成新增授权。前后端同批切换,不保留旧的混合新增/改价/移除语义。
|
||||
|
||||
- 已授权套餐显示“已授权”并置灰,不可重复选择。
|
||||
- 未授权套餐支持复选框多选并一次提交。
|
||||
- 后端对重复套餐按幂等处理,不能依赖前端置灰保证一致性。
|
||||
- `company_cost_price`、`authorized_cost_price` 和 `suggested_retail_price` 分字段返回,禁止继续使用含义不明确的单一 `cost_price` 展示。
|
||||
- 套餐候选属于 Query,批量授权属于轻量 Application 事务脚本,不为此创建空洞聚合。
|
||||
页面按调用视角分别标注上级当前成本价、目标代理授权成本价和建议零售价;平台视角的上级成本才是公司成本。所有系列、套餐、价格和直属下级权限由后端重新校验,不能依赖前端置灰。
|
||||
|
||||
---
|
||||
|
||||
@@ -942,6 +1124,9 @@ GET /api/admin/shop-series-grants/{id}/package-options
|
||||
- 修改角色默认信用配置只影响以后新建的店铺,不更新任何已有店铺。
|
||||
- 已有店铺通过独立资金接口直接修改实际额度,之后也不跟随角色变化。
|
||||
- 店铺后续增加其他角色不改变钱包信用额度,避免多角色组合影响资金事实。
|
||||
- 代理账号不能调整自己或任何下级代理的实际信用额度;现有店铺管理权限和数据范围不推导信用额度修改权。
|
||||
- 实际额度只能由超级管理员,或具备独立信用额度管理权限的平台账号修改。角色默认模板也只允许超级管理员或具备相应角色管理权限的平台账号配置。
|
||||
- 信用额度不设置产品层固定上限;接口仍须使用分为单位的 `int64` 安全范围并拒绝负数和算术溢出。
|
||||
|
||||
#### 不变量
|
||||
|
||||
@@ -998,7 +1183,7 @@ CHECK (
|
||||
|------|------|
|
||||
| 修改角色默认额度 | 只更新角色模板和审计,不扫描、不修改任何已有店铺钱包 |
|
||||
| 创建店铺 | 在创建事务中读取默认角色模板并初始化代理主钱包实际额度 |
|
||||
| 修改额度 | 校验权限、加载主钱包、校验新可用金额、按 `version` 条件更新、写信用变更审计 |
|
||||
| 修改额度 | 拒绝代理账号;校验平台独立权限、加载主钱包、校验新可用金额、按 `version` 条件更新、写信用变更审计 |
|
||||
| 钱包扣款 | 使用有效额度计算可用金额,同事务更新余额、版本和资金流水 |
|
||||
| 查询/导出 | Query 返回 `credit_enabled`、`credit_limit`、`available_balance`、`is_in_debt`、`debt_amount` |
|
||||
|
||||
@@ -1011,6 +1196,8 @@ GET /api/admin/shops/fund-summary 返回信用和可用金额
|
||||
|
||||
角色页面显示“新建代理默认信用额度”,并明确提示“修改后不会影响已有店铺”。店铺资金页面独立显示和修改实际信用额度。前端只展示接口返回的可用金额,不自行重新计算;额度调整弹框显示修改前后金额预览,并发冲突时刷新最新钱包版本。
|
||||
|
||||
资金概况中的 `is_in_debt` 表示 `balance < 0`,`debt_amount = max(-balance, 0)`;冻结金额只影响现金可用金额和总可用金额,不直接记为欠款。额度调整只改变资金边界,不伪造一条金额为零的钱包交易流水;变更前后值进入全局 Audit Event。
|
||||
|
||||
### 6.3 需求 18:多人审批业务映射
|
||||
|
||||
多人审批由企业微信模板负责,本系统不解析审批角色、账号、部门或会签规则:
|
||||
@@ -1020,25 +1207,28 @@ GET /api/admin/shops/fund-summary 返回信用和可用金额
|
||||
| 多级、会签、或签 | 在企微模板中配置,本系统使用 `use_template_approver=1` |
|
||||
| “部门领导→财务” | 可以作为企微模板中的组织规则,本系统不建立部门模型也不推导审批人 |
|
||||
| 当前节点待办 | 由企业微信自身提醒,本系统不重复生成站内待审批任务 |
|
||||
| 通过/驳回/撤销通知 | 状态同步后向申请人生成站内结果通知 |
|
||||
| 通过/驳回/撤销通知 | 状态同步后向真实业务提交人生成站内结果通知 |
|
||||
| 意见和附件 | 从 `getapprovaldetail` 保存审批详情快照并在业务详情只读展示 |
|
||||
| 历史版本 | 本地保存模板 ID、控件映射和提交快照,历史实例不受新模板影响 |
|
||||
|
||||
平台员工必须先完成系统账号与企微成员扫码绑定,发起审批使用绑定的 `userid`;普通运营不查询或录入成员 ID。
|
||||
平台/超级管理员必须扫码绑定并使用本人企微 `userid` 发起;代理退款使用部署配置中的固定企微成员代提交。两类路径都把真实业务提交人写入模板 `submitter` 字段和本地快照,通知与审计均以真实业务提交人为准。
|
||||
|
||||
### 6.4 需求 19:批量订购套餐
|
||||
|
||||
#### 规则和流程
|
||||
|
||||
- 支付方式整批选择 `offline` 或 `agent_wallet`,Excel 不包含支付方式。
|
||||
- 支付方式整批选择 `offline` 或 `agent_wallet`,CSV 不包含支付方式。
|
||||
- 混合支付必须拆成不同批次。
|
||||
- 模板字段:资产类型、资产标识、套餐编码、套餐名称;实际匹配使用套餐编码。
|
||||
- 批次不选择代理、不接收 `shop_id`;同一 CSV 可以包含不同代理的资产。Worker 逐行以资产当前归属解析结算代理,套餐授权、成本价、钱包和数据权限均以该行解析结果为准。
|
||||
- 创建、查询批次和查看明细只允许超级管理员,或具备独立“批量订购套餐”权限的平台账号;代理和企业账号无页面及 API 权限。平台身份只授予发起批次的能力,不跳过任何逐行资产、结算代理、套餐授权、成本价或钱包校验。
|
||||
- CSV 固定 UTF-8(允许 BOM),模板字段:资产类型、资产标识、套餐编码、套餐名称;实际匹配使用套餐编码,套餐名称只供人工核对。不接受 Excel。
|
||||
- 同一 CSV 内按“资产类型 + 标准化资产标识 + 套餐编码”识别重复业务行:首次出现的行正常处理,后续重复行记为失败并返回首次出现的行号;同一资产订购不同套餐不视为重复。本期不通过复制相同行表达购买多份,未来需要多份时增加明确数量字段。
|
||||
- 任务允许部分成功,每行是独立、可重试、可审计的业务单元。
|
||||
- 文件最大 10MB、最多 1000 行;失败明细最多保存 1000 条。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Submit[选择代理、支付方式、凭证并上传] --> Task[创建任务]
|
||||
Submit[选择支付方式,CSV及凭证直传私有对象存储] --> Task[提交file_key和voucher_keys创建任务]
|
||||
Task --> Parse[解析并持久化逐行明细]
|
||||
Parse --> Item{处理下一行}
|
||||
Item -->|钱包| Wallet[锁钱包并校验有效可用金额]
|
||||
@@ -1055,8 +1245,8 @@ flowchart TD
|
||||
|
||||
| 表 | 关键字段 |
|
||||
|----|----------|
|
||||
| `tb_bulk_purchase_task` | 任务号、`request_id`、文件 Key、代理、支付方式、凭证快照、金额和数量汇总、状态、处理租约 |
|
||||
| `tb_bulk_purchase_item` | 行号、资产、套餐快照、金额、状态、订单 ID、错误码、错误原因、幂等键 |
|
||||
| `tb_bulk_purchase_task` | 任务号、`request_id`、文件 Key、支付方式、凭证快照、涉及代理数、金额和数量汇总、状态、处理租约 |
|
||||
| `tb_bulk_purchase_item` | 行号、资产、结算代理快照、套餐快照、金额、状态、订单 ID、错误码、错误原因、幂等键 |
|
||||
|
||||
任务状态:`1=待处理, 2=处理中, 3=完成, 4=部分成功, 5=失败`。
|
||||
明细状态:`1=待处理, 2=处理中, 3=成功, 4=失败`。
|
||||
@@ -1068,17 +1258,22 @@ flowchart TD
|
||||
- 行幂等键:`bulk_purchase:{task_id}:{row_no}`。
|
||||
- 钱包可用金额统一使用 `credit_enabled` 后的有效信用额度,禁止直接无条件加 `credit_limit`。
|
||||
- 钱包余额、版本、订单、资金流水和明细成功状态在同一事务。
|
||||
- 钱包支付逐行扣该资产当前所属代理的主钱包;资产无代理归属、归属异常或该代理没有有效主钱包时只将该行记为失败。同一批次可依次锁定不同代理钱包,不存在整批共享钱包。
|
||||
- 单行失败不回滚其他成功行,任务统计从明细表重新聚合。
|
||||
- 批量订购必须复用需求 15 的套餐可售策略,不能绕过下架续费限制。
|
||||
- 任务详情和明细只能由上述有权平台主体读取;不得通过猜测 `task_id` 向代理或企业账号暴露跨代理资产、钱包或失败原因。
|
||||
|
||||
API:
|
||||
|
||||
```text
|
||||
POST /api/admin/storage/upload-url
|
||||
POST /api/admin/bulk-purchases
|
||||
GET /api/admin/bulk-purchases/{task_id}
|
||||
GET /api/admin/bulk-purchases/{task_id}/items
|
||||
```
|
||||
|
||||
CSV 先使用 `purpose=bulk_purchase` 获取预签名地址并直传私有对象存储;线下凭证使用附件用途直传。`POST /api/admin/bulk-purchases` 只接收 JSON:`request_id`、`payment_method`、`file_key`、`voucher_keys`,不接收 `shop_id`、multipart 或文件字节。创建任务前校验对象存在、归属当前上传主体、扩展名/Content-Type 和大小;Worker 按稳定 `file_key` 下载解析。
|
||||
|
||||
线下凭证仅作为本批次业务资料和审计快照,本期不校验跨批次唯一性或建立财务核销规则。
|
||||
|
||||
### 6.5 需求 20:退款审批
|
||||
@@ -1111,17 +1306,11 @@ sequenceDiagram
|
||||
- 微信、支付宝、线下等非代理钱包支付由财务在系统外人工退款后再通过企微;企微通过即表示人工退款已确认,本系统不调用渠道退款 API,也不再提供本地 `manual-complete` 二次确认。
|
||||
- 代理钱包支付订单在企微通过后按原扣款流水定位原代理主钱包,幂等回溯并写退款流水;可自然冲减负余额。
|
||||
- 个人客户或资产钱包不自动回款,现有 `BuyerTypePersonal` 自动资产钱包退款分支在迁移时删除或隔离。
|
||||
- 驳回时本地状态改为已拒绝;撤销/删除时改为已撤销,可修改业务资料后重新申请。
|
||||
- 驳回时本地状态改为已拒绝,审批和该退款单同时终结;原退款单不可编辑、不可再次提交。业务人员纠正驳回原因后仍需退款时,重新走 `POST /api/admin/refunds` 创建新退款单。撤销/删除时进入异常状态和人工处置,同样不开放原单重新提交。
|
||||
- 通过后撤销且资金已执行时不自动冲正,记录 `critical` 审计、站内告警并人工处理;资金尚未执行时终止后续任务。
|
||||
- 原退款业务单级 `approve/reject/return` 路由下线,不存在本地审批动作 API。
|
||||
|
||||
重新申请:
|
||||
|
||||
```text
|
||||
POST /api/admin/refunds/{id}/resubmit
|
||||
```
|
||||
|
||||
只允许已驳回、已撤销或已删除且尚未完成退款的申请按原退款规则修改申请金额、凭证和原因,并创建 `round_no + 1` 的企微实例;订单、资产快照、提交人和历史审批不可修改。
|
||||
一张退款单只对应一条企微审批申请。企微同意或拒绝后,该审批申请和退款单均形成不可变终态;本期下线既有 `POST /api/admin/refunds/{id}/resubmit`,不提供任何原退款单编辑或重提接口。拒绝后再次退款属于新的业务事实:前端重新进入退款创建流程,用户根据拒绝原因重新填写金额、凭证和原因,后端生成新的退款 ID、退款单号、业务快照、提交人快照和企微审批申请。新旧退款单只因指向同一订单或资产而具有关联,不继承审批节点、意见、附件、状态或企微发起身份;已拒绝退款不计入该订单或资产的活跃退款,但仍须阻止与其他活跃退款并存。企微意外返回撤销、删除或通过后撤销时只进入异常处置,不作为创建新退款的自动放行依据。
|
||||
|
||||
前端只读展示企微审批状态、意见/附件和业务处理结果,不显示本地审批或人工退款确认按钮。
|
||||
|
||||
@@ -1205,14 +1394,14 @@ POST /api/admin/agent-recharges/{id}/reject
|
||||
- 检查同一设备多条 `is_current=true` 绑定并先修复。
|
||||
- 检查未删除卡 `iccid_19` 重复,解决冲突后才能建立部分唯一索引。
|
||||
- 检查 `realname_link_type!=none` 但资产 `realname_policy=none` 的冲突数据并明确修正结果。
|
||||
- 使用生产卡量测算活跃/不活跃轮询间隔对应的 Gateway QPS 和最长兜底延迟。
|
||||
- 记录现有轮询配置、队列深度、卡级开关和监控基线,发布后验证调度行为未被公共写入改造改变。
|
||||
- 核对存量退款的支付方式和买家类型;仅将代理钱包订单接入自动回退,个人资产钱包订单不得误入该处理器。
|
||||
- 统计待审批退款、平台员工线下充值和历史终态记录数量。
|
||||
- 轮换用户 demo 中泄露的企微 Secret、Token 和 EncodingAESKey,配置可信域名、应用可见范围和回调地址。
|
||||
- 发布并验证退款、线下充值企微模板控件映射;要求会发起审批的平台员工完成扫码绑定。
|
||||
- 发布并验证退款、线下充值企微模板控件映射,验证代理固定代提交成员可用,并要求会发起审批的平台/超级管理员完成扫码绑定。
|
||||
- 验证微信 Native、支付宝 PreCreate 配置和回调地址,确认代理充值支付渠道可用。
|
||||
- 盘点旧账号、资产、轮询日志的写入口和查询入口,确认统一审计切换清单。
|
||||
- 初始化角色导出字段的最小权限集,禁止默认放开敏感字段。
|
||||
- 停机窗口内由业务使用超级管理员配置普通角色导出字段并抽样验证;不运行默认授权迁移,永久禁止导出的字段不进入代码目录。
|
||||
|
||||
### 7.2 迁移清单
|
||||
|
||||
@@ -1221,7 +1410,7 @@ POST /api/admin/agent-recharges/{id}/reject
|
||||
| 新建 | `tb_system_config` | 受控动态配置 |
|
||||
| 新建 | `tb_notification` | 分类、级别、受控跳转和接收人幂等 |
|
||||
| 新建 | `tb_wecom_approval_scene`、`tb_wecom_approval_template_version` | 稳定场景和不可变模板映射版本 |
|
||||
| 新建 | `tb_wecom_approval_instance`、`tb_account_wecom_mapping` | 企微审批镜像和账号扫码绑定 |
|
||||
| 新建 | `tb_wecom_approval_instance`、`tb_account_wecom_mapping` | 企微审批镜像、平台账号扫码绑定、真实业务提交人和企微发起身份快照 |
|
||||
| 新建 | `tb_audit_event`、`tb_audit_event_resource` | 全局不可变业务审计和多资源关联 |
|
||||
| 新建 | `tb_integration_log` | Gateway、运营商、企微和支付渠道交互 |
|
||||
| 新建/确认 | `tb_outbox_event` | 可靠事件投递 |
|
||||
@@ -1230,8 +1419,7 @@ POST /api/admin/agent-recharges/{id}/reject
|
||||
| 新建 | `tb_expiry_push_record` | 15/7/3 天临期通知防重 |
|
||||
| 新建 | `tb_bulk_purchase_task`、`tb_bulk_purchase_item` | 批量订购任务和逐行明细 |
|
||||
| 修改 | `tb_device` | 实名状态快照 |
|
||||
| 修改 | `tb_iot_card`/轮询调度状态 | 活跃级别、最后活跃/上游变化信息;高频调度心跳不写核心表 |
|
||||
| 修改 | `tb_polling_config` | 收口为全局活跃/不活跃间隔,不再按卡类别形成轮询资格 |
|
||||
| 修改 | 现有实名/流量/网络轮询 Handler | 保持调度不变,只将查询结果交给公共卡状态写入用例 |
|
||||
| 修改 | `tb_iot_card.iccid_19` | 未删除数据范围 Partial Unique Index |
|
||||
| 修改 | `tb_shop_package_allocation`、`tb_package_usage` | 生效条件、周期和时长快照 |
|
||||
| 修改 | `tb_exchange_order` | 提交人快照、资产标识快照和新旧资产查询索引 |
|
||||
@@ -1239,7 +1427,7 @@ POST /api/admin/agent-recharges/{id}/reject
|
||||
| 修改 | `tb_shop` | 可空平台业务员字段 `business_owner_account_id` |
|
||||
| 修改 | `tb_role` | 新建店铺默认信用开关和额度模板 |
|
||||
| 修改 | `tb_agent_wallet` | 实际信用开关、额度和 CHECK 约束 |
|
||||
| 修改 | `tb_refund_request` | 提交人、企微实例轮次、撤销状态和终态处理结果 |
|
||||
| 修改 | `tb_refund_request` | 提交人、唯一企微审批申请引用、撤销状态和终态处理结果 |
|
||||
| 修改 | `tb_agent_recharge_record` | 提交人、企微实例、支付状态和入账处理结果 |
|
||||
| 修改 | `tb_payment` | 支持 `order_type=agent_recharge` 和创建时支付配置快照 |
|
||||
|
||||
@@ -1251,7 +1439,7 @@ POST /api/admin/agent-recharges/{id}/reject
|
||||
flowchart LR
|
||||
M[进入维护模式并停止写入] --> DB[执行增量迁移]
|
||||
DB --> Deploy[同时发布 API、Relay/Worker、前端]
|
||||
Deploy --> WeCom[发布企微模板映射和扫码绑定]
|
||||
Deploy --> WeCom[发布企微模板映射、验证代理固定账号并完成平台账号绑定]
|
||||
WeCom --> Backfill[提交存量待审批单到企微]
|
||||
Backfill --> Verify[人工验证核心链路]
|
||||
Verify --> Open[解除维护模式]
|
||||
@@ -1262,8 +1450,8 @@ flowchart LR
|
||||
1. 停止订单、退款、充值、资产状态和配置相关写入,暂停旧 Worker。
|
||||
2. 创建企微、审计、通知、批量任务、权限和同步调度所需表/索引,并增加业务关联字段。
|
||||
3. 同时发布 API、Relay/Worker 和前端,统一切换 Audit Writer、Integration Log 和 Access Log 脱敏。
|
||||
4. 发布两个企微模板映射版本,验证连接、回调、状态查询和员工扫码绑定。
|
||||
5. 使用一次性 Application 命令为存量待审批退款和平台员工线下充值创建企微实例;未绑定创建人的记录进入迁移待处理列表。
|
||||
4. 发布两个企微模板映射版本,验证连接、代理固定代提交账号、平台账号扫码绑定、回调和状态查询。
|
||||
5. 使用一次性 Application 命令为存量待审批记录创建企微实例:代理创建的退款使用固定代提交账号;平台/超级管理员创建的记录仅在创建人已绑定企微时提交,未绑定或真实创建人缺失的记录进入迁移待处理列表。
|
||||
6. 历史终态记录保留 `approval_source=legacy`,不得伪造企微实例或审批时间线。
|
||||
7. 验证数据同步三通道、19/20 位 ICCID 回调、代理微信/支付宝扫码充值和统一审计查询。
|
||||
8. 确认旧退款审批、充值 `offline-pay/reject`、旧审计写入口和重复卡状态写逻辑不可访问。
|
||||
@@ -1287,7 +1475,7 @@ flowchart LR
|
||||
|
||||
| 编号 | 已确认结论 |
|
||||
|------|------------|
|
||||
| C-01 | 限速内部单位固定 `kbps`;本期仅人工设置/取消,Gateway 取消参数仅由适配器处理。 |
|
||||
| C-01 | 限速使用固定语义化 `speed_level`;前端不得输入任意速率或渠道 `code`;恢复不限速与限到 0kbps 严格区分,上游编码由适配器按 Gateway 账户和运营商映射。 |
|
||||
| C-02 | 实名策略批量单次最多 500 条,事务内全成全败。 |
|
||||
| C-03 | 设备批量分配文件最大 10MB、最多 1000 行、每批 200 条、失败明细最多 1000 条,且一任务只做一种分配操作。 |
|
||||
| C-04 | 批量订购线下凭证仅保存业务资料快照,不校验跨批次唯一性或财务核销。 |
|
||||
@@ -1301,7 +1489,7 @@ flowchart LR
|
||||
| C-12 | H5 不增加全局实名策略默认值,新建卡/设备继续默认 `after_order`。 |
|
||||
| C-13 | 行业卡实名由 `realname_link_type` 决定;19/20 位 ICCID 精确查对应列,不截断、不补位、不跨列降级。 |
|
||||
| C-14 | 事件同步固定立即、3 分钟、5 分钟三次;Gateway 超频不退避,不删除后续任务。 |
|
||||
| C-15 | 企微账号只允许扫码绑定;一个 `userid` 不能覆盖绑定到第二个系统账号。 |
|
||||
| C-15 | 平台/超级管理员企微账号只允许扫码绑定且一个 `userid` 不得绑定多个系统账号;代理审批使用部署配置中的固定企微账号代提交,真实业务提交人始终独立保存和展示。 |
|
||||
| C-16 | 代理在线充值最低 100 元,支付成功直接入主钱包,不因金额大进入审批。 |
|
||||
| C-17 | 全局审计本次停止旧表新写入;历史只读投影,不双写、不在线回填。 |
|
||||
| C-18 | 角色默认信用配置只作用于以后新建的店铺;修改角色不更新已有店铺。 |
|
||||
@@ -1309,7 +1497,7 @@ flowchart LR
|
||||
| C-20 | 临期只发站内通知;3 天内使用红色,且只在临期独立列表置顶。 |
|
||||
| C-21 | 换货新资产继承旧资产店铺;旧资产保留原归属,已属于其他店铺的新资产不得换入。 |
|
||||
|
||||
Gateway 的取消限速具体报文不是产品决策:上线前由上游接口契约确定,业务层始终只传 `speed_kbps=0`。
|
||||
Gateway 上游已确认使用 `POST /flow-card/speedLimit`,请求核心参数为 `cardNo + code` 并由统一客户端包装在 `params` 中。业务层始终只传语义化 `speed_level`;`code=-1` 表示恢复不限速,`code=0` 表示限到 0kbps,二者禁止混用。不同 Gateway 账户相同速率编码可能不同,实施前必须完成账户/运营商映射和真实环境联调。
|
||||
|
||||
### 8.1 主要运行风险
|
||||
|
||||
@@ -1318,11 +1506,12 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
| 企微模板失效 | 模板或控件 ID 编辑后变化 | 场景暂停、模板版本、定期验证和原子切换 |
|
||||
| 企微提交重复 | `applyevent` 超时后盲目重试 | 提交结果未知状态和人工绑定 `sp_no` |
|
||||
| 审批回调漏失 | 网络或企微回调异常 | 审批中实例每 2 分钟查询详情兜底 |
|
||||
| 账号绑定冲突 | 同一企微成员绑定多个账号 | `userid` 唯一约束、扫码会话和强制解绑审计 |
|
||||
| 平台账号绑定冲突 | 同一企微成员绑定多个平台账号 | `userid` 唯一约束、扫码会话和强制解绑审计 |
|
||||
| 代理固定代提交账号失效 | 成员离职、停用或移出应用可见范围 | 周期验证、提交前就绪校验、暂停代理新申请和系统告警 |
|
||||
| 重复代理钱包回退或入账 | Outbox/Asynq 至少一次投递 | 稳定业务幂等键、资金流水唯一业务号、处理租约 |
|
||||
| 通过后撤销 | 企微通过且资金已执行后撤销 | 不自动冲正,critical 审计、通知和人工处理 |
|
||||
| 支付重复回调 | 微信/支付宝多次通知 | 支付单状态条件、钱包流水唯一键和业务幂等键 |
|
||||
| 同步请求放大 | 查询、轮询和业务事件同时请求同一卡 | 同场景合并、单卡互斥、运营商最小间隔和活跃调频 |
|
||||
| 同步请求放大 | 查询、轮询和业务事件同时请求同一卡 | 事件序列按同场景合并、单次请求互斥、运营商最小间隔;现有周期轮询调度保持不变 |
|
||||
| ICCID 错配 | 20 位截断或 19 位补位命中错误卡 | 双列精确路由和 `iccid_19` 部分唯一索引 |
|
||||
| 审计数据量过大 | 高频轮询和全局写操作持续增长 | 时间索引、分批清理、Integration Log 短保留和后续月分区 |
|
||||
| 批量重复下单 | 重复提交或并发 Worker | 创建请求幂等、任务/明细条件领取、行级唯一键 |
|
||||
@@ -1345,8 +1534,8 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
|
||||
- Outbox 待投递数、最早积压时间和失败次数。
|
||||
- 企微 Token 刷新、模板失效、提交结果未知、回调失败、待审批轮询积压和业务处理失败。
|
||||
- 账号扫码绑定成功/失败/冲突和未绑定申请人数量。
|
||||
- 活跃/不活跃卡数量、各同步类型 QPS、Gateway 超频、连续失败和事件序列完成率。
|
||||
- 平台账号扫码绑定成功/失败/冲突、未绑定平台申请人数、代理固定代提交账号验证结果和提交失败数量。
|
||||
- 现有轮询队列/配置基线、各同步类型 QPS、Gateway 超频、连续失败和事件序列完成率。
|
||||
- Audit Event/Integration Log 写入失败、增长速度、清理积压和敏感读取次数。
|
||||
- 微信/支付宝预下单、回调失败、已支付未入账和重复回调数量。
|
||||
- 批量任务成功/失败/部分成功数量。
|
||||
@@ -1358,8 +1547,8 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
|
||||
| 范围 | 必测场景 |
|
||||
|------|----------|
|
||||
| 企微审批 | 模板发布/失效、扫码绑定、提交、回调、2分钟轮询、驳回/撤销/删除、提交未知恢复、意见附件和业务快照 |
|
||||
| 数据同步 | 活跃调频、0/3/5 阶梯、同场景合并、单卡互斥、超频不退避、19/20位回调、解除实名忽略、旧入口收口 |
|
||||
| 企微审批 | 模板发布/失效、平台账号扫码绑定、代理固定账号有效/失效、两类发起身份与真实业务提交人展示、提交、回调、2分钟轮询、驳回/撤销/删除、提交未知恢复、意见附件和业务快照 |
|
||||
| 数据同步 | 现有轮询调度回归、0/3/5 阶梯、同场景合并、单次请求互斥、事件超频不退避、19/20位回调、解除实名忽略、旧写入口收口 |
|
||||
| 全局审计 | 关键事务失败回滚、人员/资源/请求/资金/风险/集成视角、历史投影、脱敏、旧表停止新写入 |
|
||||
| 钱包 | 普通余额扣款、信用扣款、额度降低失败、并发版本冲突、负余额回充 |
|
||||
| 角色默认额度 | 新建店铺继承默认值、修改角色不影响已有店铺、店铺独立调额 |
|
||||
@@ -1367,14 +1556,14 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
| 批量订购 | 钱包/线下两种支付、部分成功、重复提交、Worker 重试、失败明细、模板错误 |
|
||||
| 退款 | 金额发起时固定、财务人工退款企微确认、代理钱包回退原主钱包、个人资产钱包不误入、通过后撤销不冲正 |
|
||||
| 充值 | 微信/支付宝最低100元扫码、重复回调不重复入账、已支付恢复、在线不审批、线下企微通过自动入账且无操作密码 |
|
||||
| 导出 | 普通角色、敏感字段角色、超级管理员、权限为空、审批摘要批量查询 |
|
||||
| 限速 | 单卡、设备当前卡、无当前卡、设置、取消、Gateway 失败和审计记录 |
|
||||
| 导出 | 普通角色字段并集、超级管理员全代码目录、权限为空、行权限、附件受保护链接、审批摘要和附件批量查询 |
|
||||
| 限速 | 单卡、设备当前卡、无/多当前卡、固定档位、恢复不限速、限到0kbps、运营商能力、Gateway 失败/结果未知和审计记录 |
|
||||
| 临期 | 当前与排队套餐最终到期推算、等待实名不可预计、15/7/3 天、3天红色和临期页置顶、漏跑补发、列表/详情/C端一致 |
|
||||
| 换货补充 | 新资产继承店铺、其他店铺资产拒绝、旧资产保留归属、前代/后代标识和受控跳转 |
|
||||
| 系列授权 | 首次和后续批量选择、已授权置灰、重复提交幂等、三类价格含义正确 |
|
||||
| 发布 | 存量退款和充值回填、历史 `legacy`、旧路由不可访问、Worker 暂停后恢复 |
|
||||
|
||||
验收使用接口调用、PostgreSQL 数据核对、日志检查和页面操作,不以自动化测试作为本项目交付前提。
|
||||
验收同时使用自动化测试、真实接口调用、PostgreSQL 数据核对、日志检查和页面操作;资金、状态机、权限、异步幂等和第三方 Adapter 必须有可重复的自动化公共行为测试,真实第三方联调与人工验收不能被测试替代。
|
||||
|
||||
---
|
||||
|
||||
@@ -1383,8 +1572,8 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
```text
|
||||
1. 增量迁移、事务管理、Outbox、统一审计模型和 Access Log 脱敏
|
||||
2. 站内通知与审计多视角 Query/前端
|
||||
3. 卡状态领域、轮询活跃调频、事件阶梯和运营商回调防腐层
|
||||
4. 企微连接、模板版本、账号扫码绑定、提交/回调/轮询
|
||||
3. 卡状态公共写入、现有轮询接入、事件阶梯和运营商回调防腐层
|
||||
4. 企微连接、模板版本、平台账号扫码绑定、代理固定代提交、提交/回调/轮询
|
||||
5. 退款和平台员工线下充值接入企微,代理微信/支付宝扫码充值
|
||||
6. 钱包信用额度、业务员和余额预警、批量订购、导出权限、设备批量分配、系列套餐批量授权、限速和临期提醒
|
||||
7. 换货归属与换货链、其他查询和显示修复、存量回填及停机发布演练
|
||||
@@ -1413,8 +1602,8 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
| 工作包 | 后端人日 | 前端人日 | 快速交付说明 |
|
||||
|--------|----------|----------|--------------|
|
||||
| 迁移、Outbox、全局审计和站内通知 | 2 | 1.5~2 | 复用现有日志、列表和抽屉组件,先完成核心多视角 |
|
||||
| 数据同步领域收口、活跃轮询和运营商回调 | 2~3 | 0.5~1 | 后端为主,前端只补状态和审计跳转 |
|
||||
| 企微模板、扫码绑定、提交/回调/轮询 | 2~3 | 1.5~2 | 复用企微官方页面和现有业务详情布局 |
|
||||
| 数据同步领域收口、事件触发和运营商回调 | 2~3 | 0.5~1 | 现有轮询调度不改,前端只补审计轨迹跳转 |
|
||||
| 企微模板、平台绑定、代理固定代提交、提交/回调/轮询 | 2~3 | 1.5~2 | 复用企微官方页面和现有业务详情布局 |
|
||||
| 退款、线下充值终态和代理扫码充值 | 2~3 | 1.5~2 | 复用现有钱包、支付回调和充值页面 |
|
||||
| 信用、业务员预警、换货、系列授权、批量、导出、限速和临期 | 2.5~3.5 | 2.5~3 | 系列授权和换货链已有后端基础,只补增量能力 |
|
||||
| 联调、数据核对、回填和停机发布 | 1~1.5 | 0.5~1 | 随开发持续联调,最后集中验证核心链路 |
|
||||
@@ -1428,8 +1617,8 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
|
||||
```text
|
||||
第 1~2 天:迁移、Outbox、审计/通知骨架,前端同步搭建页面框架
|
||||
第 3~5 天:数据同步收口、活跃轮询、回调防腐层和审计外部集成视角
|
||||
第 4~7 天:企微模板、扫码绑定、审批提交/回调/轮询及前端配置页面
|
||||
第 3~5 天:数据同步写入收口、事件阶梯、回调防腐层和审计外部集成视角
|
||||
第 4~7 天:企微模板、平台账号扫码绑定、代理固定代提交、审批提交/回调/轮询及前端配置页面
|
||||
第 6~9 天:退款、线下充值终态、代理微信/支付宝扫码充值
|
||||
第 8~12 天:信用、业务员预警、换货归属与标识、系列批量授权、批量、导出、限速和临期
|
||||
第 12~14 天:全链路联调、数据核对、旧入口清理和存量回填演练
|
||||
@@ -1445,7 +1634,7 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
| 本期范围与移出项 | 待评审 | | |
|
||||
| 渐进式 DDD 边界 | 待评审 | | |
|
||||
| 数据同步三通道与运营商回调 | 待评审 | | |
|
||||
| 企业微信审批、模板版本与账号绑定 | 待评审 | | |
|
||||
| 企业微信审批、模板版本、平台账号绑定与代理固定代提交 | 待评审 | | |
|
||||
| 全局多视角审计与历史投影 | 待评审 | | |
|
||||
| 站内通知与受控跳转 | 待评审 | | |
|
||||
| 资金与信用额度 | 待评审 | | |
|
||||
@@ -1455,4 +1644,4 @@ Gateway 的取消限速具体报文不是产品决策:上线前由上游接口
|
||||
| 前端交互和权限 | 待评审 | | |
|
||||
| 停机发布和回滚 | 待评审 | | |
|
||||
|
||||
评审通过条件:第八章约束全部纳入实施任务;除 Gateway 上游取消参数和真实第三方联调结果外,不存在需要实施人员自行猜测的数据模型、接口、状态语义或资金规则。
|
||||
评审通过条件:第八章约束全部纳入实施任务;除真实第三方联调结果和不同 Gateway 账户/运营商的档位映射配置外,不存在需要实施人员自行猜测的数据模型、接口、状态语义或资金规则。
|
||||
|
||||
Reference in New Issue
Block a user