智慧充电系统订单服务Java 实现方案

一、整体架构设计

技术栈

  • 框架:SpringBoot 3.x + Spring MVC + Spring Task(定时任务)
  • 存储:MySQL(订单主表 + 详情表)
  • 交互:RESTful API 接口,Feign/HTTP 调用依赖服务(充电 / 计费 / 支付)
  • 规范:面向接口编程,统一返回结果

核心模块划分

  1. 实体层:订单枚举、订单主表、订单详情表
  2. DAO 层:Mapper 数据访问
  3. Service 层:核心业务逻辑(接口 + 实现)
  4. Controller 层:对外 API 接口
  5. 定时任务:异常订单自动修复
  6. 远程调用:依赖服务接口

二、核心实体定义(Java Bean)

1. 订单状态枚举(核心业务状态)

复制代码
/**
 * 订单状态枚举
 * 待支付、充电中、已完成、已取消、异常
 */
public enum OrderStatus {
    PENDING_PAYMENT,  // 待支付
    CHARGING,         // 充电中
    COMPLETED,        // 已完成
    CANCELED,         // 已取消
    ABNORMAL          // 异常订单
}

2. 订单主表实体

复制代码
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Data
public class Order {
    private Long id;                // 主键ID
    private String orderNo;         // 订单号(唯一)
    private Long userId;            // 用户ID
    private Long deviceId;          // 设备ID(充电桩)
    private Long stationId;         // 场站ID
    private OrderStatus orderStatus;// 订单状态
    private BigDecimal totalPower;  // 总电量(度)
    private Integer chargeDuration; // 充电时长(秒)
    private BigDecimal originalPrice;// 原价
    private BigDecimal discountPrice;// 优惠价
    private BigDecimal actualPrice;  // 实付价
    private LocalDateTime createTime;// 创建时间
    private LocalDateTime updateTime;// 更新时间
    private String remark;          // 备注(异常原因)
}

3. 订单详情 DTO(接口传输对象)

复制代码
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class OrderDetailDTO {
    private String orderNo;
    private Long userId;
    private Long deviceId;
    private Long stationId;
    private OrderStatus orderStatus;
    private BigDecimal totalPower;
    private Integer chargeDuration;
    private BigDecimal originalPrice;
    private BigDecimal discountPrice;
    private BigDecimal actualPrice;
    private LocalDateTime createTime;
}

三、服务接口定义(核心业务接口)

这是订单服务对外暴露的核心接口,完全匹配你要求的:创建订单、订单状态查询、订单详情查询。

复制代码
/**
 * 订单服务核心接口
 */
public interface OrderService {

    /**
     * 1. 创建订单(充电启动时调用)
     * 业务:生成待支付订单,关联用户/设备/场站
     */
    Order createOrder(Long userId, Long deviceId, Long stationId);

    /**
     * 2. 查询订单状态
     */
    OrderStatus getOrderStatus(String orderNo);

    /**
     * 3. 查询订单详情
     */
    OrderDetailDTO getOrderDetail(String orderNo);

    /**
     * 4. 充电中更新订单数据(电量/时长)
     */
    void updateChargingData(String orderNo, BigDecimal totalPower, Integer chargeDuration);

    /**
     * 5. 充电结束,计算费用并更新订单
     */
    void finishCharge(String orderNo);

    /**
     * 6. 支付成功,完结订单
     */
    void paySuccess(String orderNo);

    /**
     * 7. 取消订单
     */
    void cancelOrder(String orderNo);

    /**
     * 8. 异常订单自动修复(定时任务调用)
     */
    void autoRepairAbnormalOrders();
}

四、接口实现类(核心业务逻辑详解)

这是最关键的业务实现,我会逐方法讲解业务含义 + 代码逻辑。

