|
|
@@ -3,11 +3,11 @@ package com.haha.service.impl;
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
-import com.haha.common.constant.OrderConstants;
|
|
|
import com.haha.common.enums.DeviceDoorStatus;
|
|
|
-import com.haha.entity.Device;
|
|
|
+import com.haha.common.enums.RecognizeConsumeType;
|
|
|
import com.haha.entity.Order;
|
|
|
import com.haha.mapper.DeviceMapper;
|
|
|
+import com.haha.sdk.HahaClient;
|
|
|
import com.haha.service.HahaCallbackService;
|
|
|
import com.haha.service.OrderService;
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
@@ -18,6 +18,8 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
@@ -34,6 +36,9 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
@Autowired
|
|
|
private StringRedisTemplate stringRedisTemplate;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private HahaClient hahaClient;
|
|
|
+
|
|
|
@Value("${haha.api.app-secret}")
|
|
|
private String appSecret;
|
|
|
|
|
|
@@ -77,44 +82,39 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void handleDeviceStatus(Map<String, Object> params) {
|
|
|
try {
|
|
|
+ String activityId = (String) params.get("activity_id");
|
|
|
String deviceId = (String) params.get("device_id");
|
|
|
- String openStatus = (String) params.get("status");
|
|
|
+ String doorStatus = (String) params.get("status");
|
|
|
String openType = (String) params.get("open_type");
|
|
|
- String activityId = (String) params.get("activity_id");
|
|
|
- String userId = (String) params.get("user_id");
|
|
|
-
|
|
|
- log.info("开关门状态通知 - 设备: {}, 状态: {}, 类型: {}, 活动: {}, 用户: {}",
|
|
|
- deviceId, openStatus, openType, activityId, userId);
|
|
|
-
|
|
|
- // 保存设备状态到Redis,供小程序轮询
|
|
|
- String statusKey = DEVICE_STATUS_KEY + deviceId;
|
|
|
- stringRedisTemplate.opsForValue().set(statusKey, JSON.toJSONString(params), 30, TimeUnit.MINUTES);
|
|
|
-
|
|
|
- // 更新设备表中的门状态字段
|
|
|
- updateDeviceDoorStatus(deviceId, openStatus);
|
|
|
-
|
|
|
- switch (openStatus) {
|
|
|
- case "OPENED":
|
|
|
- log.info("设备 {} 开门成功", deviceId);
|
|
|
- handleDeviceOpened(deviceId, activityId, userId, openType);
|
|
|
- break;
|
|
|
- case "CLOSED":
|
|
|
- log.info("设备 {} 关门成功,等待AI识别", deviceId);
|
|
|
- handleDeviceClosed(deviceId, activityId, userId);
|
|
|
- break;
|
|
|
- case "ERROR":
|
|
|
- log.error("设备 {} 开门失败", deviceId);
|
|
|
- handleDeviceError(deviceId, activityId, userId);
|
|
|
- break;
|
|
|
- case "ANOTHER":
|
|
|
- log.warn("设备 {} 繁忙", deviceId);
|
|
|
- handleDeviceBusy(deviceId, activityId, userId);
|
|
|
- break;
|
|
|
- default:
|
|
|
- log.warn("未知的设备状态: {}", openStatus);
|
|
|
+ String outUserId = (String) params.get("out_user_id");
|
|
|
+
|
|
|
+ log.info("开关门状态通知 - 设备: {}, 状态: {}, 类型: {}, 用户: {}",
|
|
|
+ deviceId, doorStatus, openType, outUserId);
|
|
|
+
|
|
|
+ saveDeviceStatusToRedis(deviceId, activityId, doorStatus, openType, outUserId);
|
|
|
+
|
|
|
+ DeviceDoorStatus doorStatusEnum = DeviceDoorStatus.fromCode(doorStatus);
|
|
|
+ if (doorStatusEnum != null) {
|
|
|
+ switch (doorStatusEnum) {
|
|
|
+ case OPENED:
|
|
|
+ log.info("设备 {} 开门成功", deviceId);
|
|
|
+ break;
|
|
|
+ case CLOSED:
|
|
|
+ log.info("设备 {} 关门成功,等待AI识别", deviceId);
|
|
|
+ break;
|
|
|
+ case ERROR:
|
|
|
+ log.error("设备 {} 开门失败", deviceId);
|
|
|
+ break;
|
|
|
+ case BUSY:
|
|
|
+ log.warn("设备 {} 繁忙", deviceId);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ updateDeviceDoorStatus(deviceId, doorStatus);
|
|
|
+
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理开关门状态通知逻辑失败", e);
|
|
|
+ log.error("处理开关门状态通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -123,16 +123,15 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
try {
|
|
|
String deviceId = (String) params.get("device_id");
|
|
|
Object onlineObj = params.get("is_online");
|
|
|
- Integer isOnline = onlineObj instanceof Integer ? (Integer) onlineObj : Integer.valueOf(onlineObj.toString());
|
|
|
+ Integer isOnline = parseInteger(onlineObj);
|
|
|
|
|
|
log.info("设备在线状态通知 - 设备: {}, 在线状态: {}", deviceId, isOnline == 1 ? "在线" : "离线");
|
|
|
|
|
|
- // 更新设备在线状态到缓存
|
|
|
String onlineKey = "device:online:" + deviceId;
|
|
|
stringRedisTemplate.opsForValue().set(onlineKey, isOnline.toString(), 10, TimeUnit.MINUTES);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理设备在线状态通知逻辑失败", e);
|
|
|
+ log.error("处理设备在线状态通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -141,16 +140,15 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
try {
|
|
|
String deviceId = (String) params.get("device_id");
|
|
|
Object voiceObj = params.get("voice");
|
|
|
- Integer voice = voiceObj instanceof Integer ? (Integer) voiceObj : Integer.valueOf(voiceObj.toString());
|
|
|
+ Integer voice = parseInteger(voiceObj);
|
|
|
|
|
|
log.info("音量调节结果通知 - 设备: {}, 音量值: {}", deviceId, voice);
|
|
|
|
|
|
- // 保存音量设置到缓存
|
|
|
String voiceKey = "device:voice:" + deviceId;
|
|
|
stringRedisTemplate.opsForValue().set(voiceKey, voice.toString(), 30, TimeUnit.DAYS);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理音量调节结果通知逻辑失败", e);
|
|
|
+ log.error("处理音量调节结果通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -159,20 +157,22 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
try {
|
|
|
String id = (String) params.get("id");
|
|
|
Object statusObj = params.get("status");
|
|
|
- Integer status = statusObj instanceof Integer ? (Integer) statusObj : Integer.valueOf(statusObj.toString());
|
|
|
+ Integer status = parseInteger(statusObj);
|
|
|
String name = (String) params.get("name");
|
|
|
- String auditRemark = (String) params.get("audit_remark");
|
|
|
+ String code = (String) params.get("code");
|
|
|
+ String rejectReason = (String) params.get("reject_reason");
|
|
|
|
|
|
- log.info("新品审核结果 - ID: {}, 商品名: {}, 状态: {}, 备注: {}", id, name, status, auditRemark);
|
|
|
+ log.info("新品审核结果 - ID: {}, 商品名: {}, 状态: {}, code: {}", id, name, status, code);
|
|
|
+
|
|
|
+ if (status != null && status == 2) {
|
|
|
+ log.warn("新品 {} 被拒绝,原因: {}", name, rejectReason);
|
|
|
+ }
|
|
|
|
|
|
- // 保存审核结果到缓存
|
|
|
String auditKey = "product:audit:" + id;
|
|
|
stringRedisTemplate.opsForValue().set(auditKey, JSON.toJSONString(params), 7, TimeUnit.DAYS);
|
|
|
|
|
|
- // TODO: 根据审核状态更新商品信息或通知相关人员
|
|
|
-
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理新品审核结果通知逻辑失败", e);
|
|
|
+ log.error("处理新品审核结果通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -180,19 +180,21 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
public void handleMergeProduct(Map<String, Object> params) {
|
|
|
try {
|
|
|
Object listObj = params.get("list");
|
|
|
- if (listObj instanceof JSONArray) {
|
|
|
- JSONArray list = (JSONArray) listObj;
|
|
|
- log.info("商品合并结果通知 - 合并数量: {}", list.size());
|
|
|
|
|
|
- // 保存合并结果到缓存
|
|
|
- String mergeKey = "product:merge:" + System.currentTimeMillis();
|
|
|
- stringRedisTemplate.opsForValue().set(mergeKey, list.toJSONString(), 1, TimeUnit.DAYS);
|
|
|
-
|
|
|
- // TODO: 处理商品合并逻辑,如更新商品关联关系
|
|
|
+ if (listObj instanceof JSONArray list) {
|
|
|
+ log.info("商品合并结果通知 - 合并数量: {}", list.size());
|
|
|
|
|
|
+ for (Object item : list) {
|
|
|
+ if (item instanceof JSONObject merge) {
|
|
|
+ String mainCode = merge.getString("main_code");
|
|
|
+ String productCode = merge.getString("product_code");
|
|
|
+ log.info("商品合并 - 主商品: {}, 合并商品: {}", mainCode, productCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理商品合并结果通知逻辑失败", e);
|
|
|
+ log.error("处理商品合并结果通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -202,175 +204,130 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
try {
|
|
|
String activityId = (String) params.get("activity_id");
|
|
|
String deviceId = (String) params.get("device_id");
|
|
|
- String userId = (String) params.get("user_id");
|
|
|
- Object nobuyObj = params.get("nobuy");
|
|
|
- Integer nobuy = nobuyObj instanceof Integer ? (Integer) nobuyObj : Integer.valueOf(nobuyObj.toString());
|
|
|
+ String userId = (String) params.get("out_user_id");
|
|
|
+ Integer nobuy = parseInteger(params.get("nobuy"));
|
|
|
+ String resultStr = (String) params.get("result");
|
|
|
+ String skuListStr = (String) params.get("sku_list");
|
|
|
String resourceInfoStr = (String) params.get("resource_info");
|
|
|
- Object confidenceObj = params.get("confidence");
|
|
|
- BigDecimal confidence = confidenceObj != null ? new BigDecimal(confidenceObj.toString()) : null;
|
|
|
|
|
|
- // 保存识别结果到Redis
|
|
|
- String recognizeKey = RECOGNIZE_RESULT_KEY + activityId;
|
|
|
- stringRedisTemplate.opsForValue().set(recognizeKey, JSON.toJSONString(params), 30, TimeUnit.MINUTES);
|
|
|
+ log.info("AI识别结果通知 - 设备: {}, 活动: {}, 是否消费: {}",
|
|
|
+ deviceId, activityId, RecognizeConsumeType.isNoConsume(nobuy) ? "无消费" : "有消费");
|
|
|
|
|
|
- if (nobuy == 1) {
|
|
|
- log.info("AI识别结果: 用户未消费 (activityId: {})", activityId);
|
|
|
- handleNoPurchase(activityId, deviceId, userId);
|
|
|
+ saveRecognizeResultToRedis(activityId, params);
|
|
|
+
|
|
|
+ if (RecognizeConsumeType.isNoConsume(nobuy)) {
|
|
|
+ log.info("用户打开柜门但未消费,无需处理");
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 解析识别结果
|
|
|
- String resultStr = (String) params.get("result");
|
|
|
- String skuListStr = (String) params.get("skuList");
|
|
|
- JSONObject result = JSON.parseObject(resultStr);
|
|
|
- JSONArray excepts = result.getJSONArray("excepts");
|
|
|
+ BigDecimal confidence = parseBigDecimal(params.get("confidence"));
|
|
|
|
|
|
- if (excepts != null && !excepts.isEmpty()) {
|
|
|
- log.warn("识别结果包含异常 (activityId: {}): {}", activityId, excepts.toJSONString());
|
|
|
+ Order existingOrder = orderService.getOrderByActivityId(activityId);
|
|
|
+ if (existingOrder != null) {
|
|
|
+ log.info("订单已存在(开门时创建),更新订单信息 - activityId: {}, orderId: {}", activityId, existingOrder.getId());
|
|
|
+ updateOrderFromRecognition(existingOrder, skuListStr, resourceInfoStr, confidence, activityId);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- log.info("AI识别结果通知处理完成 - 设备: {}, 活动: {}, 用户: {}", deviceId, activityId, userId);
|
|
|
+ logRecognizeResultDetails(resultStr, skuListStr, resourceInfoStr);
|
|
|
|
|
|
- // 创建订单
|
|
|
Order order = orderService.createOrderFromRecognition(
|
|
|
activityId, deviceId, userId, skuListStr, resourceInfoStr, confidence);
|
|
|
|
|
|
if (order != null) {
|
|
|
- log.info("AI识别订单创建成功 - 订单ID: {}, 金额: {}", order.getId(), order.getTotalAmount());
|
|
|
-
|
|
|
- // 保存订单信息到Redis供小程序查询
|
|
|
+ log.info("AI识别订单创建成功 - 订单ID: {}", order.getId());
|
|
|
saveOrderInfoToRedis(order, activityId);
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理AI识别结果逻辑失败", e);
|
|
|
+ log.error("处理AI识别结果通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 处理设备开门成功
|
|
|
- */
|
|
|
- private void handleDeviceOpened(String deviceId, String activityId, String userId, String openType) {
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void handleOrderCallback(Map<String, Object> params) {
|
|
|
try {
|
|
|
- log.info("处理设备开门成功 - 设备: {}, 活动: {}, 用户: {}, 类型: {}",
|
|
|
- deviceId, activityId, userId, openType);
|
|
|
-
|
|
|
- // 更新相关订单状态为进行中
|
|
|
- if (activityId != null && userId != null) {
|
|
|
- Order order = orderService.lambdaQuery()
|
|
|
- .eq(Order::getActivityId, activityId)
|
|
|
- .eq(Order::getUserId, Long.parseLong(userId))
|
|
|
- .eq(Order::getStatus, OrderConstants.STATUS_PENDING_PAYMENT)
|
|
|
- .orderByDesc(Order::getCreateTime)
|
|
|
- .last("LIMIT 1")
|
|
|
- .one();
|
|
|
-
|
|
|
- if (order != null) {
|
|
|
- order.setStatus(OrderConstants.STATUS_PENDING_PAYMENT);
|
|
|
- order.setPayStatus(OrderConstants.PAY_STATUS_UNPAID);
|
|
|
- orderService.updateById(order);
|
|
|
- log.info("更新订单状态为待支付: orderNo={}", order.getOrderNo());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("处理设备开门成功逻辑失败", e);
|
|
|
- }
|
|
|
- }
|
|
|
+ String orderId = (String) params.get("order_id");
|
|
|
+ String deviceId = (String) params.get("device_id");
|
|
|
+ String activityId = (String) params.get("activity_id");
|
|
|
+ String userId = (String) params.get("user_id");
|
|
|
+ Object orderMoney = params.get("order_money");
|
|
|
+ String orderDetail = (String) params.get("order_detail");
|
|
|
|
|
|
- /**
|
|
|
- * 处理设备关门
|
|
|
- */
|
|
|
- private void handleDeviceClosed(String deviceId, String activityId, String userId) {
|
|
|
- try {
|
|
|
- log.info("处理设备关门 - 设备: {}, 活动: {}, 用户: {}", deviceId, activityId, userId);
|
|
|
+ log.info("订单信息 - 订单号: {}, 设备: {}, 活动: {}, 用户: {}, 金额: {}",
|
|
|
+ orderId, deviceId, activityId, userId, orderMoney);
|
|
|
|
|
|
- // 触发AI识别流程
|
|
|
- // 实际的AI识别由哈哈平台处理,我们只需等待ORC_RESULT回调
|
|
|
+ Order localOrder = null;
|
|
|
+ if (activityId != null && !activityId.isEmpty()) {
|
|
|
+ localOrder = orderService.getOrderByActivityId(activityId);
|
|
|
+ }
|
|
|
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("处理设备关门逻辑失败", e);
|
|
|
- }
|
|
|
- }
|
|
|
+ if (localOrder == null && userId != null && deviceId != null) {
|
|
|
+ log.info("订单不存在,主动查询识别结果 - activityId: {}", activityId);
|
|
|
+ localOrder = fetchRecognitionAndCreateOrder(activityId, deviceId, userId);
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 处理设备错误
|
|
|
- */
|
|
|
- private void handleDeviceError(String deviceId, String activityId, String userId) {
|
|
|
- try {
|
|
|
- log.error("处理设备错误 - 设备: {}, 活动: {}, 用户: {}", deviceId, activityId, userId);
|
|
|
-
|
|
|
- // 取消相关订单
|
|
|
- if (activityId != null && userId != null) {
|
|
|
- Order order = orderService.lambdaQuery()
|
|
|
- .eq(Order::getActivityId, activityId)
|
|
|
- .eq(Order::getUserId, Long.parseLong(userId))
|
|
|
- .eq(Order::getStatus, OrderConstants.STATUS_PENDING_PAYMENT)
|
|
|
- .orderByDesc(Order::getCreateTime)
|
|
|
- .last("LIMIT 1")
|
|
|
- .one();
|
|
|
+ if (localOrder == null) {
|
|
|
+ log.warn("无法创建订单 - 缺少必要信息: userId={}, deviceId={}, activityId={}", userId, deviceId, activityId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- if (order != null) {
|
|
|
- order.setStatus(OrderConstants.STATUS_CANCELLED);
|
|
|
- order.setPayStatus(OrderConstants.PAY_STATUS_UNPAID);
|
|
|
- orderService.updateById(order);
|
|
|
- log.info("取消订单due to设备错误: orderNo={}", order.getOrderNo());
|
|
|
- }
|
|
|
+ if (orderId != null && orderId.equals(localOrder.getOrderNo())) {
|
|
|
+ log.info("订单已处理过,跳过更新 - orderId: {}", orderId);
|
|
|
+ saveOrderInfoToRedis(localOrder, activityId, orderId, orderMoney, orderDetail);
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
+ updateOrderFromCallback(localOrder, orderId, activityId, orderMoney, orderDetail);
|
|
|
+ saveOrderInfoToRedis(localOrder, activityId, orderId, orderMoney, orderDetail);
|
|
|
+
|
|
|
} catch (Exception e) {
|
|
|
- log.error("处理设备错误逻辑失败", e);
|
|
|
+ log.error("处理订单回调通知失败", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 处理设备繁忙
|
|
|
- */
|
|
|
- private void handleDeviceBusy(String deviceId, String activityId, String userId) {
|
|
|
- try {
|
|
|
- log.warn("处理设备繁忙 - 设备: {}, 活动: {}, 用户: {}", deviceId, activityId, userId);
|
|
|
-
|
|
|
- // 通知用户设备繁忙,建议重试
|
|
|
- // TODO: 发送消息通知给用户
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("处理设备繁忙逻辑失败", e);
|
|
|
+ @Override
|
|
|
+ public boolean validateSign(Map<String, Object> params) {
|
|
|
+ String receivedSign = (String) params.get("sign");
|
|
|
+ if (receivedSign == null || receivedSign.isEmpty()) {
|
|
|
+ log.warn("签名参数为空");
|
|
|
+ return false;
|
|
|
}
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 处理用户未消费情况
|
|
|
- */
|
|
|
- private void handleNoPurchase(String activityId, String deviceId, String userId) {
|
|
|
- try {
|
|
|
- log.info("处理用户未消费 - 活动: {}, 设备: {}, 用户: {}", activityId, deviceId, userId);
|
|
|
-
|
|
|
- // 取消相关订单
|
|
|
- if (activityId != null && userId != null) {
|
|
|
- Order order = orderService.lambdaQuery()
|
|
|
- .eq(Order::getActivityId, activityId)
|
|
|
- .eq(Order::getUserId, Long.parseLong(userId))
|
|
|
- .eq(Order::getStatus, OrderConstants.STATUS_PENDING_PAYMENT)
|
|
|
- .orderByDesc(Order::getCreateTime)
|
|
|
- .last("LIMIT 1")
|
|
|
- .one();
|
|
|
-
|
|
|
- if (order != null) {
|
|
|
- order.setStatus(OrderConstants.STATUS_CANCELLED);
|
|
|
- order.setPayStatus(OrderConstants.PAY_STATUS_UNPAID);
|
|
|
- orderService.updateById(order);
|
|
|
- log.info("取消订单due to用户未消费: orderNo={}", order.getOrderNo());
|
|
|
- }
|
|
|
- }
|
|
|
+ private void saveDeviceStatusToRedis(String deviceId, String activityId, String doorStatus, String openType, String outUserId) {
|
|
|
+ String statusKey = DEVICE_STATUS_KEY + deviceId;
|
|
|
+ Map<String, String> statusData = new HashMap<>();
|
|
|
+ statusData.put("deviceId", deviceId);
|
|
|
+ statusData.put("activityId", activityId != null ? activityId : "");
|
|
|
+ statusData.put("status", doorStatus);
|
|
|
+ statusData.put("openType", openType != null ? openType : "");
|
|
|
+ statusData.put("userId", outUserId != null ? outUserId : "");
|
|
|
+ statusData.put("doorStatus", DeviceDoorStatus.convertToStatus(doorStatus));
|
|
|
+ statusData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
+
|
|
|
+ stringRedisTemplate.opsForHash().putAll(statusKey, statusData);
|
|
|
+ stringRedisTemplate.expire(statusKey, 30, TimeUnit.MINUTES);
|
|
|
+ }
|
|
|
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("处理用户未消费逻辑失败", e);
|
|
|
- }
|
|
|
+ private void saveRecognizeResultToRedis(String activityId, Map<String, Object> params) {
|
|
|
+ String resultKey = RECOGNIZE_RESULT_KEY + activityId;
|
|
|
+ Map<String, String> recognizeData = new HashMap<>();
|
|
|
+ recognizeData.put("activityId", activityId != null ? activityId : "");
|
|
|
+ recognizeData.put("deviceId", (String) params.get("device_id"));
|
|
|
+ recognizeData.put("userId", (String) params.get("out_user_id"));
|
|
|
+ recognizeData.put("nobuy", params.get("nobuy") != null ? String.valueOf(params.get("nobuy")) : "0");
|
|
|
+ recognizeData.put("result", (String) params.get("result"));
|
|
|
+ recognizeData.put("skuList", (String) params.get("sku_list"));
|
|
|
+ recognizeData.put("resourceInfo", (String) params.get("resource_info"));
|
|
|
+ recognizeData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
+
|
|
|
+ stringRedisTemplate.opsForHash().putAll(resultKey, recognizeData);
|
|
|
+ stringRedisTemplate.expire(resultKey, 30, TimeUnit.MINUTES);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 保存订单信息到Redis供小程序查询
|
|
|
- */
|
|
|
private void saveOrderInfoToRedis(Order order, String activityId) {
|
|
|
try {
|
|
|
String orderKey = ORDER_INFO_KEY + activityId;
|
|
|
@@ -394,28 +351,184 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 更新设备门状态
|
|
|
- */
|
|
|
+ private void saveOrderInfoToRedis(Order order, String activityId, String orderId, Object orderMoney, String orderDetail) {
|
|
|
+ String orderKey = ORDER_INFO_KEY + activityId;
|
|
|
+ Map<String, String> orderData = new HashMap<>();
|
|
|
+ orderData.put("orderId", orderId != null ? orderId : "");
|
|
|
+ orderData.put("activityId", activityId != null ? activityId : "");
|
|
|
+ orderData.put("deviceId", order.getDeviceId() != null ? order.getDeviceId() : "");
|
|
|
+ orderData.put("userId", order.getUserId() != null ? order.getUserId().toString() : "");
|
|
|
+ orderData.put("totalAmount", orderMoney != null ? orderMoney.toString() : "0");
|
|
|
+ orderData.put("products", orderDetail != null ? orderDetail : "");
|
|
|
+ orderData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
+
|
|
|
+ stringRedisTemplate.opsForHash().putAll(orderKey, orderData);
|
|
|
+ stringRedisTemplate.expire(orderKey, 30, TimeUnit.MINUTES);
|
|
|
+ }
|
|
|
+
|
|
|
private void updateDeviceDoorStatus(String deviceId, String doorStatus) {
|
|
|
try {
|
|
|
- // 使用专门的更新方法直接更新数据库
|
|
|
- int result = deviceMapper.updateDoorStatus(deviceId, doorStatus);
|
|
|
+ String dbDoorStatus = DeviceDoorStatus.convertToDbValue(doorStatus);
|
|
|
+ int result = deviceMapper.updateDoorStatus(deviceId, dbDoorStatus);
|
|
|
|
|
|
if (result > 0) {
|
|
|
- log.info("更新设备 {} 门状态为: {} " , deviceId, doorStatus);
|
|
|
+ log.info("数据库门状态更新成功 - 设备: {}, 状态: {}", deviceId, dbDoorStatus);
|
|
|
} else {
|
|
|
- log.warn("未找到设备或更新失败: {}", deviceId);
|
|
|
+ log.warn("数据库门状态更新失败 - 设备: {}, 状态: {}", deviceId, dbDoorStatus);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- log.error("更新设备门状态失败 - 设备: {}, 状态: {}", deviceId, doorStatus, e);
|
|
|
+ log.error("更新数据库门状态异常 - 设备: {}", deviceId, e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public boolean validateSign(Map<String, Object> params) {
|
|
|
- // TODO: 实现具体的签名验证逻辑
|
|
|
- // 建议使用HMAC-SHA256算法,结合appSecret进行签名验证
|
|
|
- return true;
|
|
|
+ private void updateOrderFromRecognition(Order order, String skuListStr, String resourceInfoStr, BigDecimal confidence, String activityId) {
|
|
|
+ BigDecimal totalAmount = calculateTotalAmount(skuListStr);
|
|
|
+ String videoUrl = parseVideoUrl(resourceInfoStr);
|
|
|
+
|
|
|
+ order.setItems(skuListStr);
|
|
|
+ order.setTotalAmount(totalAmount);
|
|
|
+ if (videoUrl != null) {
|
|
|
+ order.setVideoUrl(videoUrl);
|
|
|
+ }
|
|
|
+ if (confidence != null) {
|
|
|
+ order.setConfidence(confidence);
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean updated = orderService.updateById(order);
|
|
|
+ if (updated) {
|
|
|
+ log.info("订单信息更新成功 - orderId: {}, totalAmount: {}", order.getId(), totalAmount);
|
|
|
+ }
|
|
|
+
|
|
|
+ saveOrderInfoToRedis(order, activityId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void updateOrderFromCallback(Order order, String orderId, String activityId, Object orderMoney, String orderDetail) {
|
|
|
+ order.setOrderNo(orderId);
|
|
|
+ order.setActivityId(activityId);
|
|
|
+
|
|
|
+ if (orderDetail != null) {
|
|
|
+ order.setItems(orderDetail);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (orderMoney != null) {
|
|
|
+ order.setTotalAmount(new BigDecimal(orderMoney.toString()));
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean updated = orderService.updateById(order);
|
|
|
+ if (updated) {
|
|
|
+ log.info("订单信息更新成功: {}", orderId);
|
|
|
+ } else {
|
|
|
+ log.error("订单信息更新失败: {}", orderId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Order fetchRecognitionAndCreateOrder(String activityId, String deviceId, String userId) {
|
|
|
+ try {
|
|
|
+ Map<String, Object> recognizeResult = hahaClient.getOrderApi().getRecognizeResult(null, activityId);
|
|
|
+ if (recognizeResult != null) {
|
|
|
+ String skuListStr = (String) recognizeResult.get("sku_list");
|
|
|
+ String resourceInfoStr = (String) recognizeResult.get("resource_info");
|
|
|
+ Object confidenceObj = recognizeResult.get("confidence");
|
|
|
+ BigDecimal confidence = confidenceObj != null ? new BigDecimal(confidenceObj.toString()) : null;
|
|
|
+
|
|
|
+ Order order = orderService.createOrderFromRecognition(
|
|
|
+ activityId, deviceId, userId, skuListStr, resourceInfoStr, confidence);
|
|
|
+
|
|
|
+ if (order != null) {
|
|
|
+ log.info("主动创建订单成功 - orderId: {}, activityId: {}", order.getId(), activityId);
|
|
|
+ }
|
|
|
+ return order;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("主动查询识别结果失败 - activityId: {}", activityId, e);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal calculateTotalAmount(String skuListStr) {
|
|
|
+ BigDecimal totalAmount = BigDecimal.ZERO;
|
|
|
+ if (skuListStr != null && !skuListStr.isEmpty()) {
|
|
|
+ JSONArray skuList = JSON.parseArray(skuListStr);
|
|
|
+ if (skuList != null) {
|
|
|
+ for (int i = 0; i < skuList.size(); i++) {
|
|
|
+ JSONObject sku = skuList.getJSONObject(i);
|
|
|
+ BigDecimal price = sku.getBigDecimal("price");
|
|
|
+ Integer quantity = sku.getInteger("quantity");
|
|
|
+ if (price != null && quantity != null) {
|
|
|
+ totalAmount = totalAmount.add(price.multiply(BigDecimal.valueOf(quantity)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ totalAmount = totalAmount.setScale(2, RoundingMode.HALF_UP);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return totalAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String parseVideoUrl(String resourceInfoStr) {
|
|
|
+ if (resourceInfoStr != null && !resourceInfoStr.isEmpty()) {
|
|
|
+ JSONObject resourceInfo = JSON.parseObject(resourceInfoStr);
|
|
|
+ return resourceInfo.getString("video_url");
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void logRecognizeResultDetails(String resultStr, String skuListStr, String resourceInfoStr) {
|
|
|
+ if (resultStr != null && !resultStr.isEmpty()) {
|
|
|
+ JSONObject result = JSON.parseObject(resultStr);
|
|
|
+ String type = result.getString("type");
|
|
|
+ JSONArray data = result.getJSONArray("data");
|
|
|
+ JSONArray excepts = result.getJSONArray("excepts");
|
|
|
+
|
|
|
+ log.info("识别类型: {}, 数据: {}", type, data != null ? data.size() : 0);
|
|
|
+
|
|
|
+ if (excepts != null && !excepts.isEmpty()) {
|
|
|
+ log.warn("识别结果包含异常: {}", excepts.toJSONString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (skuListStr != null && !skuListStr.isEmpty()) {
|
|
|
+ JSONArray skuList = JSON.parseArray(skuListStr);
|
|
|
+ log.info("商品数量: {}", skuList != null ? skuList.size() : 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (resourceInfoStr != null && !resourceInfoStr.isEmpty()) {
|
|
|
+ JSONObject resourceInfo = JSON.parseObject(resourceInfoStr);
|
|
|
+ String videoUrl = resourceInfo.getString("video_url");
|
|
|
+ log.info("视频URL: {}", videoUrl);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer parseInteger(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (value instanceof Integer) {
|
|
|
+ return (Integer) value;
|
|
|
+ } else if (value instanceof String) {
|
|
|
+ String str = (String) value;
|
|
|
+ if (str.trim().isEmpty()) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return Integer.parseInt(str);
|
|
|
+ } else if (value instanceof Number) {
|
|
|
+ return ((Number) value).intValue();
|
|
|
+ }
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ log.warn("无法转换为整型: {}", value);
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private BigDecimal parseBigDecimal(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return new BigDecimal(value.toString());
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ log.warn("无法转换为BigDecimal: {}", value);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|
|
|
}
|