|
|
@@ -253,24 +253,46 @@ public class IWxPayService {
|
|
|
*/
|
|
|
private void processOrderPayment(String orderId) {
|
|
|
log.info("开始处理订单支付完成逻辑,订单号: {}", orderId);
|
|
|
- StoreOrder order = storeOrderMapper.selectStoreOrderByOrderId(orderId);
|
|
|
- if (order != null) {
|
|
|
- // 检查订单是否已经处理过
|
|
|
- if (order.getPaid() == null || order.getPaid() != 1) {
|
|
|
- log.info("更新订单状态为已支付,订单号: {}", orderId);
|
|
|
- // 更新订单状态
|
|
|
- order.setPaid(1); // 设置为已支付
|
|
|
- order.setStatus(1); // 设置订单状态为已支付
|
|
|
- order.setPayTime(new Date()); // 设置支付时间
|
|
|
- storeOrderMapper.updateStoreOrder(order);
|
|
|
- // 从延迟队列中移除订单
|
|
|
- removeOrderFromDelayQueue(orderId);
|
|
|
- log.info("订单状态更新完成,订单号: {}", orderId);
|
|
|
+
|
|
|
+ // 使用Redis分布式锁防止并发处理
|
|
|
+ String lockKey = "payment:lock:" + orderId;
|
|
|
+ Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", java.time.Duration.ofSeconds(30));
|
|
|
+
|
|
|
+ if (Boolean.FALSE.equals(lockAcquired)) {
|
|
|
+ log.warn("订单正在被其他线程处理,订单号: {}", orderId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ StoreOrder order = storeOrderMapper.selectStoreOrderByOrderId(orderId);
|
|
|
+ if (order != null) {
|
|
|
+ // 检查订单是否已被取消
|
|
|
+ if (order.getStatus() != null && order.getStatus() == 3) {
|
|
|
+ log.warn("订单已超时取消,支付回调到达,订单号: {}", orderId);
|
|
|
+ // TODO: 这里应该调用退款接口,将钱退回给用户
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查订单是否已经处理过
|
|
|
+ if (order.getPaid() == null || order.getPaid() != 1) {
|
|
|
+ log.info("更新订单状态为已支付,订单号: {}", orderId);
|
|
|
+ // 更新订单状态
|
|
|
+ order.setPaid(1); // 设置为已支付
|
|
|
+ order.setStatus(1); // 设置订单状态为已支付
|
|
|
+ order.setPayTime(new Date()); // 设置支付时间
|
|
|
+ storeOrderMapper.updateStoreOrder(order);
|
|
|
+ // 从延迟队列中移除订单
|
|
|
+ removeOrderFromDelayQueue(orderId);
|
|
|
+ log.info("订单状态更新完成,订单号: {}", orderId);
|
|
|
+ } else {
|
|
|
+ log.info("订单已处理过,无需重复处理,订单号: {}", orderId);
|
|
|
+ }
|
|
|
} else {
|
|
|
- log.info("订单已处理过,无需重复处理,订单号: {}", orderId);
|
|
|
+ log.warn("订单不存在,订单号: {}", orderId);
|
|
|
}
|
|
|
- } else {
|
|
|
- log.warn("订单不存在,订单号: {}", orderId);
|
|
|
+ } finally {
|
|
|
+ // 释放锁
|
|
|
+ redisTemplate.delete(lockKey);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -313,7 +335,7 @@ public class IWxPayService {
|
|
|
request.setReason(param.getReason());
|
|
|
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
|
|
|
//原订单实际支付金额(单位:分)
|
|
|
- amount.setTotal(yuanToFen(param.getRefundAmount()));
|
|
|
+ amount.setTotal(yuanToFen(param.getTotalPrice()));
|
|
|
//退款金额(单位:分)
|
|
|
amount.setRefund(yuanToFen(param.getRefundAmount()));
|
|
|
//货币类型,默认 "CNY"
|
|
|
@@ -321,15 +343,25 @@ public class IWxPayService {
|
|
|
request.setAmount(amount);
|
|
|
request.setNotifyUrl(wxPayProperties.getRefundNotifyUrl());
|
|
|
param.setSysMember(getSysMember(param.getUserId()));
|
|
|
+
|
|
|
// 检查是否已存在退款记录
|
|
|
StoreRefund existingRefund = storeRefundMapper.selectStoreRefundByOrderId(param.getOrderId());
|
|
|
- if (existingRefund == null) {
|
|
|
- log.info("创建退款记录,订单号: {}", param.getOrderId());
|
|
|
- refundOrder(param);
|
|
|
+ if (existingRefund != null && "2".equals(existingRefund.getRefundStatus())) {
|
|
|
+ log.warn("退款失败,退款记录已存在且已完成,订单号: {}", param.getOrderId());
|
|
|
+ throw new WxPayException("该订单已退款");
|
|
|
}
|
|
|
+
|
|
|
+ // 先调用微信退款接口
|
|
|
log.info("调用微信退款接口,订单号: {}", param.getOrderId());
|
|
|
WxPayRefundV3Result result = this.wxService.refundV3(request);
|
|
|
- log.info("微信退款接口调用完成,订单号: {}", param.getOrderId());
|
|
|
+ log.info("微信退款接口调用成功,订单号: {}", param.getOrderId());
|
|
|
+
|
|
|
+ // 微信退款成功后,再创建本地退款记录
|
|
|
+ if (existingRefund == null) {
|
|
|
+ log.info("微信退款成功,创建本地退款记录,订单号: {}", param.getOrderId());
|
|
|
+ refundOrder(param);
|
|
|
+ }
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -458,6 +490,15 @@ public class IWxPayService {
|
|
|
// 从Redis有序集合中获取所有已超时的订单(score小于当前时间的元素)
|
|
|
redisTemplate.opsForZSet().rangeByScore(ORDER_DELAY_QUEUE_PREFIX + "orders", 0, currentTime)
|
|
|
.forEach(orderId -> {
|
|
|
+ // 使用分布式锁防止与支付回调冲突
|
|
|
+ String lockKey = "payment:lock:" + orderId;
|
|
|
+ Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", java.time.Duration.ofSeconds(30));
|
|
|
+
|
|
|
+ if (Boolean.FALSE.equals(lockAcquired)) {
|
|
|
+ log.warn("订单正在被处理,跳过超时处理,订单号: {}", orderId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
log.info("处理超时订单: {}", orderId);
|
|
|
// 查询订单信息
|
|
|
@@ -480,6 +521,9 @@ public class IWxPayService {
|
|
|
log.info("超时订单 {} 处理完成", orderId);
|
|
|
} catch (Exception e) {
|
|
|
log.error("处理超时订单 {} 时发生错误", orderId, e);
|
|
|
+ } finally {
|
|
|
+ // 释放锁
|
|
|
+ redisTemplate.delete(lockKey);
|
|
|
}
|
|
|
});
|
|
|
// log.info("超时订单处理完成");
|