6.9 KiB
Context
AUG26-017 给代理预存款带来两类变化:在线自充的收款方式从「由支付配置自动决定」改为「超管配置允许范围」;线下预存款审批从「金额 + 支付凭证」补齐为「收款方式 + 交易流水号 + 其他凭证」。后端接口边界已经确认:
| 用途 | 接口 |
|---|---|
| 在线可用方式 | GET /api/admin/agent-self-recharge-payment-methods,代理/平台可用,超管 403;旧接口 GET /api/admin/agent-recharges/payment-methods 保留但前端不再调用 |
| 允许范围读取 | GET /api/admin/system-configs(module、page、page_size,返回 list / page / page_size / total) |
| 允许范围写入 | PUT /api/admin/system-configs/{key},请求体 { key, value },value 为字符串化配置值 |
| 交易流水号识别 | POST /api/admin/agent-recharges/payment-voucher-ocr,请求 { payment_voucher_key },响应 { external_transaction_no } |
| 线下创建 | POST /api/admin/agent-recharges,payment_method=offline 时新增 offline_payment_method_id、external_transaction_no、other_voucher_key |
| 列表与详情 | GET /api/admin/agent-recharges、GET /api/admin/agent-recharges/{id} 新增 5 个响应字段 |
Goals / Non-Goals
Goals
- 在线充值只展示后端返回的实际可用方式,并优雅处理空列表。
- 超管可在既有系统配置页面维护允许范围,无需新增接口或页面。
- 线下预存款申请可提交收款方式、交易流水号与其他凭证,并支持 OCR 预填流水号。
- 列表与详情正确展示两类交易号与收款方式快照。
Non-Goals
- 不新增「代理自充设置」独立页面与专用配置接口。
- 不实现允许范围的审计查询接口(后端记录操作者、前后值与时间,前端不查询)。
- 不实现后端接口、商户池交集计算、企微审批回调。
- 不实现 H5/C 端在线充值,不为企业账号做分支。
Decisions
允许范围沿用受控系统配置
允许范围配置项的读取与写入统一走系统配置:读取 GET /api/admin/system-configs,写入 PUT /api/admin/system-configs/{key}。系统配置页已是元数据驱动的通用渲染器(value_type 决定控件、enum_values 决定枚举选项、readonly 与 sensitive 决定保护策略),因此后端的允许范围配置项注册后即可在页面中展示与编辑。
前端 MUST NOT 硬编码该配置项的 config_key,也 MUST NOT 新增专用设置写接口。该配置项归属 c2b.payment 模块,属于现有 SystemConfigModule 取值,无需扩展模块枚举。
允许范围的枚举取值为 wechat_only(仅微信支付)、alipay_only(仅支付宝支付)、both(同时支持微信与支付宝);系统配置页展示与选择时使用中文标签,未命中映射时回退展示原值。
超管入口使用一个「代理自充设置」菜单项,跳转到系统配置页面并带 module=c2b.payment 过滤条件;系统配置页面除了既有的 config_key query,还需支持从 route.query.module 初始化模块筛选,保证跳转后列表已按模块收敛。
在线可用方式
| 项 | 取值 |
|---|---|
| 接口 | GET /api/admin/agent-self-recharge-payment-methods |
| 响应 | { methods: (wechat | alipay)[], min_amount, max_amount } |
| 空列表 | 只提示「当前暂无可用的在线支付方式」,禁用提交,不解释被限制还是无可用商户 |
| 超管 | 该接口对超管返回 403,前端在超管视角不请求它,仅通过系统配置查看允许范围 |
| 存量单 | 配置变更不影响已创建的待支付单,前端不在配置变更后刷新待支付单 |
金额上下限优先使用接口返回的 min_amount / max_amount(单位分),接口未返回时回退既有常量。
线下预存款创建字段
| 字段 | 必填 | 说明 |
|---|---|---|
offline_payment_method_id |
是 | 取自 GET /api/admin/employee-collection-payment-methods 的启用项(enabled=true,page_size=100) |
external_transaction_no |
是 | 交易流水号,OCR 预填后人工确认,可编辑;前端不做重复校验 |
other_voucher_key |
否 | 其他凭证对象键数组,最多 5 个 |
payment_voucher_key |
是 | 支付凭证,至少 1 个,与其他凭证分开提交 |
历史线下单的收款方式只用 offline_payment_method_code / offline_payment_method_name 快照展示,不用 offline_payment_method_id 反查字典当前值。
列表筛选保持后端已有参数集合(page、page_size、shop_id、status、recharge_source、start_date、end_date),不新增交易流水号筛选,交易流水号只做展示。
OCR 预填交互
- 入口:线下代充弹窗支付凭证区的「识别凭证」按钮,取已上传的第一个
payment_voucher_key;未上传凭证时禁用。 - 请求:
POST /api/admin/agent-recharges/payment-voucher-ocr;通过BaseService.post的第三个参数传{ timeout: 30000 },请求期间按钮与交易流水号字段展示 loading 并防重复点击。 - 成功:把
external_transaction_no写入交易流水号输入框,字段保持可编辑并提示对照凭证核对。 - 失败(凭证不是图片、对象不存在、识别服务异常):只提示,不清空已填内容、不阻断手工填写与提交。
- 只预填交易流水号,金额、付款人、付款时间、备注一律不预填。
凭证上传类型
取上传地址时必须显式声明 content_type 为 image/jpeg,否则 OCR 会以「不是图片」直接拒绝。VoucherUpload 新增可选 contentType prop,代理充值的支付凭证与其他凭证固定传 image/jpeg,并把它透传给 StorageService.getUploadUrl 与 StorageService.uploadFile。
交易流水号展示
payment_transaction_id 是在线渠道返回的权威交易号,只有在线单有值;external_transaction_no 是线下人工申报的交易流水号。两者独立展示、互不覆盖:在线单只展示前者,线下单只展示后者。
详情页保持只读
代理充值详情页只做信息展示,顶部仅保留返回导航;本次新增的交易流水号、收款方式与其他凭证都只读呈现,不引入任何业务操作按钮。创建、确认线下充值、驳回等操作入口仍留在列表页操作列。
Risks / Trade-offs
- 配置 Key 由后端注册决定:前端不硬编码,配置项按
c2b.payment模块渲染;若后端最终调整模块归属,只需同步调整菜单跳转的module参数。 - OCR 端到端约 15 至 16 秒:必须配置不低于 30 秒的超时并展示 loading,否则用户容易重复点击。
- 强制声明
image/jpeg:按需求文档要求统一声明为image/jpeg,上传非 JPEG 图片时以声明类型为准。 - 收款方式字典项被引用后会冻结:展示历史单依赖快照字段,避免字典改名或停用导致历史数据展示漂移。