GogoAI无人健身系统开发,异常订单处理机制设计

痛点分析

无人健身系统的订单链路包含下单、支付回调、发卡、权益发放、套餐实例化多个环节。网络抖动、微信支付回调丢失、MQ消息消费失败、数据库锁竞争、库存不足等场景,很容易产生异常订单:用户已经扣款,但是会员卡没有生成;订单状态一直处于支付中;重复回调导致多次发卡、重复扣库存。

如果缺少统一的异常订单处理机制,只能人工核对账单,客服手动补发卡片或者退款,效率低还容易引发客诉。很多方案只依赖定时任务扫描,缺少状态机管控,订单状态流转混乱;退款、权益回滚逻辑分散在各个业务分支,财务对账时订单和资金流水对不上,资损风险高。

GogoAI无人健身系统引入订单状态机+幂等+补偿任务+人工复核的整套异常处理机制,统一管理购卡、套餐、时段计费类订单,保证资金、权益、库存最终一致性。

整体设计思路

后端基于Spring Boot、RabbitMQ、Redis实现,采用状态机驱动订单流转,所有订单的状态变更都走状态机校验,不允许随意修改状态。订单分为预下单、待支付、已支付、权益发放成功、已取消、已退款、异常待补偿、人工复核。

模块分为订单状态引擎、支付回调处理、异步补偿队列、定时扫描任务、人工复核工作台。每一笔订单分配唯一orderNo作为幂等标识,支付流水号、业务事件ID都和订单号绑定。

核心数据表:order_main订单主表、order_item订单明细表、order_log订单流转日志表、order_compensate补偿任务表。补偿任务独立建表,记录补偿类型、重试次数、下一次执行时间、参数快照,避免补偿逻辑和订单业务耦合。

订单状态机核心代码实现

使用状态机控制流转,非法状态变更直接拦截,同时记录流转日志。

@Service
@Slf4j
public class OrderStateMachineService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderLogMapper orderLogMapper;

    /**
     * 订单状态流转
     * @param orderNo 订单编号
     * @param event 事件:PAY_SUCCESS、ISSUE_CARD、REFUND、CANCEL、COMPENSATE
     * @return 流转结果
     */
    public ResultDTO<OrderVO> transition(String orderNo, OrderEvent event) {
        OrderMain order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            return ResultDTO.fail("订单不存在");
        }
        OrderStatus currentStatus = OrderStatus.valueOf(order.getStatus());
        // 判断当前状态是否允许该事件触发
        if (!currentStatus.canAcceptEvent(event)) {
            log.error("订单状态非法流转,orderNo:{},current:{},event:{}", orderNo, currentStatus, event);
            return ResultDTO.fail("订单状态异常,不支持当前操作");
        }
        OrderStatus nextStatus = currentStatus.getNext(event);
        order.setStatus(nextStatus.name());
        orderMapper.updateById(order);
        // 写入订单流转日志
        OrderLog logEntity = new OrderLog();
        logEntity.setOrderNo(orderNo);
        logEntity.setBeforeStatus(currentStatus.name());
        logEntity.setAfterStatus(nextStatus.name());
        logEntity.setEvent(event.name());
        logEntity.setCreateTime(new Date());
        orderLogMapper.insert(logEntity);
        return ResultDTO.success(convert(order));
    }
}

当支付成功事件到来,状态机从待支付转到已支付,然后投递MQ执行发卡;发卡成功再流转到权益发放成功;发卡失败则转入异常待补偿,生成补偿任务。

支付回调幂等与防重复处理

微信支付回调是高频异常点,同一笔订单可能多次回调。系统以支付交易号+orderNo做幂等,Redis记录已经处理过的支付流水,回调到达时先判断是否已经处理。

