|
@@ -1002,13 +1002,17 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
}
|
|
}
|
|
|
String redisKey = REDIS_KEY_PREFIX + deviceId + ":" + userId;
|
|
String redisKey = REDIS_KEY_PREFIX + deviceId + ":" + userId;
|
|
|
|
|
|
|
|
- // 防止覆盖已有的未消费预授权:如果同一设备+用户已有 preauth key,不覆盖
|
|
|
|
|
- // 新的 outOrderNo 已在 tracking SET 中,后续可通过三层恢复机制找到
|
|
|
|
|
|
|
+ // 检查是否已有未消费的预授权。如果旧预授权关联的 DoorRecord 尚未被 ORC_RESULT 处理
|
|
|
|
|
+ // (即本地无对应订单),说明购物流程正在进行中,不覆盖;否则可以安全覆盖
|
|
|
String existing = stringRedisTemplate.opsForValue().get(redisKey);
|
|
String existing = stringRedisTemplate.opsForValue().get(redisKey);
|
|
|
if (existing != null && !existing.isEmpty()) {
|
|
if (existing != null && !existing.isEmpty()) {
|
|
|
- log.warn("[支付分服务] Redis中已有未消费的预授权信息,不覆盖 - key: {}, 已有: {}, 新: {}",
|
|
|
|
|
|
|
+ if (isPreAuthStillPending(existing)) {
|
|
|
|
|
+ log.warn("[支付分服务] Redis中已有进行中的预授权信息,不覆盖 - key: {}, 已有: {}, 新: {}",
|
|
|
|
|
+ redisKey, existing, result.getOutOrderNo());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("[支付分服务] Redis中旧预授权已消费完毕,覆盖 - key: {}, 旧: {}, 新: {}",
|
|
|
redisKey, existing, result.getOutOrderNo());
|
|
redisKey, existing, result.getOutOrderNo());
|
|
|
- return;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
JSONObject json = new JSONObject();
|
|
JSONObject json = new JSONObject();
|
|
@@ -1021,6 +1025,44 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
log.info("[支付分服务] 支付分信息已存入Redis - key: {}, ttl: {}min", redisKey, REDIS_TTL_MINUTES);
|
|
log.info("[支付分服务] 支付分信息已存入Redis - key: {}, ttl: {}min", redisKey, REDIS_TTL_MINUTES);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 检查 Redis 中已有的预授权是否仍在进行中(未被 ORC_RESULT 消费)
|
|
|
|
|
+ * 如果对应 payScoreOrderId 的本地订单已存在 → 已消费 → 可覆盖
|
|
|
|
|
+ * 如果本地无订单 → 可能仍在等待 ORC_RESULT → 不可覆盖
|
|
|
|
|
+ */
|
|
|
|
|
+ private boolean isPreAuthStillPending(String existingJson) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ JSONObject json = JSON.parseObject(existingJson);
|
|
|
|
|
+ String oldOutOrderNo = json.getString("payScoreOrderId");
|
|
|
|
|
+ if (oldOutOrderNo == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 检查是否已有本地订单关联此支付分订单号
|
|
|
|
|
+ // 有 → ORC_RESULT 已处理完毕 → 可安全覆盖
|
|
|
|
|
+ // 无 → 可能还在等 ORC_RESULT → 保守不覆盖
|
|
|
|
|
+ long count = orderService.lambdaQuery()
|
|
|
|
|
+ .eq(Order::getPayScoreOrderId, oldOutOrderNo)
|
|
|
|
|
+ .count();
|
|
|
|
|
+ return count == 0;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("[支付分服务] 检查预授权状态失败,保守不覆盖", e);
|
|
|
|
|
+ return true; // 解析失败保守处理
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 消费(读取并删除)Redis 中的预授权信息
|
|
|
|
|
+ * 由 scan-open 流程调用,确保每次开门后 Redis 清零,防止下次 scan-open 读错
|
|
|
|
|
+ */
|
|
|
|
|
+ public void consumePreAuthFromRedis(String deviceId, Long userId) {
|
|
|
|
|
+ if (stringRedisTemplate == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ String redisKey = REDIS_KEY_PREFIX + deviceId + ":" + userId;
|
|
|
|
|
+ stringRedisTemplate.delete(redisKey);
|
|
|
|
|
+ log.debug("[支付分服务] Redis预授权已消费 - key: {}", redisKey);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 从 Redis 获取预创建的支付分信息并关联到订单
|
|
* 从 Redis 获取预创建的支付分信息并关联到订单
|
|
|
* 由 HahaCallbackServiceImpl 在创建订单后调用
|
|
* 由 HahaCallbackServiceImpl 在创建订单后调用
|