复制代码
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderMapper orderMapper;
    // 远程调用:计费服务
    private final BillingService billingService;
    // 远程调用:支付服务
    private final PaymentService paymentService;

    // ====================== 核心业务实现 ======================

    /**
     * 1. 创建订单
     * 业务场景:用户启动充电 → 充电服务调用此接口 → 生成【待支付】空订单
     * 业务规则:
     * 1. 生成唯一订单号
     * 2. 初始状态:待支付
     * 3. 初始电量/时长/金额为0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order createOrder(Long userId, Long deviceId, Long stationId) {
        Order order = new Order();
        // 生成唯一订单号(时间戳+UUID)
        String orderNo = "ORDER_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        order.setOrderNo(orderNo);
        order.setUserId(userId);
        order.setDeviceId(deviceId);
        order.setStationId(stationId);
        // 初始状态:待支付
        order.setOrderStatus(OrderStatus.PENDING_PAYMENT);
        // 初始数据
        order.setTotalPower(BigDecimal.ZERO);
        order.setChargeDuration(0);
        order.setOriginalPrice(BigDecimal.ZERO);
        order.setDiscountPrice(BigDecimal.ZERO);
        order.setActualPrice(BigDecimal.ZERO);
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());

        // 入库
        orderMapper.insert(order);
        return order;
    }

    /**
     * 2. 查询订单状态
     * 业务:用户/设备/运营端查询当前订单处于什么阶段
     */
    @Override
    public OrderStatus getOrderStatus(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        return order.getOrderStatus();
    }

    /**
     * 3. 查询订单详情
     * 业务:用户查看历史订单、运营端对账
     */
    @Override
    public OrderDetailDTO getOrderDetail(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        // 转换为DTO返回
        OrderDetailDTO dto = new OrderDetailDTO();
        // 属性拷贝(可使用BeanUtils)
        dto.setOrderNo(order.getOrderNo());
        dto.setUserId(order.getUserId());
        dto.setDeviceId(order.getDeviceId());
        dto.setStationId(order.getStationId());
        dto.setOrderStatus(order.getOrderStatus());
        dto.setTotalPower(order.getTotalPower());
        dto.setChargeDuration(order.getChargeDuration());
        dto.setOriginalPrice(order.getOriginalPrice());
        dto.setDiscountPrice(order.getDiscountPrice());
        dto.setActualPrice(order.getActualPrice());
        dto.setCreateTime(order.getCreateTime());
        return dto;
    }

    /**
     * 4. 充电中更新数据(实时上报)
     * 业务:充电桩实时上传电量、时长 → 订单服务更新数据
     * 状态约束:必须是【充电中/待支付】才能更新
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateChargingData(String orderNo, BigDecimal totalPower, Integer chargeDuration) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) throw new RuntimeException("订单不存在");

        // 状态校验:只有待支付/充电中可以更新
        if (order.getOrderStatus() != OrderStatus.PENDING_PAYMENT
                && order.getOrderStatus() != OrderStatus.CHARGING) {
            throw new RuntimeException("订单状态不允许更新充电数据");
        }

        // 更新为充电中状态
        order.setOrderStatus(OrderStatus.CHARGING);
        order.setTotalPower(totalPower);
        order.setChargeDuration(chargeDuration);
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.updateById(order);
    }

    /**
     * 5. 充电结束 → 计算费用
     * 业务流程:
     * 1. 调用计费服务,根据电量/时长计算 原价、优惠价、实付价
     * 2. 更新订单金额
     * 3. 状态改为【待支付】
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finishCharge(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) throw new RuntimeException("订单不存在");
        if (order.getOrderStatus() != OrderStatus.CHARGING) {
            throw new RuntimeException("只有充电中订单可以结束充电");
        }

        // 远程调用【计费服务】计算费用
        BillingDTO billing = billingService.calculateFee(
                order.getTotalPower(),
                order.getStationId()
        );

        // 更新订单价格
        order.setOriginalPrice(billing.getOriginalPrice());
        order.setDiscountPrice(billing.getDiscountPrice());
        order.setActualPrice(billing.getActualPrice());
        // 充电结束 → 状态改为待支付
        order.setOrderStatus(OrderStatus.PENDING_PAYMENT);
        order.setUpdateTime(LocalDateTime.now());

        orderMapper.updateById(order);
    }

    /**
     * 6. 支付成功 → 订单完结
     * 业务:支付服务回调 → 订单改为【已完成】
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) throw new RuntimeException("订单不存在");
        if (order.getOrderStatus() != OrderStatus.PENDING_PAYMENT) {
            throw new RuntimeException("只有待支付订单可以支付");
        }

        order.setOrderStatus(OrderStatus.COMPLETED);
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.updateById(order);
    }

    /**
     * 7. 取消订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(String orderNo) {
        Order order = orderMapper.selectByOrderNo(orderNo);
        if (order == null) throw new RuntimeException("订单不存在");

        order.setOrderStatus(OrderStatus.CANCELED);
        order.setRemark("用户主动取消/系统取消");
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.updateById(order);
    }

    /**
     * 8. 异常订单自动修复(定时任务)
     * 业务规则:
     * 1. 充电中超过24小时未结束 → 标记异常
     * 2. 待支付超过1小时 → 自动取消
     * 3. 无状态订单 → 修复为待支付
     */
    @Override
    @Transactional
    public void autoRepairAbnormalOrders() {
        // 1. 查询超过24小时充电中订单 → 标记异常
        orderMapper.updateChargingTimeoutToAbnormal();

        // 2. 查询超过1小时待支付未支付 → 自动取消
        orderMapper.updatePendingPaymentToCancel();

        // 3. 无电量/无状态异常订单 → 修复
        orderMapper.repairNullDataOrders();
    }
}

