|
@@ -5,6 +5,12 @@ import com.alibaba.fastjson2.JSON;
|
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
import com.alibaba.fastjson2.JSONArray;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
import com.haha.common.constant.OrderConstants;
|
|
import com.haha.common.constant.OrderConstants;
|
|
|
|
|
+import com.haha.common.enums.DeviceDoorStatus;
|
|
|
|
|
+import com.haha.common.enums.DeviceOnlineStatus;
|
|
|
|
|
+import com.haha.common.enums.NotifyType;
|
|
|
|
|
+import com.haha.common.enums.ProductAuditStatus;
|
|
|
|
|
+import com.haha.common.enums.RecognizeActionType;
|
|
|
|
|
+import com.haha.common.enums.RecognizeConsumeType;
|
|
|
import com.haha.entity.Order;
|
|
import com.haha.entity.Order;
|
|
|
import com.haha.service.OrderService;
|
|
import com.haha.service.OrderService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
@@ -76,9 +82,7 @@ public class CallbackController {
|
|
|
* @return 响应结果,必须返回 "success" 字符串
|
|
* @return 响应结果,必须返回 "success" 字符串
|
|
|
*/
|
|
*/
|
|
|
@PostMapping("/message")
|
|
@PostMapping("/message")
|
|
|
- public String handleMessageCallback(
|
|
|
|
|
- HttpServletRequest request,
|
|
|
|
|
- @RequestParam(required = false) Map<String, String> requestParams) {
|
|
|
|
|
|
|
+ public String handleMessageCallback(HttpServletRequest request, @RequestParam(required = false) Map<String, String> requestParams) {
|
|
|
try {
|
|
try {
|
|
|
// 解析请求参数(兼容JSON和表单两种格式)
|
|
// 解析请求参数(兼容JSON和表单两种格式)
|
|
|
Map<String, Object> params = parseRequestParams(request, requestParams);
|
|
Map<String, Object> params = parseRequestParams(request, requestParams);
|
|
@@ -97,28 +101,33 @@ public class CallbackController {
|
|
|
return "success";
|
|
return "success";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 3. 根据通知类型分发处理
|
|
|
|
|
- switch (notifyType) {
|
|
|
|
|
- case "DEVICE_STATUS":
|
|
|
|
|
|
|
+ NotifyType type = NotifyType.fromCode(notifyType);
|
|
|
|
|
+ if (type == null) {
|
|
|
|
|
+ log.warn("未知的消息通知类型: {}", notifyType);
|
|
|
|
|
+ return "success";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ switch (type) {
|
|
|
|
|
+ case DEVICE_STATUS:
|
|
|
handleDeviceStatus(params);
|
|
handleDeviceStatus(params);
|
|
|
break;
|
|
break;
|
|
|
- case "ONLINE_STATUS":
|
|
|
|
|
|
|
+ case ONLINE_STATUS:
|
|
|
handleOnlineStatus(params);
|
|
handleOnlineStatus(params);
|
|
|
break;
|
|
break;
|
|
|
- case "VOICE_RESULT":
|
|
|
|
|
|
|
+ case VOICE_RESULT:
|
|
|
handleVoiceResult(params);
|
|
handleVoiceResult(params);
|
|
|
break;
|
|
break;
|
|
|
- case "CLIENT_NEW_PRODUCT":
|
|
|
|
|
|
|
+ case CLIENT_NEW_PRODUCT:
|
|
|
handleNewProductAudit(params);
|
|
handleNewProductAudit(params);
|
|
|
break;
|
|
break;
|
|
|
- case "MERGE_PRODUCT":
|
|
|
|
|
|
|
+ case MERGE_PRODUCT:
|
|
|
handleMergeProduct(params);
|
|
handleMergeProduct(params);
|
|
|
break;
|
|
break;
|
|
|
- case "ORC_RESULT":
|
|
|
|
|
|
|
+ case ORC_RESULT:
|
|
|
handleOrcResult(params);
|
|
handleOrcResult(params);
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
- log.warn("未知的消息通知类型: {}", notifyType);
|
|
|
|
|
|
|
+ log.warn("未处理的消息通知类型: {}", type);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 4. 返回成功响应(必须返回 "success" 字符串)
|
|
// 4. 返回成功响应(必须返回 "success" 字符串)
|
|
@@ -161,26 +170,28 @@ public class CallbackController {
|
|
|
statusData.put("status", status);
|
|
statusData.put("status", status);
|
|
|
statusData.put("openType", openType != null ? openType : "");
|
|
statusData.put("openType", openType != null ? openType : "");
|
|
|
statusData.put("userId", outUserId != null ? outUserId : "");
|
|
statusData.put("userId", outUserId != null ? outUserId : "");
|
|
|
- statusData.put("doorStatus", convertDoorStatus(status));
|
|
|
|
|
|
|
+ statusData.put("doorStatus", DeviceDoorStatus.convertToStatus(status));
|
|
|
statusData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
statusData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
|
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
|
|
redisTemplate.expire(statusKey, 30, TimeUnit.MINUTES);
|
|
redisTemplate.expire(statusKey, 30, TimeUnit.MINUTES);
|
|
|
|
|
|
|
|
- // 可以根据业务需要处理不同状态
|
|
|
|
|
- switch (status) {
|
|
|
|
|
- case "2": // OPENED
|
|
|
|
|
- log.info("设备 {} 开门成功", deviceId);
|
|
|
|
|
- break;
|
|
|
|
|
- case "3": // CLOSED
|
|
|
|
|
- log.info("设备 {} 关门成功,等待AI识别", deviceId);
|
|
|
|
|
- break;
|
|
|
|
|
- case "1": // ERROR
|
|
|
|
|
- log.error("设备 {} 开门失败", deviceId);
|
|
|
|
|
- break;
|
|
|
|
|
- case "4": // ANOTHER
|
|
|
|
|
- log.warn("设备 {} 繁忙", deviceId);
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ DeviceDoorStatus doorStatus = DeviceDoorStatus.fromCode(status);
|
|
|
|
|
+ if (doorStatus != null) {
|
|
|
|
|
+ switch (doorStatus) {
|
|
|
|
|
+ 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;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
@@ -188,31 +199,13 @@ public class CallbackController {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private String convertDoorStatus(String status) {
|
|
|
|
|
- if (status == null) return "unknown";
|
|
|
|
|
- switch (status) {
|
|
|
|
|
- case "2": return "open";
|
|
|
|
|
- case "3": return "close";
|
|
|
|
|
- case "1": return "error";
|
|
|
|
|
- case "4": return "busy";
|
|
|
|
|
- default: return "unknown";
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 处理设备在线状态通知 (ONLINE_STATUS)
|
|
|
|
|
- *
|
|
|
|
|
- * @param params 通知参数
|
|
|
|
|
- */
|
|
|
|
|
private void handleOnlineStatus(Map<String, Object> params) {
|
|
private void handleOnlineStatus(Map<String, Object> params) {
|
|
|
try {
|
|
try {
|
|
|
String deviceId = (String) params.get("device_id");
|
|
String deviceId = (String) params.get("device_id");
|
|
|
Integer isOnline = parseInteger(params.get("is_online"));
|
|
Integer isOnline = parseInteger(params.get("is_online"));
|
|
|
|
|
|
|
|
log.info("设备在线状态通知 - 设备: {}, 在线状态: {}",
|
|
log.info("设备在线状态通知 - 设备: {}, 在线状态: {}",
|
|
|
- deviceId, isOnline != null && isOnline == 1 ? "在线" : "离线");
|
|
|
|
|
-
|
|
|
|
|
- // 可以在这里更新设备在线状态到数据库
|
|
|
|
|
|
|
+ deviceId, DeviceOnlineStatus.isOnline(isOnline) ? "在线" : "离线");
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("处理设备在线状态通知失败", e);
|
|
log.error("处理设备在线状态通知失败", e);
|
|
@@ -256,7 +249,7 @@ public class CallbackController {
|
|
|
|
|
|
|
|
log.info("新品审核结果 - ID: {}, 商品名: {}, 状态: {}, code: {}", id, name, status, code);
|
|
log.info("新品审核结果 - ID: {}, 商品名: {}, 状态: {}, code: {}", id, name, status, code);
|
|
|
|
|
|
|
|
- if (status != null && status == 2) {
|
|
|
|
|
|
|
+ if (ProductAuditStatus.isRejected(status)) {
|
|
|
log.warn("新品 {} 被拒绝,原因: {}", name, rejectReason);
|
|
log.warn("新品 {} 被拒绝,原因: {}", name, rejectReason);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -274,13 +267,11 @@ public class CallbackController {
|
|
|
try {
|
|
try {
|
|
|
Object listObj = params.get("list");
|
|
Object listObj = params.get("list");
|
|
|
|
|
|
|
|
- if (listObj instanceof JSONArray) {
|
|
|
|
|
- JSONArray list = (JSONArray) listObj;
|
|
|
|
|
|
|
+ if (listObj instanceof JSONArray list) {
|
|
|
log.info("商品合并结果通知 - 合并数量: {}", list.size());
|
|
log.info("商品合并结果通知 - 合并数量: {}", list.size());
|
|
|
|
|
|
|
|
for (Object item : list) {
|
|
for (Object item : list) {
|
|
|
- if (item instanceof JSONObject) {
|
|
|
|
|
- JSONObject merge = (JSONObject) item;
|
|
|
|
|
|
|
+ if (item instanceof JSONObject merge) {
|
|
|
String mainCode = merge.getString("main_code");
|
|
String mainCode = merge.getString("main_code");
|
|
|
String productCode = merge.getString("product_code");
|
|
String productCode = merge.getString("product_code");
|
|
|
log.info("商品合并 - 主商品: {}, 合并商品: {}", mainCode, productCode);
|
|
log.info("商品合并 - 主商品: {}, 合并商品: {}", mainCode, productCode);
|
|
@@ -315,7 +306,7 @@ public class CallbackController {
|
|
|
String resourceInfoStr = (String) params.get("resource_info");
|
|
String resourceInfoStr = (String) params.get("resource_info");
|
|
|
|
|
|
|
|
log.info("AI识别结果通知 - 设备: {}, 活动: {}, 是否消费: {}",
|
|
log.info("AI识别结果通知 - 设备: {}, 活动: {}, 是否消费: {}",
|
|
|
- deviceId, activityId, nobuy != null && nobuy == 1 ? "无消费" : "有消费");
|
|
|
|
|
|
|
+ deviceId, activityId, RecognizeConsumeType.isNoConsume(nobuy) ? "无消费" : "有消费");
|
|
|
|
|
|
|
|
// 保存识别结果到Redis,供小程序轮询查询
|
|
// 保存识别结果到Redis,供小程序轮询查询
|
|
|
String resultKey = RECOGNIZE_RESULT_KEY + activityId;
|
|
String resultKey = RECOGNIZE_RESULT_KEY + activityId;
|
|
@@ -328,25 +319,26 @@ public class CallbackController {
|
|
|
recognizeData.put("skuList", skuListStr != null ? skuListStr : "");
|
|
recognizeData.put("skuList", skuListStr != null ? skuListStr : "");
|
|
|
recognizeData.put("resourceInfo", resourceInfoStr != null ? resourceInfoStr : "");
|
|
recognizeData.put("resourceInfo", resourceInfoStr != null ? resourceInfoStr : "");
|
|
|
recognizeData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
recognizeData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
redisTemplate.opsForHash().putAll(resultKey, recognizeData);
|
|
redisTemplate.opsForHash().putAll(resultKey, recognizeData);
|
|
|
redisTemplate.expire(resultKey, 30, TimeUnit.MINUTES);
|
|
redisTemplate.expire(resultKey, 30, TimeUnit.MINUTES);
|
|
|
|
|
|
|
|
- if (nobuy != null && nobuy == 1) {
|
|
|
|
|
|
|
+ if (RecognizeConsumeType.isNoConsume(nobuy)) {
|
|
|
log.info("用户打开柜门但未消费,无需处理");
|
|
log.info("用户打开柜门但未消费,无需处理");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 解析result字段
|
|
|
|
|
if (resultStr != null && !resultStr.isEmpty()) {
|
|
if (resultStr != null && !resultStr.isEmpty()) {
|
|
|
JSONObject result = JSON.parseObject(resultStr);
|
|
JSONObject result = JSON.parseObject(resultStr);
|
|
|
- String type = result.getString("type"); // IN或OUT
|
|
|
|
|
|
|
+ String type = result.getString("type");
|
|
|
JSONArray data = result.getJSONArray("data");
|
|
JSONArray data = result.getJSONArray("data");
|
|
|
JSONArray excepts = result.getJSONArray("excepts");
|
|
JSONArray excepts = result.getJSONArray("excepts");
|
|
|
|
|
|
|
|
- log.info("识别类型: {}, 数据: {}", type, data != null ? data.size() : 0);
|
|
|
|
|
|
|
+ RecognizeActionType actionType = RecognizeActionType.fromCode(type);
|
|
|
|
|
+ log.info("识别类型: {}, 数据: {}",
|
|
|
|
|
+ actionType != null ? actionType.getDescription() : type,
|
|
|
|
|
+ data != null ? data.size() : 0);
|
|
|
|
|
|
|
|
- // 检查是否有异常
|
|
|
|
|
if (excepts != null && !excepts.isEmpty()) {
|
|
if (excepts != null && !excepts.isEmpty()) {
|
|
|
log.warn("识别结果包含异常: {}", excepts.toJSONString());
|
|
log.warn("识别结果包含异常: {}", excepts.toJSONString());
|
|
|
}
|
|
}
|
|
@@ -359,16 +351,17 @@ public class CallbackController {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 解析resource_info获取视频URL
|
|
// 解析resource_info获取视频URL
|
|
|
-// if (resourceInfoStr != null && !resourceInfoStr.isEmpty()) {
|
|
|
|
|
-// JSONObject resourceInfo = JSON.parseObject(resourceInfoStr);
|
|
|
|
|
-// String videoUrl = resourceInfo.getString("video_url");
|
|
|
|
|
-// log.info("视频URL: {}", videoUrl);
|
|
|
|
|
-// }
|
|
|
|
|
|
|
+ if (resourceInfoStr != null && !resourceInfoStr.isEmpty()) {
|
|
|
|
|
+ JSONObject resourceInfo = JSON.parseObject(resourceInfoStr);
|
|
|
|
|
+ String videoUrl = resourceInfo.getString("video_url");
|
|
|
|
|
+ log.info("视频URL: {}", videoUrl);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// TODO: 根据识别结果进行后续处理
|
|
// TODO: 根据识别结果进行后续处理
|
|
|
// 1. 计算订单金额
|
|
// 1. 计算订单金额
|
|
|
// 2. 生成订单记录
|
|
// 2. 生成订单记录
|
|
|
- // 3. 触发支付流程
|
|
|
|
|
|
|
+ // 3. 优惠信息处理
|
|
|
|
|
+ // 4. 触发支付流程
|
|
|
|
|
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("处理AI识别结果通知失败", e);
|
|
log.error("处理AI识别结果通知失败", e);
|
|
@@ -460,7 +453,7 @@ public class CallbackController {
|
|
|
orderData.put("totalAmount", orderMoney != null ? orderMoney.toString() : "0");
|
|
orderData.put("totalAmount", orderMoney != null ? orderMoney.toString() : "0");
|
|
|
orderData.put("products", orderDetail != null ? orderDetail : "");
|
|
orderData.put("products", orderDetail != null ? orderDetail : "");
|
|
|
orderData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
orderData.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
redisTemplate.opsForHash().putAll(orderKey, orderData);
|
|
redisTemplate.opsForHash().putAll(orderKey, orderData);
|
|
|
redisTemplate.expire(orderKey, 30, TimeUnit.MINUTES);
|
|
redisTemplate.expire(orderKey, 30, TimeUnit.MINUTES);
|
|
|
|
|
|