|
|
@@ -1,547 +0,0 @@
|
|
|
-# 酒店订单支付系统开发文档
|
|
|
-
|
|
|
-> 开发时间:2026-08-17
|
|
|
-> 功能模块:酒店顾客端支付流程(Mock 模式)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 一、功能概述
|
|
|
-
|
|
|
-实现了酒店顾客端完整的支付流程,支持**先支付后接单**的业务模式。当前采用 Mock 支付模式,后续可无缝对接微信支付、支付宝小程序支付。
|
|
|
-
|
|
|
-### 核心特性
|
|
|
-
|
|
|
-- ✅ **支付前置**:订单创建后进入"待支付"状态,支付成功后才进入"待接单"
|
|
|
-- ✅ **15 分钟超时**:未支付订单自动取消,定时任务扫描处理
|
|
|
-- ✅ **并发安全**:订单号生成、菜品销量累加均解决并发问题
|
|
|
-- ✅ **支付流水**:完整的支付日志记录,支持对账
|
|
|
-- ✅ **多状态管理**:待支付(0) → 已支付/待接单(1) → 后续流程;超时取消(10)
|
|
|
-- ✅ **H5 适配**:支持微信小程序、支付宝小程序、H5、Mock 四种支付环境
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 二、数据库变更
|
|
|
-
|
|
|
-### 2.1 Flyway 迁移脚本
|
|
|
-
|
|
|
-**文件**:`forge-server/db/migration/V1.0.105__add_hotel_order_payment_fields.sql`
|
|
|
-
|
|
|
-> MySQL 8.0 兼容:使用 `information_schema` + `PREPARE/EXECUTE` 模式替代 MariaDB 专有的 `IF NOT EXISTS` 扩展语法。
|
|
|
-
|
|
|
-#### hotel_order 表新增字段
|
|
|
-
|
|
|
-```sql
|
|
|
-pay_status TINYINT -- 支付状态:0=待支付, 1=已支付, 2=已退款, 3=支付超时已取消
|
|
|
-pay_expire_time DATETIME -- 支付截止时间
|
|
|
-pay_time DATETIME -- 实际支付时间
|
|
|
-pay_trade_no VARCHAR(128) -- 第三方支付交易号
|
|
|
-paid_amount DECIMAL(10,2) -- 实付金额
|
|
|
-pay_source VARCHAR(32) -- 支付来源:WECHAT/ALIPAY/H5/MOCK
|
|
|
-```
|
|
|
-
|
|
|
-#### 清理遗留字段
|
|
|
-
|
|
|
-- `pay_method`:V1.0.104 创建但实体已移除,迁移脚本自动 DROP COLUMN
|
|
|
-
|
|
|
-#### 新增索引
|
|
|
-
|
|
|
-- `idx_pay_expire`:加速支付超时订单扫描(`pay_status`, `pay_expire_time`)
|
|
|
-- `uk_order_no`:已在 V1.0.104 中创建,不重复
|
|
|
-
|
|
|
-#### hotel_pay_log 表
|
|
|
-
|
|
|
-记录每笔支付的完整流水,包括:
|
|
|
-- 订单关联(order_id, order_no)
|
|
|
-- 支付渠道(pay_channel: WECHAT/ALIPAY/MOCK)
|
|
|
-- 支付来源(pay_source: WECHAT/ALIPAY/H5/WECHAT_MP/ALIPAY_MP/MOCK)
|
|
|
-- 交易流水号(out_trade_no: 商户生成,trade_no: 第三方返回)
|
|
|
-- 支付金额、状态、时间等
|
|
|
-
|
|
|
-#### 字典数据
|
|
|
-
|
|
|
-新增字典类型:
|
|
|
-- `hotel_pay_status`:支付状态(0=待支付, 1=已支付, 2=已退款, 3=支付超时已取消)
|
|
|
-- `hotel_pay_source`:支付来源(WECHAT/ALIPAY/H5/MOCK 等)
|
|
|
-- `hotel_order_status`:补充 0=待支付、10=超时取消
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 三、后端变更
|
|
|
-
|
|
|
-### 3.1 常量定义
|
|
|
-
|
|
|
-**文件**:`HotelOrderConstants.java`
|
|
|
-
|
|
|
-```java
|
|
|
-// 订单状态
|
|
|
-STATUS_PENDING_PAY = 0 // 待支付(新增)
|
|
|
-STATUS_PLACED = 1 // 待接单(已支付)
|
|
|
-STATUS_PAY_TIMEOUT = 10 // 超时取消(新增)
|
|
|
-
|
|
|
-// 支付状态
|
|
|
-PAY_STATUS_PENDING = 0 // 待支付
|
|
|
-PAY_STATUS_SUCCESS = 1 // 已支付
|
|
|
-PAY_STATUS_TIMEOUT = 2 // 支付超时
|
|
|
-
|
|
|
-// 支付来源
|
|
|
-PAY_SOURCE_WECHAT = "WECHAT"
|
|
|
-PAY_SOURCE_ALIPAY = "ALIPAY"
|
|
|
-PAY_SOURCE_H5 = "H5"
|
|
|
-PAY_SOURCE_MOCK = "MOCK"
|
|
|
-
|
|
|
-// 超时配置
|
|
|
-PAY_TIMEOUT_MINUTES = 15 // 支付超时时间(分钟)
|
|
|
-```
|
|
|
-
|
|
|
-### 3.2 实体类
|
|
|
-
|
|
|
-#### HotelOrder.java
|
|
|
-
|
|
|
-新增字段:
|
|
|
-- `payStatus`(Integer):支付状态
|
|
|
-- `payExpireTime`(LocalDateTime):支付截止时间
|
|
|
-- `payTime`(LocalDateTime):实际支付时间
|
|
|
-- `payTradeNo`(String):支付交易号
|
|
|
-- `paidAmount`(BigDecimal):实付金额
|
|
|
-- `paySource`(String):支付来源
|
|
|
-
|
|
|
-移除字段:
|
|
|
-- `payMethod`(已废弃,改用 paySource)
|
|
|
-
|
|
|
-#### HotelPayLog.java(新建)
|
|
|
-
|
|
|
-支付流水实体,包含完整的支付记录字段。
|
|
|
-
|
|
|
-### 3.3 Mapper 层
|
|
|
-
|
|
|
-#### HotelOrderMapper.java
|
|
|
-
|
|
|
-新增方法:
|
|
|
-```java
|
|
|
-List<Long> selectExpiredUnpaidOrderIds()
|
|
|
-```
|
|
|
-查询所有超时未支付的订单 ID。
|
|
|
-
|
|
|
-#### HotelOrderMapper.xml
|
|
|
-
|
|
|
-- `resultMap` 和 `OrderColumns`:添加支付相关字段映射
|
|
|
-- `selectDashboard`、`countTodayOrders`、`sumTodayRevenue`:改为只统计已支付订单(`pay_status = 1`)
|
|
|
-- `selectOrderPage`:筛选条件从 `payMethod` 改为 `payStatus`、`paySource`
|
|
|
-- 新增 `selectExpiredUnpaidOrderIds`:查询超时订单
|
|
|
-
|
|
|
-#### HotelDishMapper.java
|
|
|
-
|
|
|
-新增方法:
|
|
|
-```java
|
|
|
-int incrementSales(@Param("dishId") Long dishId, @Param("quantity") Integer quantity)
|
|
|
-```
|
|
|
-原子更新菜品销量。
|
|
|
-
|
|
|
-#### HotelDishMapper.xml
|
|
|
-
|
|
|
-新增 SQL:
|
|
|
-```xml
|
|
|
-<update id="incrementSales">
|
|
|
- UPDATE hotel_dish
|
|
|
- SET sales = IFNULL(sales, 0) + #{quantity},
|
|
|
- update_time = NOW()
|
|
|
- WHERE id = #{dishId} AND del_flag = 0
|
|
|
-</update>
|
|
|
-```
|
|
|
-
|
|
|
-#### HotelPayLogMapper.java(新建)
|
|
|
-
|
|
|
-```java
|
|
|
-HotelPayLog selectByOutTradeNo(@Param("outTradeNo") String outTradeNo)
|
|
|
-```
|
|
|
-根据商户订单号查询支付流水。
|
|
|
-
|
|
|
-### 3.4 Service 层
|
|
|
-
|
|
|
-#### HotelOrderServiceImpl.java
|
|
|
-
|
|
|
-**orderCreate() 方法重构**:
|
|
|
-- 订单创建后状态设为 `STATUS_PENDING_PAY`(待支付)
|
|
|
-- 设置 `payStatus = PAY_STATUS_PENDING`
|
|
|
-- 设置 `payExpireTime = now + 15 分钟`
|
|
|
-- 移除 `payMethod` 字段赋值
|
|
|
-
|
|
|
-**generateOrderNo() 并发修复**:
|
|
|
-- 添加 3 次重试机制
|
|
|
-- 每次重试前检查唯一性(`selectCount`)
|
|
|
-- 防御性唯一性检查:插入前再次验证订单号是否已存在
|
|
|
-
|
|
|
-**incrementDishSales() 并发修复**:
|
|
|
-- 从"先查后写"改为原子 SQL 更新
|
|
|
-- 调用 `dishMapper.incrementSales()` 直接执行 `SET sales = IFNULL(sales, 0) + #{quantity}`
|
|
|
-
|
|
|
-**customerRefund() 新增逻辑**:
|
|
|
-- 待支付订单(status=0):直接取消,状态改为 `STATUS_PAY_TIMEOUT`
|
|
|
-- 已支付订单(status=1):进入退单流程
|
|
|
-
|
|
|
-#### HotelPayService.java(新建)
|
|
|
-
|
|
|
-支付服务接口,定义核心方法:
|
|
|
-```java
|
|
|
-Map<String, Object> createPay(Long orderId, String paySource)
|
|
|
-PayResultVO mockPaySuccess(Long orderId)
|
|
|
-void handlePayCallback(String outTradeNo, String tradeNo, boolean success, String rawContent)
|
|
|
-PayResultVO queryPayStatus(Long orderId)
|
|
|
-void cancelTimeoutOrder(Long orderId)
|
|
|
-```
|
|
|
-
|
|
|
-#### HotelPayServiceImpl.java(新建)
|
|
|
-
|
|
|
-**createPay()**:
|
|
|
-- 校验订单状态(必须为待支付)
|
|
|
-- 检查是否已过期
|
|
|
-- 生成商户订单号(`PAY + 时间戳 + 订单ID后6位`)
|
|
|
-- 创建支付流水(`hotel_pay_log`)
|
|
|
-- 返回支付参数(Mock 模式返回简化参数)
|
|
|
-
|
|
|
-**mockPaySuccess()**:
|
|
|
-- 模拟支付成功流程
|
|
|
-- 创建 Mock 支付流水(如果不存在)
|
|
|
-- 触发支付回调处理
|
|
|
-
|
|
|
-**handlePayCallback()**:
|
|
|
-- 幂等校验:已处理的订单直接返回
|
|
|
-- 支付成功:更新流水状态、更新订单状态(0→1)、记录支付时间和交易号
|
|
|
-- 支付失败:更新流水状态为失败
|
|
|
-
|
|
|
-**cancelTimeoutOrder()**:
|
|
|
-- 更新订单状态为 `STATUS_PAY_TIMEOUT`
|
|
|
-- 更新支付状态为 `PAY_STATUS_TIMEOUT`
|
|
|
-
|
|
|
-**queryPayStatus()**:
|
|
|
-- 返回订单支付状态、金额、时间等信息
|
|
|
-
|
|
|
-### 3.5 Controller 层
|
|
|
-
|
|
|
-#### HotelPayController.java(新建)
|
|
|
-
|
|
|
-路径:`/hotel/open/pay/**`(免登录,已在 SaToken 白名单中)
|
|
|
-
|
|
|
-接口列表:
|
|
|
-```
|
|
|
-POST /create 发起支付(创建支付流水)
|
|
|
-POST /mockSuccess 模拟支付成功(开发阶段)
|
|
|
-GET /status 查询支付状态(前端轮询)
|
|
|
-POST /notify 支付回调通知(微信/支付宝异步通知入口,Mock 占位)
|
|
|
-```
|
|
|
-
|
|
|
-所有接口都需要传入 `tenantId` 参数,通过 `TenantContextHolder.executeWithTenant()` 在指定租户上下文中执行。
|
|
|
-
|
|
|
-### 3.6 定时任务
|
|
|
-
|
|
|
-#### PayTimeoutTask.java(新建)
|
|
|
-
|
|
|
-```java
|
|
|
-@Scheduled(fixedDelay = 120000, initialDelay = 30000)
|
|
|
-public void cancelExpiredOrders()
|
|
|
-```
|
|
|
-
|
|
|
-- 每 2 分钟执行一次(启动后 30 秒开始)
|
|
|
-- 使用 `TenantContextHolder.executeIgnore()` 跨租户扫描
|
|
|
-- 查询所有超时未支付的订单 ID
|
|
|
-- 逐条调用 `payService.cancelTimeoutOrder()` 取消
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 四、前端变更(H5)
|
|
|
-
|
|
|
-### 4.1 API 层
|
|
|
-
|
|
|
-**文件**:`forge-h5-ui/src/api/index.js`
|
|
|
-
|
|
|
-新增支付相关 API:
|
|
|
-```javascript
|
|
|
-hotelPayCreate: (data) => request.post('/hotel/open/pay/create', data)
|
|
|
-hotelPayMockSuccess: (data) => request.post('/hotel/open/pay/mockSuccess', data)
|
|
|
-hotelPayStatus: (params) => request.get('/hotel/open/pay/status', { params })
|
|
|
-```
|
|
|
-
|
|
|
-### 4.2 支付页面
|
|
|
-
|
|
|
-**文件**:`forge-h5-ui/src/pages/hotel/customer/pay.vue`
|
|
|
-
|
|
|
-**核心功能**:
|
|
|
-- **15 分钟倒计时**:显示剩余时间(分:秒),超时自动跳转
|
|
|
-- **环境自动识别**:
|
|
|
- - 微信小程序:`wx.miniProgram.getPhoneNumber()`
|
|
|
- - 支付宝小程序:`my.tradePay()`
|
|
|
- - H5:跳转第三方支付页面
|
|
|
- - Mock:直接调用模拟支付接口
|
|
|
-- **支付流程**:
|
|
|
- 1. 调用 `hotelPayCreate` 创建支付流水
|
|
|
- 2. 根据环境调用对应支付方法(Mock 直接调用 `hotelPayMockSuccess`)
|
|
|
- 3. 支付成功后跳转到订单状态页
|
|
|
-
|
|
|
-**UI 元素**:
|
|
|
-- 订单信息展示(订单号、金额、房间号)
|
|
|
-- 倒计时显示(红色高亮)
|
|
|
-- 支付方式选择(当前仅 Mock)
|
|
|
-- 支付按钮(根据环境显示不同文案)
|
|
|
-
|
|
|
-### 4.3 订单状态页
|
|
|
-
|
|
|
-**文件**:`forge-h5-ui/src/pages/hotel/customer/order-status.vue`
|
|
|
-
|
|
|
-新增状态处理:
|
|
|
-- **状态 0(待支付)**:
|
|
|
- - 图标:💳
|
|
|
- - 文案:"等待支付"
|
|
|
- - 提示:"请在 15 分钟内完成支付"
|
|
|
- - 按钮:"去支付"(跳转到支付页)
|
|
|
-- **状态 10(超时取消)**:
|
|
|
- - 图标:⏰
|
|
|
- - 文案:"支付超时,订单已取消"
|
|
|
- - 提示:"您可以重新下单"
|
|
|
- - `isFinished()` 返回 true(订单结束)
|
|
|
-
|
|
|
-### 4.4 订单列表页
|
|
|
-
|
|
|
-**文件**:`forge-h5-ui/src/pages/hotel/customer/orders.vue`
|
|
|
-
|
|
|
-**状态标签更新**:
|
|
|
-```javascript
|
|
|
-statusLabel(status) {
|
|
|
- const map = {
|
|
|
- 0: '待支付', 1: '待接单', 2: '已接单', 3: '备餐中',
|
|
|
- 4: '已出餐', 5: '配送中', 6: '已完成',
|
|
|
- 7: '已拒单', 8: '退单审核中', 9: '已退单',
|
|
|
- 10: '超时取消',
|
|
|
- }
|
|
|
- return map[status] || '未知'
|
|
|
-}
|
|
|
-```
|
|
|
-
|
|
|
-**状态颜色**:
|
|
|
-- `.o-st--0`:黄色背景(待支付)
|
|
|
-- `.o-st--10`:灰色背景(超时取消)
|
|
|
-
|
|
|
-**待支付订单特殊处理**:
|
|
|
-- 显示"去支付"按钮
|
|
|
-- 点击卡片跳转到支付页(而非订单状态页)
|
|
|
-
|
|
|
-### 4.5 订单确认页
|
|
|
-
|
|
|
-**文件**:`forge-h5-ui/src/pages/hotel/customer/order-confirm.vue`
|
|
|
-
|
|
|
-更新跳转逻辑:
|
|
|
-- 下单成功后跳转到支付页(而非订单状态页)
|
|
|
-- 传递参数:`orderId`、`tenantId`、`amount`
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 五、并发问题修复
|
|
|
-
|
|
|
-### 5.1 订单号并发
|
|
|
-
|
|
|
-**问题**:多个订单同时生成可能产生重复订单号
|
|
|
-
|
|
|
-**解决方案**:
|
|
|
-1. 数据库层面:`order_no` 添加唯一索引
|
|
|
-2. 代码层面:`generateOrderNo()` 添加 3 次重试
|
|
|
-3. 防御性检查:插入前 `selectCount` 验证唯一性
|
|
|
-
|
|
|
-### 5.2 菜品销量并发
|
|
|
-
|
|
|
-**问题**:先查后写导致并发时销量丢失
|
|
|
-
|
|
|
-**解决方案**:
|
|
|
-- 使用原子 SQL 更新:`SET sales = IFNULL(sales, 0) + #{quantity}`
|
|
|
-- 避免"读取-计算-写入"的竞态条件
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 六、支付流程时序图
|
|
|
-
|
|
|
-```
|
|
|
-顾客 H5前端 后端API 数据库
|
|
|
- | | | |
|
|
|
- |--下单----------->| | |
|
|
|
- | |--创建订单-------->| |
|
|
|
- | | |--插入订单(status=0)|
|
|
|
- | | |<-------------------|
|
|
|
- | |<--返回orderId-----| |
|
|
|
- | | | |
|
|
|
- |--跳转支付页----->| | |
|
|
|
- | |--创建支付-------->| |
|
|
|
- | | |--插入pay_log |
|
|
|
- | | |<-------------------|
|
|
|
- | |<--返回支付参数----| |
|
|
|
- | | | |
|
|
|
- |--点击支付------->| | |
|
|
|
- | |--模拟支付成功---->| |
|
|
|
- | | |--更新pay_log |
|
|
|
- | | |--更新订单(status=1)|
|
|
|
- | | |<-------------------|
|
|
|
- | |<--返回支付结果----| |
|
|
|
- | | | |
|
|
|
- |--跳转订单状态--->| | |
|
|
|
- | |--轮询支付状态---->| |
|
|
|
- | | |--查询订单 |
|
|
|
- | | |<-------------------|
|
|
|
- | |<--返回已支付------| |
|
|
|
- | | | |
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 七、后续对接真实支付
|
|
|
-
|
|
|
-### 7.1 微信支付(小程序)
|
|
|
-
|
|
|
-1. 在 `HotelPayServiceImpl.createPay()` 中调用微信统一下单接口
|
|
|
-2. 返回微信支付所需参数(prepay_id、sign 等)
|
|
|
-3. 前端 `pay.vue` 中调用 `wx.requestPayment()`
|
|
|
-4. 微信异步通知 `/hotel/open/pay/notify`
|
|
|
-5. 验签、解密、更新订单状态
|
|
|
-
|
|
|
-### 7.2 支付宝支付(小程序)
|
|
|
-
|
|
|
-1. 在 `HotelPayServiceImpl.createPay()` 中调用支付宝订单创建接口
|
|
|
-2. 返回支付宝所需参数(trade_no 等)
|
|
|
-3. 前端 `pay.vue` 中调用 `my.tradePay()`
|
|
|
-4. 支付宝异步通知 `/hotel/open/pay/notify`
|
|
|
-5. 验签、更新订单状态
|
|
|
-
|
|
|
-### 7.3 配置项
|
|
|
-
|
|
|
-需要在 `application.yml` 中添加:
|
|
|
-```yaml
|
|
|
-forge:
|
|
|
- pay:
|
|
|
- wechat:
|
|
|
- appId: xxx
|
|
|
- mchId: xxx
|
|
|
- apiKey: xxx
|
|
|
- alipay:
|
|
|
- appId: xxx
|
|
|
- privateKey: xxx
|
|
|
- alipayPublicKey: xxx
|
|
|
-```
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 八、文件清单
|
|
|
-
|
|
|
-### 后端新增文件
|
|
|
-
|
|
|
-1. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/pay/domain/HotelPayLog.java`
|
|
|
-2. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/pay/mapper/HotelPayLogMapper.java`
|
|
|
-3. `forge-server/forge-business/forge-hotel/src/main/resources/mapper/business/hotel/pay/HotelPayLogMapper.xml`
|
|
|
-4. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/pay/service/HotelPayService.java`
|
|
|
-5. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/pay/service/impl/HotelPayServiceImpl.java`
|
|
|
-6. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/pay/vo/PayResultVO.java`
|
|
|
-7. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/controller/open/HotelPayController.java`
|
|
|
-8. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/pay/task/PayTimeoutTask.java`
|
|
|
-
|
|
|
-### 后端修改文件
|
|
|
-
|
|
|
-1. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/order/constant/HotelOrderConstants.java`
|
|
|
-2. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/order/domain/HotelOrder.java`
|
|
|
-3. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/order/mapper/HotelOrderMapper.java`
|
|
|
-4. `forge-server/forge-business/forge-hotel/src/main/resources/mapper/business/hotel/order/HotelOrderMapper.xml`
|
|
|
-5. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/mapper/HotelDishMapper.java`
|
|
|
-6. `forge-server/forge-business/forge-hotel/src/main/resources/mapper/business/hotel/HotelDishMapper.xml`
|
|
|
-7. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/order/service/impl/HotelOrderServiceImpl.java`
|
|
|
-8. `forge-server/forge-business/forge-hotel/src/main/java/com/mdframe/forge/business/core/hotel/order/vo/HotelOrderVO.java`
|
|
|
-
|
|
|
-### 数据库脚本
|
|
|
-
|
|
|
-1. `forge-server/db/migration/V1.0.105__add_hotel_order_payment_fields.sql`
|
|
|
-
|
|
|
-### 前端新增文件
|
|
|
-
|
|
|
-无
|
|
|
-
|
|
|
-### 前端修改文件
|
|
|
-
|
|
|
-1. `forge-h5-ui/src/api/index.js`
|
|
|
-2. `forge-h5-ui/src/pages/hotel/customer/pay.vue`
|
|
|
-3. `forge-h5-ui/src/pages/hotel/customer/order-status.vue`
|
|
|
-4. `forge-h5-ui/src/pages/hotel/customer/orders.vue`
|
|
|
-5. `forge-h5-ui/src/pages/hotel/customer/order-confirm.vue`
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 九、测试建议
|
|
|
-
|
|
|
-### 9.1 功能测试
|
|
|
-
|
|
|
-1. **正常支付流程**:
|
|
|
- - 下单 → 跳转支付页 → 点击支付 → 支付成功 → 订单状态变为"待接单"
|
|
|
-
|
|
|
-2. **超时取消**:
|
|
|
- - 下单 → 等待 15 分钟 → 订单自动取消 → 状态变为"超时取消"
|
|
|
-
|
|
|
-3. **主动取消**:
|
|
|
- - 下单 → 在支付页点击"取消订单" → 订单状态变为"超时取消"
|
|
|
-
|
|
|
-4. **重复支付防护**:
|
|
|
- - 已支付订单再次调用支付接口 → 返回"订单已支付"错误
|
|
|
-
|
|
|
-### 9.2 并发测试
|
|
|
-
|
|
|
-1. **订单号唯一性**:
|
|
|
- - 同时创建 100 个订单 → 验证订单号无重复
|
|
|
-
|
|
|
-2. **菜品销量准确性**:
|
|
|
- - 同时完成 10 个包含同一菜品的订单 → 验证销量累加正确
|
|
|
-
|
|
|
-### 9.3 边界测试
|
|
|
-
|
|
|
-1. **支付超时边界**:
|
|
|
- - 在第 14 分 59 秒支付 → 应该成功
|
|
|
- - 在第 15 分 01 秒支付 → 应该返回"订单已超时"
|
|
|
-
|
|
|
-2. **库存不足**:
|
|
|
- - 下单时菜品库存不足 → 应该返回错误
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 十、已知问题与优化建议
|
|
|
-
|
|
|
-### 10.1 已知问题
|
|
|
-
|
|
|
-1. **Mock 模式安全性**:
|
|
|
- - 当前 Mock 支付接口无需鉴权,生产环境需要移除或限制访问
|
|
|
-
|
|
|
-2. **定时任务精度**:
|
|
|
- - 数据库轮询方案最大延迟 2 分钟,对业务影响可接受
|
|
|
-
|
|
|
-### 10.2 优化建议
|
|
|
-
|
|
|
-1. **支付回调重试**:
|
|
|
- - 添加重试机制,防止网络问题导致回调失败
|
|
|
-
|
|
|
-2. **支付对账**:
|
|
|
- - 添加每日对账任务,比对本地流水与第三方支付平台数据
|
|
|
-
|
|
|
-3. **支付统计**:
|
|
|
- - 添加支付成功率、支付金额等统计报表
|
|
|
-
|
|
|
-4. **退款流程**:
|
|
|
- - 完善已支付订单的退款流程(当前只支持未支付取消)
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-## 十一、总结
|
|
|
-
|
|
|
-本次开发完成了酒店订单支付系统的核心功能,包括:
|
|
|
-
|
|
|
-- ✅ 数据库结构设计(支付字段、流水表、索引)
|
|
|
-- ✅ 后端支付服务(Mock 模式、回调处理、超时取消)
|
|
|
-- ✅ 前端支付页面(倒计时、环境识别、支付调用)
|
|
|
-- ✅ 并发问题修复(订单号、菜品销量)
|
|
|
-- ✅ 订单状态管理(待支付、已支付、超时取消)
|
|
|
-
|
|
|
-当前系统已支持完整的 Mock 支付流程,后续可无缝对接微信支付、支付宝小程序支付。所有代码已通过编译验证,无语法错误。
|
|
|
-
|
|
|
----
|
|
|
-
|
|
|
-**文档版本**:v1.0
|
|
|
-**最后更新**:2026-08-17
|
|
|
-**维护人员**:AI Assistant
|