|
|
@@ -9,8 +9,10 @@ import com.haha.common.enums.PayStatus;
|
|
|
import com.haha.common.enums.PaymentChannel;
|
|
|
import com.haha.entity.Order;
|
|
|
import com.haha.entity.User;
|
|
|
+import com.haha.entity.DoorRecord;
|
|
|
import com.haha.service.OrderService;
|
|
|
import com.haha.service.UserService;
|
|
|
+import com.haha.service.DoorRecordService;
|
|
|
import com.haha.service.payment.config.WxPayConfig;
|
|
|
import com.haha.service.payment.payscore.*;
|
|
|
import com.haha.service.payment.payscore.PayScoreCreateRequest.PostPayment;
|
|
|
@@ -47,6 +49,9 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
@Autowired
|
|
|
private UserService userService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private DoorRecordService doorRecordService;
|
|
|
+
|
|
|
@Autowired(required = false)
|
|
|
private WxPayConfig wxPayConfig;
|
|
|
|
|
|
@@ -766,7 +771,7 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
String errorMsg = (String) result.get("errorMsg");
|
|
|
if (errorMsg != null && (errorMsg.contains("进行中") || errorMsg.contains("过多"))) {
|
|
|
log.warn("[支付分服务] 首次创建失败(进行中订单过多),尝试暴力清理 - userId: {}", userId);
|
|
|
- bruteForceCancelRecentOrders(deviceId);
|
|
|
+ bruteForceCancelRecentOrders(userId, deviceId);
|
|
|
result = doCreatePayScoreOrder(userId, deviceId, openId);
|
|
|
}
|
|
|
}
|
|
|
@@ -911,7 +916,7 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
}
|
|
|
|
|
|
// 3. 暴力扫描:尝试取消当前设备最近一段时间内可能存在的孤儿订单
|
|
|
- bruteForceCancelRecentOrders(deviceId);
|
|
|
+ bruteForceCancelRecentOrders(userId, deviceId);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -951,38 +956,98 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
/**
|
|
|
* 暴力扫描并取消最近一段时间内的预创建订单
|
|
|
* 当微信返回"进行中订单过多"时,尝试用不同时间戳构造 outOrderNo 并取消
|
|
|
+ * 扫描该用户所有历史设备 + 当前设备,时间窗口 4 小时
|
|
|
*/
|
|
|
- private void bruteForceCancelRecentOrders(String deviceId) {
|
|
|
+ private void bruteForceCancelRecentOrders(Long userId, String deviceId) {
|
|
|
if (payScoreStrategy == null) {
|
|
|
return;
|
|
|
}
|
|
|
- long nowSec = System.currentTimeMillis() / 1000;
|
|
|
- String safeDeviceId = deviceId.replaceAll("[^A-Za-z0-9]", "");
|
|
|
- String suffix = safeDeviceId.length() > 10 ? safeDeviceId.substring(safeDeviceId.length() - 10) : safeDeviceId;
|
|
|
|
|
|
- // 扫描过去60分钟内,每30秒一个时间点(最多120次尝试)
|
|
|
+ // 收集所有可能的设备ID后缀
|
|
|
+ java.util.Set<String> suffixes = new java.util.HashSet<>();
|
|
|
+ addSuffix(suffixes, deviceId);
|
|
|
+
|
|
|
+ // 从 DB 中查找该用户关联过的所有设备
|
|
|
+ try {
|
|
|
+ java.util.Set<String> dbDevices = new java.util.HashSet<>();
|
|
|
+ List<Order> orders = orderService.lambdaQuery()
|
|
|
+ .eq(Order::getUserId, userId)
|
|
|
+ .select(Order::getDeviceId)
|
|
|
+ .isNotNull(Order::getDeviceId)
|
|
|
+ .list();
|
|
|
+ if (orders != null) {
|
|
|
+ for (Order o : orders) {
|
|
|
+ if (o.getDeviceId() != null) {
|
|
|
+ dbDevices.add(o.getDeviceId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<DoorRecord> records = doorRecordService.lambdaQuery()
|
|
|
+ .eq(DoorRecord::getUserId, userId)
|
|
|
+ .select(DoorRecord::getDeviceId)
|
|
|
+ .isNotNull(DoorRecord::getDeviceId)
|
|
|
+ .list();
|
|
|
+ if (records != null) {
|
|
|
+ for (DoorRecord r : records) {
|
|
|
+ if (r.getDeviceId() != null) {
|
|
|
+ dbDevices.add(r.getDeviceId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (String devId : dbDevices) {
|
|
|
+ addSuffix(suffixes, devId);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.debug("[支付分服务] 查询用户设备列表异常: {}", e.getMessage());
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("[支付分服务] 暴力扫描 {} 个设备后缀,窗口4小时", suffixes.size());
|
|
|
+
|
|
|
+ long nowSec = System.currentTimeMillis() / 1000;
|
|
|
int cancelledCount = 0;
|
|
|
- for (int i = 0; i < 120; i++) {
|
|
|
- long ts = nowSec - (i * 30L);
|
|
|
- String outOrderNo = "PS" + ts + suffix;
|
|
|
- try {
|
|
|
- PayScoreCancelRequest cancelReq = new PayScoreCancelRequest();
|
|
|
- cancelReq.setOutOrderNo(outOrderNo);
|
|
|
- cancelReq.setReason("自动清理孤儿订单");
|
|
|
- PayScoreResult cancelResult = payScoreStrategy.cancelServiceOrder(cancelReq);
|
|
|
- if (cancelResult.isSuccess()) {
|
|
|
- cancelledCount++;
|
|
|
- if (cancelledCount <= 3) {
|
|
|
- log.info("[支付分服务] 暴力清理成功 - outOrderNo: {}", outOrderNo);
|
|
|
+ int totalAttempts = 0;
|
|
|
+
|
|
|
+ // 扫描过去4小时,每15秒一个时间点
|
|
|
+ for (int i = 0; i < 960; i++) {
|
|
|
+ long ts = nowSec - (i * 15L);
|
|
|
+ for (String suffix : suffixes) {
|
|
|
+ totalAttempts++;
|
|
|
+ String outOrderNo = "PS" + ts + suffix;
|
|
|
+ try {
|
|
|
+ PayScoreCancelRequest cancelReq = new PayScoreCancelRequest();
|
|
|
+ cancelReq.setOutOrderNo(outOrderNo);
|
|
|
+ cancelReq.setReason("自动清理孤儿订单");
|
|
|
+ PayScoreResult cancelResult = payScoreStrategy.cancelServiceOrder(cancelReq);
|
|
|
+ if (cancelResult.isSuccess()) {
|
|
|
+ cancelledCount++;
|
|
|
+ if (cancelledCount <= 5) {
|
|
|
+ log.info("[支付分服务] 暴力清理成功 - outOrderNo: {}", outOrderNo);
|
|
|
+ }
|
|
|
}
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+
|
|
|
+ if (totalAttempts % 500 == 0 && cancelledCount > 0) {
|
|
|
+ log.info("[支付分服务] 暴力清理进度 - 已尝试 {} 次, 成功取消 {} 笔",
|
|
|
+ totalAttempts, cancelledCount);
|
|
|
}
|
|
|
- } catch (Exception ignored) {
|
|
|
- // 忽略单次取消异常,继续尝试
|
|
|
}
|
|
|
}
|
|
|
if (cancelledCount > 0) {
|
|
|
- log.info("[支付分服务] 暴力清理完成 - 成功取消 {} 笔孤儿订单", cancelledCount);
|
|
|
+ log.info("[支付分服务] 暴力清理完成 - 成功取消 {} 笔孤儿订单 (总尝试 {} 次)",
|
|
|
+ cancelledCount, totalAttempts);
|
|
|
+ } else {
|
|
|
+ log.info("[支付分服务] 暴力清理完成 - 未找到孤儿订单 (总尝试 {} 次)", totalAttempts);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void addSuffix(java.util.Set<String> suffixes, String deviceId) {
|
|
|
+ if (deviceId == null || deviceId.isEmpty()) {
|
|
|
+ return;
|
|
|
}
|
|
|
+ String safe = deviceId.replaceAll("[^A-Za-z0-9]", "");
|
|
|
+ String suffix = safe.length() > 10 ? safe.substring(safe.length() - 10) : safe;
|
|
|
+ suffixes.add(suffix);
|
|
|
}
|
|
|
|
|
|
/**
|