# Research: 可配置支付方式(031-pay-method-config) **Date**: 2026-09-11 | **Spec**: [spec.md](spec.md) 本文记录实现前核对的代码现状(含行号锚点)与既定决策,纠正旧记忆中过时的事实。 ## 一、代码现状(2026-09-11 核对) ### 1.1 payType 值域与三个下单入口 | 值 | 含义 | 备注 | |---|---|---| | 1 | 到付 | 商家建单固定用它(`PosOrderController.java:266/1226` `setPayType("1")`) | | 2 | 信用卡(OMG) | `OrderLifecycleService.isCardWalletPayType`(`PosOrderController.java:668`) | | 3 | LINE Pay | `LinePayService.PAY_TYPE_LINE`(`PosOrderController.java:676`) | | 4 | 现金 | 仅商家建单场景;闪送也已用作"现金" | | 5 | Apple Pay(OMG) | 与 2 同为 OMG 渠道 | | 6 | 线下转账 | 027 引入 | - **漏洞确认**:`UserOrderController.java:261` `posOrder.setPayType(input.getPaymentMethod())` —— 用户下单传什么存什么,**零校验**。 - 商家建单(`/addorder`)固定到付 1,无支付方式选择。 ### 1.2 闪送现状(⚠️ 纠正旧记忆"闪送零支付代码") 闪送**已有**支付字段与逻辑(近期提交"闪送订单增加支付方式字段"+"修改normalizePayType"): - `FlashDeliveryOrder.payType` 已存在(`FlashDeliveryOrder.java`,注释:4=现金、6=线下转账) - `FlashDeliveryApplicationService.normalizePayType(...)` 当前为**透传**(白名单校验被注释掉),缺省默认现金 - `FlashDeliveryOrderView.payType`、骑手列表 `FlashDeliveryRiderOrderListView.payType` 均已返回 - 闪送**没有**:payment_status(收款状态)、下单闸门校验、骑手收款方式设置 ### 1.3 027 线下转账(迁移基准) - 接口:`GET /chanting/store/bankInfo?id={storeId}`(匿名)——`pos_store.id → user_id → info_user`,返回 **bankAccountName / bankName / bankAccountNo** 三字段;客户端 `data != null` 才显示线下支付(详见 `specs/027-offline-transfer-payment/contracts/api.md`) - 商家确认收款:`/system/orderShOprate/confirmTransferPayment`(**商家**确认,订单级;031 的骑手确认收款是闪送订单级,二者并存不冲突) - `InfoUser` 银行相关字段:`bankAccount`(185)、`bankPhoto`(193)、`bankAccountName`(197)、`bankName`(199)、`bankAccountNo`(205)。027 转账展示用的三字段 = `bankName + bankAccountNo + bankAccountName`。 ### 1.4 凭证与就绪度数据源 - OMG(信用卡/Apple Pay):门店级 `pos_store_omg`(`/system/storeOmg` 管理) - LINE Pay:门店级 `pos_store_line_pay` - admin-vue 已有门店支付凭证配置页:`foodie-admin-vue/src/views/mendian/storePayment`(OmgTab/LinePayTab)——031 的平台开关页是**独立新页**(方式×维度开关),不复用该页 ### 1.5 可复用先例 - 银行字典:`taiwan_bank_list` 已存在,且有读取先例(`InfoUserController.java:815-821`,`query.setDictType("taiwan_bank_list")`) - 商家 PC 设置页先例:`foodie-store/src/views/SelfDeliverySettings.vue`(029) - 平台开关先例:008 用 `sys_config` 单 key;**本期改用结构化表**(已决策),理由:方式×维度矩阵、带排序、可逐行改 - 模块边界:校验服务需读 `info_user`/`pos_store_omg`/`pos_store_line_pay`/`info_bank_card`(全在 ruoyi-system)→ 闸门服务放 **ruoyi-system**,Controller 调用在 ruoyi-admin(符合 admin→system 单向依赖) ### 1.6 前端项目 - 平台端:`E:\QtwCode\foodie\foodie-admin-vue`(新页"支付方式设置",四语言) - 商家端:`E:\QtwCode\foodie\foodie-store`(新页"支付设置"= 方式勾选 + 银行卡管理,vue-i18n 四语言 `src/lang/`) - 两项目文件均为 CRLF,编辑用 Python 脚本(项目惯例) ## 二、既定决策(不再讨论,实现依据) 来源:2026-09-09 对话定稿 13 项 + 2026-09-11 补充 2 项,全文见 spec.md。 1. 三层闸门:可用 = 平台开关(方式×维度) ∩ 收款方选择 ∩ 就绪度;维度 = MERCHANT(商家餐饮单) / RIDER_FLASH(骑手闪送),独立开关可交叉 2. 闪送资金用户直达骑手,平台不经手;支付方式**下单时选**并随订单固定 3. 骑手未设置 flash_pay_methods = 平台开放全部;商家 pay_methods NULL = 全部启用(存量零变化) 4. 商家选择在**主账号级**(连锁共享,与 027 银行信息语义一致) 5. 信用卡+Apple Pay 同组一个开关(OMG 渠道,023 同组先例) 6. 到付(1) 纳入管控默认开;现金(4) 不纳入(仅商家建单) 7. 不做平台逐店覆盖(YAGNI) 8. 老 App:后端拒绝+国际化提示;`bankInfo` 接口保留、结构不变、改读启用卡、套闸门 9. 商家 PC 做设置页;商家 App/骑手 App 只出接口(027 FR-010 模式) 10. 银行卡列表化:`info_bank_card` 挂 info_user,商家/骑手通用,多卡同时仅一张 is_active,启用新卡停旧卡;付款方只见启用卡 11. 027 迁移:info_user 三字段存量 `INSERT...SELECT` 迁成一张启用卡;就绪度判据从"三字段齐全"改"存在启用卡" 12. 骑手确认收款:闪送订单 paymentStatus 0→1 + 操作日志;不阻塞送达/完成 13. **下单闸门校验封装为单一独立方法**(唯一校验入口),三下单路径(用户餐饮下单/商家建单/闪送下单)统一下单时调用,禁止各入口重复实现 14. DDL 全部追加 `updatesql/sql.md`,开发者手动执行 15. 平台开关缺行语义 = 开启(零数据依赖,新方式代码上线即默认可用,平台页保存时才落行,enabled=0 才是关) ## 三、实现要点结论 - 闪送支付方式**复用现有 `pay_type` 列**扩展值域(不新增列);仅新增 `payment_status` - `normalizePayType` 透传行为改为调用闸门校验方法(补回被注释掉的白名单 + 三层闸门) - `bankInfo` 返回结构与字段名完全不变,仅数据源与可见性判断变化 - 闸门服务命名建议 `PaymentMethodGateService`(ruoyi-system),提供 `assertUsable(...)`(校验,抛国际化异常)与 `listAvailable(...)`(结算页可选项)两个核心方法