# 转运任务支付功能设计方案(最终版) 本方案针对转运任务的"总额一次性支付"场景:总额=成交价+附加费用汇总,支持现金、挂帐、微信、支付宝四种方式。微信/支付宝由"独立支付模块"生成二维码与回调,我方系统仅对接该支付模块。 ## 一、最终确认点 - 结算金额必须与总金额一致(总金额=成交价+附加费用汇总)。 - 挂帐支付仅记录备注即可。 - 附加费用类型由后台字典维护(字典类型:task_additional_fee_type)。 - 微信、支付宝由独立支付模块生成支付二维码与查询结果,不直接集成商户号逻辑。 - 结算入口在 APP 的任务详情页和任务列表卡片上都要有。 - 后台 ruoyi-ui 只展示支付信息与附加费用明细,不允许修改。 - 只展示"有效支付"(最近一条已支付成功的记录)。 - 交易单号 outTradeNo 格式:{taskCode}-{timestampMillis},timestamp 使用毫秒级时间戳。 - 回调路径 callbackUrl 在创建二维码时由我方传入,必须为绝对地址(含域名与路径)。 - 金额校验:我方发起支付前强校验 settlementAmount==totalAmount;支付模块也进行金额二次校验。 ## 二、总体流程 1. APP 在任务列表与任务详情增加"结算"入口,跳转结算页。 2. 结算页拉取成交价与附加费用列表,允许新增/删除附加费用,实时计算总金额。 3. 选择支付方式并发起支付: - 现金、挂帐:后端直接标记已支付。 - 微信、支付宝:后端调用"支付模块创建二维码",返回 codeUrl 与过期时间给前端展示;前端轮询我方"支付状态接口"。 4. 支付成功后,APP 自动提示并展示"支付成功"状态;禁用后续修改。 5. ruoyi-ui 在任务明细页只读展示支付信息与附加费用明细。 ## 三、数据模型 支付与附加费独立建表,避免污染任务主表: ### sys_task_additional_fee(附加费用明细) - 字段:id, task_id, fee_type(字典), fee_name, unit_amount, quantity, total_amount, remark, created_by, created_time ### sys_task_payment(任务支付记录) - 字段:id, task_id, total_amount, settlement_amount(必须==total_amount), payment_method("CASH""ON_ACCOUNT""WECHAT""ALIPAY"), pay_status("UNPAID""PENDING""PAID""FAILED""REFUNDED"), pay_time, out_trade_no, trade_no, code_url, qr_expire_time, provider("WECHAT""ALIPAY"), payment_ref_id(支付模块返回唯一标识), callback_url, remark, created_by, created_time, update_time ### 成交价来源 - SysTaskEmergency.transferPrice - 总金额=transferPrice + sum(sys_task_additional_fee.total_amount) ### 有效支付 - 同一任务展示最近一条 pay_status="PAID"的记录;若不存在则显示"未支付" ## 四、字典与配置 ### 字典类型:task_additional_fee_type - 1:等待费 - 2:担架 - 3:居家ICU - 4:医疗设备 ### 配置项 - payment.module.url:支付模块服务地址(默认:http://localhost:8081/pay) - payment.callback.base-url:回调基础URL(默认:http://localhost:8080) ## 五、与支付模块的对接契约 ### 创建二维码(支付模块) - 接口:POST /pay/qrcode/create - 入参:outTradeNo, amount, provider("WECHAT""ALIPAY"), subject, attach(如 taskId/taskCode), callbackUrl(绝对地址) - 出参:paymentRefId, codeUrl, expireTime ### 查询支付状态(支付模块) - 接口:GET /pay/status?paymentRefId=xxx 或 GET /pay/status?outTradeNo=xxx - 出参:status("PENDING""PAID""FAILED""CLOSED"), tradeNo, payTime ### 回调(支付模块 → 我方) - 接口:POST {callbackUrl} - 体内字段:outTradeNo, tradeNo, amount, status=PAID, sign 等;我方验签后更新为 PAID ### 订单号规范 - outTradeNo:TASK-{taskCode}-{timestampMillis} - subject:"转运任务结算({taskCode})" ## 六、我方后端接口(APP 用) ### GET /task/payment/info - 入参:taskId - 出参:transferPrice, additionalFees[], additionalAmount, totalAmount, latestPayment(如有), paymentMethods["CASH""ON_ACCOUNT""WECHAT""ALIPAY"] ### POST /task/additional-fee/add - 入参:taskId, feeType, feeName, unitAmount, quantity, remark - 出参:additionalAmount, totalAmount ### POST /task/additional-fee/remove - 入参:taskId, feeId - 出参:additionalAmount, totalAmount ### POST /task/payment/create - 入参:taskId, paymentMethod, settlementAmount(必须==totalAmount), remark - 行为: - CASH/ON_ACCOUNT:直接创建支付记录并置为 PAID - WECHAT/ALIPAY:生成 outTradeNo(taskCode-毫秒时间戳)、计算 amount、准备 subject/attach/callbackUrl;调用支付模块创建二维码;保存 paymentRefId、codeUrl、expireTime,置为 PENDING 返回 - 出参:paymentId, payStatus, codeUrl(仅微信/支付宝), qrExpireTime ### GET /task/payment/status - 入参:taskId 或 paymentId - 行为:根据 paymentRefId 或 outTradeNo 调用支付模块查询;若返回 PAID,我方更新 sys_task_payment 为 PAID 并返回最新状态 - 出参:payStatus, tradeNo, payTime ### POST /payment/callback/{provider} - 支付模块回调接口,验签后更新支付状态为 PAID ## 七、APP 前端改造 ### 入口 - 任务列表卡片与任务详情页均增加"结算"按钮(详情页遵循既有按钮显示规则:仅完成/取消状态隐藏) ### 结算页(settlement.vue) - 初始化:调用 /task/payment/info 拉取成交价、附加费列表与汇总 - 附加费用:新增/删除使用对应接口,费用类型来自字典;刷新汇总 - 支付: - 现金/挂帐:调用 /task/payment/create,成功后提示"支付成功" - 微信/支付宝:调用 /task/payment/create 获取 codeUrl 与 qrExpireTime;展示二维码并每 2~3 秒轮询 /task/payment/status,直到 PAID 或超时 - 校验:settlementAmount 必须等于 totalAmount;二维码过期提示重新生成 - 成功后:禁用附加费用与支付操作;可返回任务详情 ## 八、ruoyi-ui 后台展示(只读) ### 任务明细页新增"支付信息"区块 - 展示:支付方式、结算金额、总金额、支付状态、交易号、支付时间 - 附加费用明细列表与汇总 - 若有历史支付记录,仅展示最近一次 PAID;不提供编辑或重试入口 ## 九、权限与安全 - APP 鉴权:JWT;仅任务归属成员(创建人、执行人、调度角色)可结算 - 数据权限:延续现有部门/分公司隔离规则 - 回调安全:callbackUrl 验签(签名算法由支付模块确定),可加源 IP 白名单 - 金额一致性:前后端双重校验;二维码创建后金额锁定,变更附加费需重新发起支付 ## 十、边界处理 - 二维码过期:提示并允许重新创建;旧支付记录置为 FAILED/CLOSED - 轮询与回调竞态:以我方后端支付状态为准(回调或查询更新) - 退款/撤销:本期不实现;如后续需要,增加 REFUNDED 状态与退款接口 ## 十一、验收标准 - APP:附加费用维护与总额计算正确;四种支付流程通畅;扫码支付成功后自动提示与禁用修改 - 后台:准确展示支付信息与附加费用明细;只显示有效支付 - 后端:支付与附加费落库正确;回调与轮询均能准确更新支付状态;金额校验严格生效 ## 十二、实现文件清单 ### 数据库 - sql/task_payment_tables.sql ### 实体类 - SysTaskAdditionalFee.java - SysTaskPayment.java - TaskPaymentInfoVO.java - TaskPaymentCreateVO.java - TaskPaymentResultVO.java ### Mapper - SysTaskAdditionalFeeMapper.java / SysTaskAdditionalFeeMapper.xml - SysTaskPaymentMapper.java / SysTaskPaymentMapper.xml ### Service - ISysTaskPaymentService.java / SysTaskPaymentServiceImpl.java - IPaymentModuleService.java / PaymentModuleServiceImpl.java ### Controller - SysTaskPaymentController.java - PaymentCallbackController.java ### 前端(待实现) - app/pages/task/settlement.vue(改造) - app/api/payment.js(新增) - ruoyi-ui/src/views/task/detail.vue(增加支付信息展示)