# Implementation Plan: OMG(歐買尬/FunPoint)AIO 支付接入 **Branch**: `(待创建,暂未建分支/未提交)` | **Date**: 2026-07-29 | **Spec**: [spec.md](spec.md) **Input**: Feature specification from `/specs/016-omg-payment/spec.md` ## Summary 接入台湾 OMG(歐買尬,金流引擎 FunPoint)AIO 幕前支付作为餐饮订单的在线支付,替代蓝新 NewebPay(不再启用)。OMG 用 `CheckMacValue`(SHA256) 单字段签名(无 AES、无解密),支持全部支付方式(信用卡/Apple Pay/ATM/超商/BarcodeATM/AFTEE,`ChoosePayment=ALL`),门店级凭证,本期含信用卡退款。**OMG 全部代码独立新建,不复用任何蓝新金流代码/表**;仅复用平台共享基础设施(订单状态机、推送、订单日志)。 技术决策与备选见 [research.md](research.md),表结构见 [data-model.md](data-model.md),接口契约见 [contracts/api.md](contracts/api.md),验证场景见 [quickstart.md](quickstart.md)。 ## Technical Context **Language/Version**: Java 21(Spring Boot 3 / RuoYi-Vue-Plus,MyBatis-Plus,Lombok) **Primary Dependencies**: Spring Boot、MyBatis-Plus(@TableName/@TableId,XML mapper)、Apache HttpClient 4(幕后 POST QueryTradeInfo/DoAction)、fastjson2、`@Anonymous`/`PermitAllUrlProperties`(回调白名单) **Storage**: MySQL(新增 `pos_store_omg` / `pos_order_omg_payment` / `pos_order_omg_refund` 三表,DDL 写 `updatesql/sql.md` 不直接执行;`pos_order` 不改结构,仅扩展 `pay_type="7"`) **Testing**: 工具类 `main` 自测(CheckMacValue 用官方示例值复算)+ 测试环境端到端(测试卡,见 quickstart.md);项目无统一自动化测试框架约定 **Target Platform**: Linux server(后端服务),配合 uni-app 用户端 Form Post 跳转 OMG 收银台 **Project Type**: web-service(后端) **Performance Goals**: 发起支付接口 < 1s;回调核销幂等无重复发货 **Constraints**: CheckMacValue 必须与 OMG 完全一致(含 .NET 风格 URL 编码与小写);回调须回纯串 `1|OK`;门店级凭证;`InvoiceMark=N`(发票走 ezPay 解耦);外部 HTTP 工具类须放 `ruoyi-admin`(模块依赖 admin→system 不可反向) **Scale/Scope**: 全平台餐饮订单在线支付(旅游·机票 015 后续衔接,不在本期) ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* `.specify/memory/constitution.md` 为未填写模板(占位符),无实际治理原则可校验。改为遵循项目 `CLAUDE.md` 与记忆中的硬约束: | 约束 | 本期遵守 | |------|----------| | 模块依赖 admin→system 不可反向 | ✅ OMG 外部 HTTP/签名工具类放 `ruoyi-admin/.../app/utils/omg/`,联网验证在 Controller 层;实体/Service/Mapper 放 `ruoyi-system` | | 外部 HTTP 工具类(httpclient4+fastjson2)放 admin | ✅ `OmgPay`/`OmgCheckMacValue` 在 admin | | 后端文件 CRLF | ✅ 新建 Java/md 文件保持 CRLF | | DB 变更写 `updatesql/sql.md` 不直接执行 | ✅ 三表 DDL 写入,不执行 | | 前端新功能必须 i18n | 本期后端为主;若涉及前端支付跳转/结果页文字,按规范加 4 语言 | | 范围控制 / 简单优先 | ✅ 不复用蓝新、不抽公共支付套件(仅一个使用点) | | **OMG 不复用蓝新代码**(用户新增) | ✅ 零 `newebpay` import,独立凭证/流水/退款表 | **结论**:无违规,Phase 0 可继续。Phase 1 设计后再次确认无蓝新耦合。 ## Project Structure ### Documentation (this feature) ```text specs/016-omg-payment/ ├── plan.md # 本文件 ├── research.md # Phase 0:技术决策 ├── data-model.md # Phase 1:表结构 + DDL ├── quickstart.md # Phase 1:端到端验证 ├── contracts/ │ └── api.md # Phase 1:OMG 外部接口 + 平台内部接口 └── tasks.md # Phase 2 (/speckit-tasks 生成,本阶段不创建) ``` ### Source Code (repository root) ```text ruoyi-admin/src/main/java/com/ruoyi/app/ ├── utils/omg/ # OMG 专属,零 newebpay 依赖 │ ├── OmgCheckMacValue.java # CheckMacValue(SHA256) 生成/校验 + main 自测 │ ├── OmgPayConfig.java # MerchantID / HashKey / HashIV │ └── OmgPay.java # HTTP 客户端:createAioForm / queryTrade / doAction ├── pay/ │ └── OmgPayController.java # /pay/omg/{create,notify,return,paymentInfo}(US1/US2/US3) └── mendian/ └── PosStoreOmgController.java # /system/storeOmg/* 凭证开通管理(US5) ruoyi-system/src/main/java/com/ruoyi/system/ ├── domain/ │ ├── PosStoreOmg.java # 门店 OMG 凭证(pos_store_omg) │ ├── PosOrderOmgPayment.java # OMG 支付流水(pos_order_omg_payment) │ ├── PosOrderOmgRefund.java # OMG 退款记录(pos_order_omg_refund) │ ├── vo/PosStoreOmgVo.java │ └── dto/StoreOmgCredentialDto.java ├── mapper/ │ ├── PosStoreOmgMapper.java (+xml) │ ├── PosOrderOmgPaymentMapper.java (+xml) │ └── PosOrderOmgRefundMapper.java (+xml) └── service/ ├── IPosStoreOmgService.java + impl ├── IPosOrderOmgPaymentService.java + impl └── IPosOrderOmgRefundService.java + impl updatesql/sql.md # 追加三表 DDL(2026-07-29) application.yml (+application-dev.yml) # 新增 omg.* 配置段 ``` **Structure Decision**:沿用项目既有分层(utils 在 `ruoyi-admin/.../app/utils/omg/`,domain/mapper/service 在 `ruoyi-system`,Controller 在 `ruoyi-admin/.../app/{pay,mendian}`),与 ezPay/newebpay 同构但**独立包/独立类/独立表**。退款入口(US4)并入 `OmgPayController` 或订单取消链路(`PosOrderShOprate`/`UserOrderController` 取消时触发),tasks 阶段定具体落点。 ## Complexity Tracking > Constitution Check 无违规,无需填表。 | Violation | Why Needed | Simpler Alternative Rejected Because | |-----------|------------|-------------------------------------| | — | — | — |