docs(changelog): #8708 二期未支付订单自动取消时刻由创建后 2h 恢复为 24h,接口契约不变
changelog-filename-gate / validate (push) Failing after 1s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot
2026-10-02 18:08:31 +08:00
共同撰写人 Claude Opus 5.5
父节点 27ba364e60
当前提交 5442f80523
@@ -0,0 +1,98 @@
---
schema: "hl-changelog/v2"
ticket: "8708"
title: "二期未支付订单自动取消时刻由创建后 2h 恢复为 24h,接口契约不变"
consumer: "multiple"
author: "wx(GIT)"
change_type: "修复"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "接口路径、入参、出参、错误码均不变;变化的只是二期待支付订单被系统自动取消的时刻:由创建后约 2h 恢复为创建后 24h,与已展示的支付截止时刻 expiryTime 一致。"
updated_at: "2026-10-02"
base: "dev-v3"
---
# 二期订单:未支付订单自动取消时刻恢复为创建后 24h
> **服务**: hl-order-service-v3(取消判定与扫描任务)、hl-user-service(定时任务调度)
> **关联 Issue**: #8708
> **关联 PR**: #8729(合并提交 89c87fd217)
> **部署状态**: 测试环境已部署并实测,见「五、实测验证」
> **影响范围**: 小程序订单详情/列表与发起支付、管理后台订单详情与线下收款登记——只影响订单何时被自动取消,不改任何字段
---
## ⚠️ 关键变化
**改前**:二期订单对外展示的支付截止时刻是创建后 24h(`expiryTime = 创建时刻 + expiryMinutes`,`expiryMinutes` 为 1440),但系统在创建后约 2h 就把未支付订单自动取消。2~24h 之间,客户看到的截止时刻还没到,订单却已是 CANCELLED:小程序无法再发起支付,管理后台也无法登记线下收款。
**改后**:系统按同一个截止时刻取消。`创建时刻 + expiryMinutes` 到达后,在下一次每分钟扫描中取消,取消原因为「订单超时未支付,系统自动取消」。
---
## 一、背景
**根因**:自动取消原来只靠 RocketMQ 延迟消息触发。RocketMQ 4.x 延迟消息最长 2h,24h 窗口的过期消息实际在约 2h 后投递并取消订单;测试服 SYSTEM_AUTO_CANCEL 记录的延迟全部是 120 分钟。
**后果**(二期尚未上生产,影响面限于测试服数据):
- 客户在创建后 2~24h 之间无法支付;
- 取消会连带房务释放:测试服有 8 单取消后配房被软删并回补库存;
- 客户在取消前发起、取消后才到账的款落入 `CANCELLED_PAID`,需要人工退款。
---
## 二、后端改动
- 窗口 ≤ 120 分钟的订单仍由延迟消息触发取消;消费延迟消息时增加到期判定,截止时刻未到不取消。
- 新增每分钟一次的扫描任务:order-v3 `OrderExpiryJob`,由 user-service 定时任务经内部接口 `POST /v3/internal/jobs/order-expiry/run` 触发,按「创建时刻 + expiryMinutes ≤ 当前时刻」取消。窗口超过 120 分钟的订单靠它取消;延迟消息丢失时,它也是兜底。
- 该内部接口经网关访问一律返回 403,前端不可调用,也无需调用。
- 到期判定与小程序展示的 `expiryTime` 共用同一个计算(`OrderPayWindow`):展示的截止时刻就是系统取消的依据。
---
## 三、对前端的影响
**前端无需改动。** 接口路径、入参、出参、错误码均不变。
### 可观察到的行为变化
| 端 | 接口 | 改前 | 改后 |
|---|---|---|---|
| 小程序 | 订单详情、订单列表(order-v3 内部端点 `GET /v3/internal/mp/order/{orderId}`、`GET /v3/internal/mp/order/list`,经小程序服务转发) | 创建约 2h 后订单变为 CANCELLED,`expiryTime` 不再返回 | 截止时刻到达前订单保持 PENDING_PAY,`expiryTime` 持续返回 |
| 小程序 | 发起支付(order-v3 内部端点 `POST /v3/internal/mp/order/{orderId}/payment/unified-order`,经小程序服务转发) | 2~24h 之间订单已取消,返回 520104「订单当前状态不允许支付」 | 截止时刻到达前可正常发起支付 |
| 管理后台 | `GET /v3/admin/order/{id}` | 创建约 2h 后为 CANCELLED | 截止时刻到达前为 PENDING_PAY |
| 管理后台 | `POST /v3/admin/order/{orderId}/payment/manual-receipt` | 2~24h 之间订单已取消,无法登记 | 截止时刻到达前可正常登记;登记后订单离开待支付,不再被自动取消 |
### 字段口径(均未变化)
- 小程序详情/列表的 `expiryTime`:仅订单为 PENDING_PAY 时返回,值为 `创建时刻 + expiryMinutes`(`expiryMinutes` 为空时按 1440 计);其他状态返回 null。
- 管理后台创单响应的 `expiryMinutes`:仍为 1440。
---
## 四、覆盖范围与边界
- 范围:二期 order-v3 的待支付订单。一期 v2 订单不受影响。
- 已支付或已登记线下收款的订单离开待支付,不会被自动取消。
- 撤销线下收款后回到待支付的订单,系统不自动取消,需人工处理(与改前一致)。
- 取消时刻:截止时刻之后的下一次每分钟扫描,按设计在截止时刻后 2 分钟内。
- 按产品配置不同支付窗口,不在本次范围。
---
## 五、实测验证(测试环境)
- **部署后存量**:创建早于部署时刻 24h 以上、仍待支付的订单经扫描全部取消(剔除撤销收款后回到待支付的单,计数为 0)。阳性对照单部署前为超期待支付,部署后转为 CANCELLED,状态日志新增一条 SYSTEM_AUTO_CANCEL 记录。
- **新建订单**:管理后台新建两张核心订单,创建后 132 分钟两单仍为 PENDING_PAY(改前此时已被取消)。对其中一张登记线下收款,返回 code 200,订单转为已付定金,状态日志中没有自动取消记录。
---
## 关联
- 工单 #8708,PR #8729