应抛出GroupBuyExpiredException表示拼团已失效并触发退款;该异常为业务异常,继承RuntimeException,仅用于“未成团且超时”场景,不用于技术故障或用户主动取消。

拼团人数不足且超时后,应抛出 GroupBuyExpiredException 表示拼团已失效,此时需终止后续流程并触发退款。
明确异常语义与使用场景
GroupBuyExpiredException 是业务异常,不是系统级错误,应继承 RuntimeException 或自定义的业务异常基类(如 BizException),避免强制调用方处理。它专用于表达“拼团未成团且已过期”这一确定性业务状态。
- 不用于网络超时、数据库失败等技术问题
- 不用于用户主动取消拼团(应抛
GroupBuyCancelledException) - 仅在定时任务或支付回调中校验到「截止时间已过」且「当前参团人数
抛出前必须完成关键校验
不能仅凭时间判断就抛异常,需原子性确认两个条件同时成立:
- 当前时间 ≥ 拼团截止时间(建议用数据库时间或统一时间服务,避免服务器时钟偏差)
- 实时查得该拼团当前有效参团人数(含已支付未确认的订单,需排除已退款/失效参团记录)
- 参团人数
推荐在 DAO 层用一条 SQL 同时查时间和人数,或加行锁防止并发修改导致误判。
立即学习“Java免费学习笔记(深入)”;
抛出异常后需联动退款逻辑
抛出 GroupBuyExpiredException 不代表退款自动完成,而是作为「触发退款」的信号。典型处理链路如下:
- 捕获该异常的服务层立即调用退款接口(如对接支付平台的退单 API)
- 退款成功后更新订单状态为「已退款」,拼团状态设为「已过期」
- 退款失败需记录日志并进入人工干预队列,不可静默吞掉异常
- 前端展示提示:“拼团未满员,订单已自动退款”
异常信息应包含可追溯字段
构造异常时传入关键业务 ID,便于排查和对账:
- 拼团活动 ID(
groupBuyId) - 主订单号(
orderNo) - 实际参团人数与目标人数(如 “3/5”)
- 过期时间戳(
expireTime)
例如:throw new GroupBuyExpiredException("拼团过期,groupBuyId=1002, orderNo=O20240520112233, current=3/5, expire=2024-05-20T23:59:59Z");


















