Преглед изворни кода

chore: 016 门店支付配置菜单SQL/tasks跟踪 + 010 会员载具carrier清理SQL

updatesql/sql.md:
- 016: 门店 OMG 凭证菜单改为「门店支付配置」(component=mendian/storePayment/index),
  配合 admin-vue 的 Tab 页结构;权限仍为 chanting:storeOmg:*
- 010: 清空历史 MEMBER 发票行误存的 carrier_type='2'(INV10013 修复的数据兜底)

specs/016-omg-payment/tasks.md:
- T028 勾选(门店支付配置 Tab 页已完成)
- T017/T024 标注推迟(客户侧流程,客户 uni-app 不在当前工作区)

Co-Authored-By: Claude <noreply@anthropic.com>
qmj пре 5 часа
родитељ
комит
9b517be734
2 измењених фајлова са 17 додато и 5 уклоњено
  1. 3 3
      specs/016-omg-payment/tasks.md
  2. 14 2
      updatesql/sql.md

+ 3 - 3
specs/016-omg-payment/tasks.md

@@ -62,7 +62,7 @@ description: "Task list for OMG(歐買尬/FunPoint)AIO 支付接入"
 - [x] T014 [US1] 实现 `ruoyi-system/.../service/IPosOrderOmgPaymentService.java` + `impl/PosOrderOmgPaymentServiceImpl.java`:`createPayment(ddId,merchantTradeNo,storeId,merchantId,amount,choosePayment)`、`getByTradeNo`、`getByMerchantTradeNo`、`getLatestByDdId`、`markSuccess(...payType,rtnCode,rtnMsg,authCode,payTime,callbackRaw)`(幂等:tradeNo 已 pay_status=1 返回 0)、`markFail`、`markRefunded`
 - [x] T014 [US1] 实现 `ruoyi-system/.../service/IPosOrderOmgPaymentService.java` + `impl/PosOrderOmgPaymentServiceImpl.java`:`createPayment(ddId,merchantTradeNo,storeId,merchantId,amount,choosePayment)`、`getByTradeNo`、`getByMerchantTradeNo`、`getLatestByDdId`、`markSuccess(...payType,rtnCode,rtnMsg,authCode,payTime,callbackRaw)`(幂等:tradeNo 已 pay_status=1 返回 0)、`markFail`、`markRefunded`
 - [x] T015 [US1] 在 `ruoyi-system/.../domain/PosOrder.java` 附近或新建常量类定义 `PAY_TYPE_OMG="7"`(OMG 在线支付),不改表结构
 - [x] T015 [US1] 在 `ruoyi-system/.../domain/PosOrder.java` 附近或新建常量类定义 `PAY_TYPE_OMG="7"`(OMG 在线支付),不改表结构
 - [x] T016 [US1] 创建 `ruoyi-admin/src/main/java/com/ruoyi/app/pay/OmgPayController.java` 实现 `POST /pay/omg/create`(`@Anonymous`+`@Auth`,Header token):校验订单存在/未支付/属当前用户/金额>0 → `getEnabledConfig(mdId)`(无则 `error("该门店暂不支持线上支付")`)→ `MerchantTradeNo="OMG"+清洗(ddId)` → 组参(MerchantID/MerchantTradeNo/MerchantTradeDate=yyyy/MM/dd HH:mm:ss/PaymentType=aio/TotalAmount=amount/ReturnURL/ChoosePayment=ALL/EncryptType=1/ItemName/InvoiceMark=N)→ `OmgPay.createAioForm` 生成 CheckMacValue 与 form 字段 → `createPayment` 落流水(pay_status=0) → 更新 `pos_order.pay_type="7"`/`pay_url=gatewayUrl` → 返回 form 字段(见 contracts/api.md B1)
 - [x] T016 [US1] 创建 `ruoyi-admin/src/main/java/com/ruoyi/app/pay/OmgPayController.java` 实现 `POST /pay/omg/create`(`@Anonymous`+`@Auth`,Header token):校验订单存在/未支付/属当前用户/金额>0 → `getEnabledConfig(mdId)`(无则 `error("该门店暂不支持线上支付")`)→ `MerchantTradeNo="OMG"+清洗(ddId)` → 组参(MerchantID/MerchantTradeNo/MerchantTradeDate=yyyy/MM/dd HH:mm:ss/PaymentType=aio/TotalAmount=amount/ReturnURL/ChoosePayment=ALL/EncryptType=1/ItemName/InvoiceMark=N)→ `OmgPay.createAioForm` 生成 CheckMacValue 与 form 字段 → `createPayment` 落流水(pay_status=0) → 更新 `pos_order.pay_type="7"`/`pay_url=gatewayUrl` → 返回 form 字段(见 contracts/api.md B1)
