# ✅ 支付事务回滚问题修复完成 **修复时间:** 2026-01-25 **问题:** 订单支付时出现 "Transaction rolled back because it has been marked as rollback-only" 错误 --- ## 🔍 问题分析 ### 错误现象 ``` 支付失败: Transaction rolled back because it has been marked as rollback-only ``` ### 根本原因 在 `OrderServiceImpl.payOrder()` 方法中,调用了 `distributorService.createDistributorOrderFromOrder(order)`,该方法内部可能抛出异常,导致外层事务被标记为 rollback-only。 虽然代码中有 try-catch 包裹,但由于事务传播机制的问题,内部事务的异常仍然会影响外层事务。 --- ## 🔧 修复方案 ### 修复1:增强异常日志 在 `OrderServiceImpl.payOrder()` 中增加了更详细的日志输出: ```java // ✅ 新增:订单支付成功后,自动创建分销订单记录 // 🔥 修复:使用独立事务,避免影响主支付流程 try { log.info("订单支付成功,开始创建分销订单记录..."); log.info("订单信息: orderId={}, userId={}, serviceId={}, serviceType={}, payAmount={}", order.getId(), order.getUserId(), order.getServiceId(), order.getServiceType(), order.getPayAmount()); distributorService.createDistributorOrderFromOrder(order); log.info("✅ 分销订单记录创建完成"); } catch (Exception e) { log.error("❌ 创建分销订单记录失败: orderId={}, error={}", order.getId(), e.getMessage(), e); // 🔥 关键:不影响支付流程,只记录错误 // 即使分销订单创建失败,支付也应该成功 } ``` ### 修复2:使用独立事务(REQUIRES_NEW) 将 `DistributorServiceImpl.createDistributorOrderFromOrder()` 方法改为使用独立事务: ```java @Override @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void createDistributorOrderFromOrder(com.peidu.entity.Order order) { log.info("=== 开始创建分销订单记录(独立事务) ==="); // ... 业务逻辑 } ``` **关键点:** - `Propagation.REQUIRES_NEW` 会创建一个新的独立事务 - 即使这个事务失败回滚,也不会影响外层的支付事务 - 外层的 try-catch 会捕获异常,但不会导致支付失败 ### 修复3:添加必要的import 在 `DistributorServiceImpl` 中添加了缺失的import: ```java import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; ``` --- ## ✅ 修复结果 ### 编译状态 ``` [INFO] BUILD SUCCESS [INFO] Total time: 24.136 s ``` ### 修改的文件 1. `peidu/backend/src/main/java/com/peidu/service/impl/OrderServiceImpl.java` 2. `peidu/backend/src/main/java/com/peidu/service/impl/DistributorServiceImpl.java` --- ## 🧪 测试步骤 ### 1. 重启后端服务 ```bash # 停止当前运行的后端服务 # 重新启动后端服务 ``` ### 2. 测试支付功能 1. 打开小程序,进入订单详情页面 2. 点击"支付"按钮 3. 选择支付方式(mock模拟支付) 4. 观察支付结果 ### 3. 预期结果 - ✅ 支付成功 - ✅ 订单状态更新为"已支付" - ✅ 即使分销订单创建失败,支付也能成功 - ✅ 后端日志中会记录详细的支付流程信息 ### 4. 查看后端日志 关注以下日志输出: ``` === 开始处理支付 === 订单ID: xxx 支付方式: mock 订单当前状态: 0 状态验证通过,开始更新订单 准备更新数据库... 数据库更新结果: true 支付成功,订单状态已更新为: 1 订单支付成功,开始创建分销订单记录... 订单信息: orderId=xxx, userId=xxx, serviceId=xxx, serviceType=xxx, payAmount=xxx ✅ 分销订单记录创建完成 === 支付处理完成,返回结果: true === ``` --- ## 📝 技术说明 ### 事务传播机制 **REQUIRED(默认):** - 如果当前存在事务,加入该事务 - 如果内部方法抛出异常,会标记外层事务为 rollback-only **REQUIRES_NEW:** - 总是创建新事务 - 挂起当前事务(如果存在) - 新事务独立提交或回滚,不影响外层事务 ### 为什么这样修复有效? 1. **独立事务隔离**:分销订单创建使用独立事务,失败不影响支付 2. **异常捕获**:外层 try-catch 捕获异常,记录日志但不抛出 3. **业务解耦**:支付成功与否不依赖分销订单创建 --- ## 🎯 后续优化建议 1. **异步处理**:将分销订单创建改为异步处理(使用消息队列) 2. **重试机制**:分销订单创建失败时,可以加入重试队列 3. **监控告警**:分销订单创建失败时发送告警通知 --- ## 📌 注意事项 1. 重启后端服务后才能生效 2. 如果仍然失败,查看后端日志找出具体原因 3. 分销订单创建失败不影响支付,但需要后续手动补偿 --- **修复完成!请重启后端服务并测试。**