Branch: test(不新建分支,在当前 test 分支开发) | Date: 2026-06-22 | Spec: spec.md
Input: Feature specification from /specs/011-newebpay-payment/spec.md
为系统接入台湾蓝新金流(NewebPay) MPG 幕前线上支付。C 端用户下单后由后端按门店凭证生成 AES-256-CBC + SHA256 加密的 MPG 交易参数,前端 Form Post 跳转蓝新付款页完成信用卡 / LINE Pay / Apple Pay 支付;蓝新经 NotifyURL 背景回调通知结果,系统解密验签、幂等、金额校验后更新订单支付状态并复用现有推送/记账链路;另支持单笔查询用于对账与回调丢失补单。
凭证按门店存储(新建 pos_store_newebpay,复用 009 开通管理模式),交易流水独立成表 pos_order_payment(按蓝新交易序号幂等)。加密工具新建 NewebPayEncryptUtil(标准 PKCS7 块16,区别于 ezPay 的块32),HTTP 客户端 NewebPay。详见 research.md、data-model.md、contracts/api.md、quickstart.md。
Language/Version: Java 17(Spring Boot 3,证据:jakarta.* 包、@EnableMethodSecurity)
Primary Dependencies: Spring Boot 3、Spring Security(@PreAuthorize/@Anonymous/PermitAllUrlProperties)、MyBatis-Plus(@TableName/@TableId/LambdaQueryWrapper)、MySQL、fastjson2、Hutool、Apache HttpClient(ezPay 已用)、RuoYi 脚手架(BaseController/AjaxResult/TableDataInfo/MessageUtils)。
Storage: MySQL(新增 pos_store_newebpay、pos_order_payment 两表;pos_order 不改结构,payType 取值扩展)。
Testing: NewebPayEncryptUtil.main 加解密/签名自测(用 NDNF §4.1 官方示例数据)+ 蓝新测试环境 ccore 端到端验证(见 quickstart.md,测试卡号见 NDNF 附录1)。
Target Platform: Linux server(Tomcat 8082,公网可达 80/443 供蓝新回调)。
Project Type: web-service(Spring Boot REST,多模块 Maven:ruoyi-admin / ruoyi-system / ruoyi-framework / ruoyi-common)。
Performance Goals: 99% 支付回调在蓝新发出后 10s 内处理(SC-004);发起支付接口 p95 < 1s。
Constraints: NotifyURL/ReturnURL 必须公网 80/443 可达;回调必须幂等(按 TradeNo);必须验签 + 金额校验,异常回调误更新率 0%(SC-003);HashKey/HashIV 不得下发前端(加密仅在后端)。
Scale/Scope: 全平台门店可开通;面向 C 端用户下单(外卖/自取/堂食扫码点餐);商家端/平台后台用于凭证管理与对账查询。
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
N/A — .specify/memory/constitution.md 仍为模板占位([PRINCIPLE_1_NAME] 等),未填写项目具体准则,无实质 gate 可校验。无违反项。
specs/011-newebpay-payment/
├── spec.md # 需求规格 (/speckit-specify)
├── plan.md # 本文件 (/speckit-plan)
├── research.md # 技术决策 (/speckit-plan Phase 0)
├── data-model.md # 数据模型 (/speckit-plan Phase 1)
├── quickstart.md # 端到端验证指南 (/speckit-plan Phase 1)
├── contracts/
│ └── api.md # 接口契约 (/speckit-plan Phase 1)
└── tasks.md # 任务分解 (/speckit-tasks,下一步生成)
ruoyi-admin/src/main/java/com/ruoyi/app/
├── utils/newebpay/
│ ├── NewebPay.java # 蓝新 HTTP 客户端(MPG/Query),仿 EzPay
│ ├── NewebPayConfig.java # merchantId/hashKey/hashIV,仿 EzPayConfig
│ └── NewebPayEncryptUtil.java # AES-256-CBC/PKCS7 + SHA256(TradeSha/CheckValue/CheckCode)
├── pay/
│ └── NewebpayPayController.java # /pay/newebpay/{create,notify,return,query}(notify/return @Anonymous)
└── mendian/
└── PosStoreNewebpayController.java # /system/storeNewebpay/* 门店凭证管理(@PreAuthorize)
ruoyi-system/src/main/java/com/ruoyi/system/
├── domain/
│ ├── PosStoreNewebpay.java # 门店蓝新凭证实体(@TableName pos_store_newebpay)
│ ├── PosOrderPayment.java # 支付流水实体(@TableName pos_order_payment)
│ ├── vo/PosStoreNewebpayVo.java # 凭证列表/详情 VO
│ └── dto/StoreNewebpayCredentialDto.java # 录入凭证 DTO
├── mapper/
│ ├── PosStoreNewebpayMapper.java + PosOrderPaymentMapper.java
├── service/
│ ├── IPosStoreNewebpayService + Impl # 纯 DB(状态机/CRUD),仿 PosStoreEzpayServiceImpl
│ └── IPosOrderPaymentService + Impl # 流水写入/幂等查询
ruoyi-system/src/main/resources/mapper/chanting/
├── PosStoreNewebpayMapper.xml # 仿 PosStoreEzpayMapper.xml
└── PosOrderPaymentMapper.xml
ruoyi-admin/src/main/resources/
└── application.yml # 新增 newebpay 段(base-url/notify-url/return-url/mpg-version)
updatesql/
└── sql.md # 追加两段建表 DDL(pos_store_newebpay、pos_order_payment)
前端(CRLF 文件,用 Python 脚本编辑,按项目规范):
E:\QtwCode\foodie\foodie-store\ # C 端发起支付入口、支付结果页、四语 i18n
E:\QtwCode\foodie\foodie-admin-vue\ # 平台后台门店蓝新凭证管理页 + 四语 i18n
Structure Decision: 严格遵循现有分层——加密/HTTP 客户端/Controller 在 ruoyi-admin,Domain/Mapper/Service 在 ruoyi-system(Service 纯 DB,联网验证在 Controller 层以避免反向依赖)。蓝新支付链路与发票(009/010)并列共存、互不干扰,复用 ezPay 的工具类组织形式与 PosStoreEzpay 的开通管理模式,但不共享表/凭证。
无 Constitution Check 违反项,本表无需填写。
| Violation | Why Needed | Simpler Alternative Rejected Because |
|---|---|---|
| — | — | — |
设计完成(research/data-model/contracts/quickstart 已产出)。constitution.md 仍为占位,无 gate 可复核;设计未引入与项目既有模式冲突的结构(全部对齐 ezPay/PosStoreEzpay/PayController.payipn 既有范式)。通过。