-- [ ] T017 [US1] 前端 `E:\QtwCode\foodie\foodie-store\` 新增「OMG 支付」入口:下单后调 `/pay/omg/create`,用返回字段构建隐藏 form 自动 submit 到 `gatewayUrl`;支付相关文案用 `$t()` 四语 i18n(zh/tw/en/vi,key 加到对应对象层级,有意义命名)
+- [ ] T017 [US1] 前端 `E:\QtwCode\foodie\foodie-store\` 新增「OMG 支付」入口:下单后调 `/pay/omg/create`,用返回字段构建隐藏 form 自动 submit 到 `gatewayUrl`;支付相关文案用 `$t()` 四语 i18n(zh/tw/en/vi,key 加到对应对象层级,有意义命名)  ⏸️ 推迟:属客户侧流程(客户下单→Form Post 跳 OMG),foodie-store 是商家端无此入口,客户 uni-app 不在当前工作区,待其就位再做
 
 
 **Checkpoint**: 发起支付链路通,可跳转 OMG 测试收银台(此时回调未接,订单状态待 US2 更新)
 **Checkpoint**: 发起支付链路通,可跳转 OMG 测试收银台(此时回调未接,订单状态待 US2 更新)
 
 
@@ -80,7 +80,7 @@ description: "Task list for OMG(歐買尬/FunPoint)AIO 支付接入"
 - [x] T021 [US2] notify 成功业务链路:`markSuccess`(pay_type=回覆 PaymentType 如 `Credit_CreditCard`、rtn_code、pay_time=PaymentDate、callback_raw)→ 更新 `pos_order`(state=0, payStatus=1) → `orderLogHelper.logSync` 记日志 → `PayPush`+`pushEventService.PublisherEvent` 推送用户/商家(参照 `PosOrderController.sendHdfkMessage` 货到付款同款 `OrderPushBodyDto.getJson`)→ **补全可接单骑手推送**:在 `OmgPayController` 内独立实现(复用 `PayPush.sendAcceptRiderPush` / 货到付款链路调用方式,**不复用 NewebPay 代码**,见 CLAUDE.md「sendAcceptRiderPush 迁移」)→ 回应**纯字符串 `1|OK`**(注意:非 JSON,与蓝新不同)
 - [x] T021 [US2] notify 成功业务链路:`markSuccess`(pay_type=回覆 PaymentType 如 `Credit_CreditCard`、rtn_code、pay_time=PaymentDate、callback_raw)→ 更新 `pos_order`(state=0, payStatus=1) → `orderLogHelper.logSync` 记日志 → `PayPush`+`pushEventService.PublisherEvent` 推送用户/商家(参照 `PosOrderController.sendHdfkMessage` 货到付款同款 `OrderPushBodyDto.getJson`)→ **补全可接单骑手推送**:在 `OmgPayController` 内独立实现(复用 `PayPush.sendAcceptRiderPush` / 货到付款链路调用方式,**不复用 NewebPay 代码**,见 CLAUDE.md「sendAcceptRiderPush 迁移」)→ 回应**纯字符串 `1|OK`**(注意:非 JSON,与蓝新不同)
 - [x] T022 [US2] notify 失败处理(`RtnCode!=1`):`markFail` 写流水(pay_status=2)、订单保持未支付、记 `rtn_code`+`rtn_msg`(不硬编码错误码分支,见 contracts §C3)、回 `1|OK`
 - [x] T022 [US2] notify 失败处理(`RtnCode!=1`):`markFail` 写流水(pay_status=2)、订单保持未支付、记 `rtn_code`+`rtn_msg`(不硬编码错误码分支,见 contracts §C3)、回 `1|OK`
 - [x] T023 [US2] 在 `OmgPayController.java` 实现 `GET|POST /pay/omg/return`(`@Anonymous`):仅 302 重定向前端结果页(带 ddId),**不改订单状态**(以 notify 为准)
 - [x] T023 [US2] 在 `OmgPayController.java` 实现 `GET|POST /pay/omg/return`(`@Anonymous`):仅 302 重定向前端结果页(带 ddId),**不改订单状态**(以 notify 为准)
-- [ ] T024 [US2] 前端 `E:\QtwCode\foodie\foodie-store\` 支付结果页:展示支付状态、轮询订单 payStatus(ReturnURL 不改状态,以轮询/回调后状态为准);文案四语 i18n
+- [ ] T024 [US2] 前端 `E:\QtwCode\foodie\foodie-store\` 支付结果页:展示支付状态、轮询订单 payStatus(ReturnURL 不改状态,以轮询/回调后状态为准);文案四语 i18n  ⏸️ 推迟:同 T017,支付结果页属客户侧
 
 
 **Checkpoint**: US1+US2 构成完整 MVP——下单→付款→订单已支付→推送,可端到端验证(quickstart 场景 B、C)
 **Checkpoint**: US1+US2 构成完整 MVP——下单→付款→订单已支付→推送,可端到端验证(quickstart 场景 B、C)
 
 
@@ -95,7 +95,7 @@ description: "Task list for OMG(歐買尬/FunPoint)AIO 支付接入"
 - [x] T025 [US5] 创建 `ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreOmgController.java`(`/system/storeOmg`,`@PreAuthorize("chanting:storeOmg:*")`):`list`/`{storeId}`/`apply/{storeId}`/`saveCredentials`/`toggleEnable/{storeId}`/`reset/{storeId}`/`enabledPayments/{storeId}`,仿 `PosStoreEzpayController` 模式
 - [x] T025 [US5] 创建 `ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreOmgController.java`(`/system/storeOmg`,`@PreAuthorize("chanting:storeOmg:*")`):`list`/`{storeId}`/`apply/{storeId}`/`saveCredentials`/`toggleEnable/{storeId}`/`reset/{storeId}`/`enabledPayments/{storeId}`,仿 `PosStoreEzpayController` 模式
 - [x] T026 [US5] `saveCredentials` 凭证验证:Controller 调 `OmgPay.queryTrade(fictitious MerchantTradeNo)` 探测;响应提示金钥/商店错误 → 视为无效拒绝、状态不变、记 `last_verify_result`;否则 `enableWithCredentials`(omg_status=2/is_enabled=1)
 - [x] T026 [US5] `saveCredentials` 凭证验证:Controller 调 `OmgPay.queryTrade(fictitious MerchantTradeNo)` 探测;响应提示金钥/商店错误 → 视为无效拒绝、状态不变、记 `last_verify_result`;否则 `enableWithCredentials`(omg_status=2/is_enabled=1)
 - [x] T027 [US5] 扩展 `PosStoreOmgServiceImpl`:`apply`(0→1)、`enableWithCredentials`、`toggleEnable`、`reset`、`setEnabledPayments`、`recordVerifyResult`(仿 PosStoreEzpayServiceImpl 状态机)
 - [x] T027 [US5] 扩展 `PosStoreOmgServiceImpl`:`apply`(0→1)、`enableWithCredentials`、`toggleEnable`、`reset`、`setEnabledPayments`、`recordVerifyResult`(仿 PosStoreEzpayServiceImpl 状态机)
-- [ ] T028 [US5] 平台后台 `E:\QtwCode\foodie\foodie-admin-vue\` 新增门店 OMG 凭证管理页(列表分页/详情/录入凭证/启停/重置/设置方式),文案四语 i18n
+- [x] T028 [US5] 平台后台 `E:\QtwCode\foodie\foodie-admin-vue\` 新增门店 OMG 凭证管理页(列表分页/详情/录入凭证/启停/重置/设置方式),文案四语 i18n  ✅ 实现为「门店支付配置」Tab 页(OMG Tab 可用 + LINE Pay 占位),克隆 storeNewebpay;权限 chanting:storeOmg:* 不变;菜单 component=mendian/storePayment/index(见 sql.md)
 - [x] T029 [US5] 菜单与权限:新增菜单项 + 权限标识 `chanting:storeOmg:list/query/apply/saveCredentials/toggleEnable`,`sys_menu` 插入 SQL 写入 `updatesql/sql.md`(仿 storeEzpay 菜单,不直接执行)
 - [x] T029 [US5] 菜单与权限:新增菜单项 + 权限标识 `chanting:storeOmg:list/query/apply/saveCredentials/toggleEnable`,`sys_menu` 插入 SQL 写入 `updatesql/sql.md`(仿 storeEzpay 菜单,不直接执行)
 
 
 **Checkpoint**: 凭证可全流程管理,US1 发起支付有真实凭证来源(不必手插数据)
 **Checkpoint**: 凭证可全流程管理,US1 发起支付有真实凭证来源(不必手插数据)

+ 14 - 2
updatesql/sql.md

@@ -550,7 +550,7 @@ CREATE TABLE pos_order_omg_refund (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OMG退款记录';
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OMG退款记录';
 ```
 ```
 
 
-## 2026-07-29 OMG支付接入 - 门店OMG凭证管理菜单与权限(016-omg-payment US5
+## 2026-07-29 OMG支付接入 - 门店支付配置菜单与权限(016-omg-payment US5,Tab页:OMG可用 / LINE Pay预留
 
 
 ```sql
 ```sql
 -- 注:parent_id 需匹配平台后台实际「门店/支付」目录的 menu_id;
 -- 注:parent_id 需匹配平台后台实际「门店/支付」目录的 menu_id;
@@ -558,7 +558,7 @@ CREATE TABLE pos_order_omg_refund (
 
 
 -- 主菜单(页面)
 -- 主菜单(页面)
 INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time, remark)
 INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time, remark)
-VALUES ('OMG凭证', 0, 50, 'storeOmg', 'mendian/storeOmg/index', 'C', '0', '0', 'chanting:storeOmg:list', '#', 'admin', NOW(), '门店OMG(歐買尬)支付凭证管理');
+VALUES ('门店支付配置', 0, 50, 'storePayment', 'mendian/storePayment/index', 'C', '0', '0', 'chanting:storeOmg:list', '#', 'admin', NOW(), '门店支付配置(OMG;后续在同一页加Tab扩展LINE Pay等)');
 SET @omgMenuId = LAST_INSERT_ID();
 SET @omgMenuId = LAST_INSERT_ID();
 
 
 -- 按钮权限
 -- 按钮权限
@@ -568,3 +568,15 @@ INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_typ
 ('OMG录入凭证', @omgMenuId, 3, '#', '', 'F', '0', '0', 'chanting:storeOmg:saveCredentials', '#', 'admin', NOW(), ''),
 ('OMG录入凭证', @omgMenuId, 3, '#', '', 'F', '0', '0', 'chanting:storeOmg:saveCredentials', '#', 'admin', NOW(), ''),
 ('OMG停用恢复', @omgMenuId, 4, '#', '', 'F', '0', '0', 'chanting:storeOmg:toggleEnable', '#', 'admin', NOW(), '');
 ('OMG停用恢复', @omgMenuId, 4, '#', '', 'F', '0', '0', 'chanting:storeOmg:toggleEnable', '#', 'admin', NOW(), '');
 ```
 ```
+
+
+## 2026-08-05 修复:会员载具(MEMBER)误用 ezPay 电子载具 type2(016/010)
+
+```sql
+-- 背景:MEMBER 原映射 carrier_type='2'(ezPay会员载具+PrintFlag=N),ezPay 强制要 BuyerEmail → INV10013 失败。
+-- 决策(2026-08-05):MEMBER 改走 PrintFlag=Y 索取纸本(不传 CarrierType),代码已改。
+-- 本 SQL 清空历史 MEMBER 发票行里误存的 carrier_type/carrier_num,使重开(retry)与详情展示和代码一致
+-- (会员手机号已在 buyer_name)。
+UPDATE pos_order_invoice SET carrier_type = NULL, carrier_num = NULL
+WHERE invoice_choice = 'MEMBER' AND carrier_type = '2';
+```