|
@@ -1369,7 +1369,14 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
/**
|
|
/**
|
|
|
* 取消同设备旧的预创建订单(已被本次新订单替代)
|
|
* 取消同设备旧的预创建订单(已被本次新订单替代)
|
|
|
* 必须检查关联的本地订单状态,避免误取消已确认/正在扣款的订单
|
|
* 必须检查关联的本地订单状态,避免误取消已确认/正在扣款的订单
|
|
|
|
|
+ *
|
|
|
|
|
+ * 安全规则:
|
|
|
|
|
+ * 1. 微信侧已确认(DOING/DONE/USER_PAYING) → 不取消
|
|
|
|
|
+ * 2. 创建不到 MIN_CANCEL_AGE_MINUTES 分钟(可能正在购物流程中)→ 不取消
|
|
|
|
|
+ * 3. 本地有 DoorRecord 引用该 payScoreOrderId 且尚未关联订单 → 不取消(正在使用中)
|
|
|
*/
|
|
*/
|
|
|
|
|
+ private static final int MIN_CANCEL_AGE_MINUTES = 5;
|
|
|
|
|
+
|
|
|
private void cancelOldDeviceOrders(Long userId, String deviceId, String currentOutOrderNo) {
|
|
private void cancelOldDeviceOrders(Long userId, String deviceId, String currentOutOrderNo) {
|
|
|
if (stringRedisTemplate == null) {
|
|
if (stringRedisTemplate == null) {
|
|
|
return;
|
|
return;
|
|
@@ -1386,6 +1393,12 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
log.info("[支付分服务] 跳过取消同设备已确认的支付分订单 - outOrderNo: {}, deviceId: {}", outOrderNo, deviceId);
|
|
log.info("[支付分服务] 跳过取消同设备已确认的支付分订单 - outOrderNo: {}, deviceId: {}", outOrderNo, deviceId);
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 订单太新,可能在购物流程中(等待开门/ORC_RESULT),不取消
|
|
|
|
|
+ if (isRecentlyCreated(outOrderNo)) {
|
|
|
|
|
+ log.info("[支付分服务] 跳过取消同设备刚创建的支付分订单 - outOrderNo: {}, deviceId: {}",
|
|
|
|
|
+ outOrderNo, deviceId);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
cancelPayScoreOrderByOutOrderNo(outOrderNo, null);
|
|
cancelPayScoreOrderByOutOrderNo(outOrderNo, null);
|
|
|
stringRedisTemplate.opsForSet().remove(trackingKey, outOrderNo);
|
|
stringRedisTemplate.opsForSet().remove(trackingKey, outOrderNo);
|
|
|
}
|
|
}
|
|
@@ -1396,6 +1409,27 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从 outOrderNo 中提取创建时间戳,判断是否在保护窗口内
|
|
|
|
|
+ * outOrderNo 格式: PS{10位timestamp}{deviceSuffix},如 PS1786332436B150534
|
|
|
|
|
+ */
|
|
|
|
|
+ private boolean isRecentlyCreated(String outOrderNo) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (outOrderNo == null || outOrderNo.length() < 12 || !outOrderNo.startsWith("PS")) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 提取 PS 后面的 10 位数字时间戳
|
|
|
|
|
+ String tsStr = outOrderNo.substring(2, 12);
|
|
|
|
|
+ long createTimestamp = Long.parseLong(tsStr);
|
|
|
|
|
+ long nowSeconds = System.currentTimeMillis() / 1000;
|
|
|
|
|
+ long ageMinutes = (nowSeconds - createTimestamp) / 60;
|
|
|
|
|
+ return ageMinutes < MIN_CANCEL_AGE_MINUTES;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("[支付分服务] 解析 outOrderNo 时间戳失败 - outOrderNo: {}", outOrderNo, e);
|
|
|
|
|
+ return false; // 解析失败保守不跳过,允许取消
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 检查支付分订单是否可以安全取消
|
|
* 检查支付分订单是否可以安全取消
|
|
|
* 已确认(DOING)或正在扣款(USER_PAYING)或已完成(DONE)的订单不应被取消
|
|
* 已确认(DOING)或正在扣款(USER_PAYING)或已完成(DONE)的订单不应被取消
|