@Service
public class PayCallbackService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private OrderStateMachineService stateMachineService;

    public ResultDTO callback(String orderNo, String transactionId) {
        String key = "pay:callback:" + transactionId;
        Boolean exist = redisTemplate.opsForValue().setIfAbsent(key, "1", Duration.ofHours(24));
        if (Boolean.FALSE.equals(exist)) {
            log.info("支付回调重复接收,transactionId:{}", transactionId);
            return ResultDTO.success();
        }
        // 状态机流转为已支付
        ResultDTO result = stateMachineService.transition(orderNo, OrderEvent.PAY_SUCCESS);
        if (result.isSuccess()) {
            // 投递消息队列执行发卡逻辑
            rabbitTemplate.convertAndSend("order_exchange", "order.issueCard", orderNo);
        }
        return result;
    }
}

补偿任务与阶梯重试策略

发卡失败、库存扣减失败、优惠券发放失败时,不会直接抛出异常回滚订单,而是创建补偿任务存入order_compensate表,标记重试次数、补偿类型。补偿采用阶梯退避策略:1分钟、5分钟、15分钟、30分钟、1小时,达到最大重试次数后停止自动重试,流转到人工复核。

消费补偿任务时,再次执行发卡或者权益发放,执行成功后标记补偿任务完成,订单状态更新为正常;重试耗尽仍失败,订单标记人工复核,推送提醒给后台运营人员。

补偿执行前再次校验订单当前状态,防止补偿任务延迟执行,和退款、取消事件冲突,避免重复发卡。

超时自动关单机制

用户下单后长时间未支付,定时任务扫描待支付订单,超过有效期自动触发取消事件,释放套餐库存、释放优惠券占用名额,状态流转为已取消。

@Component
@Slf4j
public class OrderTimeoutTask {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderStateMachineService stateMachineService;

    @Scheduled(cron = "0 */1 * * * ?")
    public void scanTimeoutOrder() {
        List<OrderMain> timeoutList = orderMapper.selectTimeoutUnPayOrder();
        for (OrderMain order : timeoutList) {
            try {
                stateMachineService.transition(order.getOrderNo(), OrderEvent.CANCEL);
                // 释放库存、释放优惠券锁定
                stockService.releaseStock(order.getOrderNo());
                couponService.releaseLock(order.getOrderNo());
            } catch (Exception e) {
                log.error("超时关单失败 orderNo:{}", order.getOrderNo(), e);
            }
        }
    }
}

退款逆向流程与权益回滚

退款属于逆向异常场景,同样走状态机。发起退款后,先校验订单状态是否允许退款,调用支付平台退款接口,退款成功后执行权益回收:次卡扣回次数、组合套餐多张卡片统一失效,同步触发财务分账冲正。

退款失败的订单同样进入补偿队列重试,防止资金已经退回用户,但系统内权益没有回收,造成资损。所有退款流水、权益回滚记录独立留存,方便财务对账。

人工复核工作台与风险管控

自动重试无法解决的异常订单,统一汇集到人工复核页面,页面展示订单基本信息、支付流水、补偿历史、失败原因。运营人员操作分为三种:手动补偿发卡、直接退款、标记问题归档。

人工操作同样会写入订单流转审计日志,记录操作人和操作内容;高危的资金补发、退款操作增加二次验证码校验,避免误操作。

后台支持异常订单看板,统计异常率、失败原因分布,比如回调丢失、MQ消费异常、库存不足,帮助开发定位系统稳定性问题。

和上下游模块联动

订单异常机制和卡种套餐、会员账户、财务分账模块联动。补偿发卡成功后,会员自动收到小程序推送通知;订单退款冲正数据同步到财务分账引擎,营收报表自动剔除退款金额。 同时和消息推送模块联动,异常订单进入人工复核时,推送消息通知运营及时处理,减少用户等待时间。

落地效果总结

这套异常订单处理机制落地GogoAI无人健身系统后,解决了支付回调重复、发卡异步失败、订单状态混乱等问题,依靠状态机约束流转,避免脏数据。自动补偿+人工复核的模式,大部分异常不需要客服介入,降低人工成本和客诉。

所有订单流转全程留痕,资金、权益双向一致,财务对账清晰。该机制可以复用在购卡套餐订单、时段计费账单订单上,和前面的权限、安防、会员模块一起,支撑连锁自助健身房稳定运行。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