五、Controller 层(对外 API 接口)

提供给前端 / 其他微服务调用的 HTTP 接口。

复制代码
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/order")
@RequiredArgsConstructor
public class OrderController {

    private final OrderService orderService;

    /**
     * 创建订单
     */
    @PostMapping("/create")
    public Result<Order> createOrder(
            @RequestParam Long userId,
            @RequestParam Long deviceId,
            @RequestParam Long stationId) {
        return Result.success(orderService.createOrder(userId, deviceId, stationId));
    }

    /**
     * 查询订单状态
     */
    @GetMapping("/status/{orderNo}")
    public Result<OrderStatus> getOrderStatus(@PathVariable String orderNo) {
        return Result.success(orderService.getOrderStatus(orderNo));
    }

    /**
     * 查询订单详情
     */
    @GetMapping("/detail/{orderNo}")
    public Result<OrderDetailDTO> getOrderDetail(@PathVariable String orderNo) {
        return Result.success(orderService.getOrderDetail(orderNo));
    }

    /**
     * 取消订单
     */
    @PostMapping("/cancel/{orderNo}")
    public Result<Void> cancelOrder(@PathVariable String orderNo) {
        orderService.cancelOrder(orderNo);
        return Result.success();
    }
}

六、定时任务(异常订单自动修复)

复制代码
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 订单定时任务:异常修复
 */
@Component
@RequiredArgsConstructor
public class OrderScheduleTask {

    private final OrderService orderService;

    /**
     * 每10分钟执行一次:异常订单自动修复
     * 解决:充电中断、超时未支付、状态异常
     */
    @Scheduled(fixedRate = 600000)
    public void autoRepairOrder() {
        orderService.autoRepairAbnormalOrders();
    }
}

七、完整业务流程讲解(最核心!)

这是订单服务串联充电、计费、支付三大服务的标准生命周期:

1. 启动充电

  • 充电服务调用 createOrder()
  • 生成订单,状态 = 待支付
  • 订单电量 / 金额 = 0

2. 充电过程

  • 充电桩实时上报数据
  • 调用 updateChargingData()
  • 订单状态改为 充电中
  • 实时更新电量、时长

3. 停止充电

  • 调用 finishCharge()
  • 远程调用计费服务计算费用
  • 订单写入:原价、优惠价、实付价
  • 状态改为 待支付

4. 用户支付

  • 支付服务完成支付后回调
  • 调用 paySuccess()
  • 状态改为 已完成
  • 订单生命周期结束

5. 异常处理

  • 充电中断超过 24 小时 → 标记异常
  • 待支付 1 小时未支付 → 自动取消
  • 定时任务自动修复,保证数据一致性

八、依赖服务交互说明

  1. 充电服务
    • 调用:创建订单、更新充电数据、结束充电
  2. 计费服务
    • 订单结束时调用,计算费用
  3. 支付服务
    • 支付成功回调,完结订单

九、关键业务规则总结

  1. 状态不可逆已完成 / 已取消 → 不能再修改充电数据
  2. 数据强校验只有充电中订单可以结束充电
  3. 事务保证所有订单写操作加事务,异常回滚
  4. 自动修复定时任务解决充电中断、系统异常导致的脏订单
  5. 财务依据订单数据不可删除,只更新状态,用于对账

总结

  1. 这套代码可直接用于 SpringBoot 项目开发
  2. 接口包含:创建订单、状态查询、详情查询三大核心对外接口
  3. 完整实现了订单生命周期:待支付 → 充电中 → 待支付 → 已完成 / 已取消 / 异常
  4. 包含异常自动修复事务控制微服务远程调用等生产级特性
  5. 是充电平台财务和对账的核心数据服务
相关推荐
JWASX3 小时前
【RocketMQ 生产者和消费者】- 事务源码分析(2)
java·rocketmq·java-rocketmq
手握风云-4 小时前
Spring AI:让大模型住进 Spring 生态(四)
java·后端·spring
装杯让你飞起来啊4 小时前
Kotlin List / Array 与 for 循环
开发语言·kotlin·list
南滑散修4 小时前
红黑树-非黑即红
java·开发语言
Java面试题总结4 小时前
Spring Boot:别再重复造轮子,这些内置功能香麻了
java·spring boot·后端
迷糊小白告4 小时前
Java微服务——SpringCloud
java·spring cloud·微服务
qq_269870434 小时前
java rabbitmq 队列在Springboot的设计
java·rabbitmq·java-rabbitmq
abcnull4 小时前
Springboot+Vue2的Web项目小白入门Demo快速学习!
java·elementui·vue·maven·springboot·web·小白
2501_932750264 小时前
Java IO流基础全面详解:字节流、字符流
java·开发语言