Explorar o código

fix: ORC_RESULT 回调以 result.data 为准构建订单商品清单

result.data 是哈哈平台总的商品识别结果,sku_list 仅含自定义商品附加数据。
以 result.data 为准构建有效 sku_list,避免平台 sku_list 聚合错误导致多商品丢失。

Co-Authored-By: Claude <noreply@anthropic.com>
skyline hai 2 días
pai
achega
1e1d2cd3af

+ 73 - 3
haha-service/src/main/java/com/haha/service/impl/HahaCallbackServiceImpl.java

@@ -372,7 +372,9 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
             BigDecimal confidence = parseBigDecimal(params.get("confidence"));
             // 从识别结果中提取类型:OUT-拿出(正常消费),IN-放入(异物放入)
             String recognizeType = extractRecognizeType(resultStr);
-            handleConsume(activityId, deviceId, userId, skuListStr, resourceInfoStr, resultStr, confidence, recognizeType);
+            // 以 result.data 为准构建商品清单(result.data 是总的识别结果,sku_list 仅含自定义商品)
+            String effectiveSkuListStr = buildSkuListFromResultData(resultStr, skuListStr);
+            handleConsume(activityId, deviceId, userId, effectiveSkuListStr, resourceInfoStr, resultStr, confidence, recognizeType);
 
         } catch (Exception e) {
             log.error("处理AI识别结果通知失败 - activityId: {}, deviceId: {}", activityId, deviceId, e);
@@ -953,6 +955,71 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
         saveOrderInfoToRedis(order, activityId);
     }
 
+    /**
+     * 从 result.data 构建有效的 sku_list 格式商品列表。
+     *
+     * 背景:哈哈平台 result.data 是总的商品识别结果(key=商品编码, value=数量变化),
+     * sku_list 仅包含自定义商品的附加信息(如 sku 字段)。
+     * 以 result.data 为准构建商品清单,同时合并原始 sku_list 中的附加字段。
+     *
+     * @param resultStr  识别结果 JSON,格式: {"type":"OUT","data":{"code1":-1,...},...}
+     * @param skuListStr 原始 sku_list JSON 数组
+     * @return 合并后的 sku_list JSON 数组字符串;若 resultStr 为空则回退到原始 skuListStr
+     */
+    private String buildSkuListFromResultData(String resultStr, String skuListStr) {
+        if (resultStr == null || resultStr.isEmpty()) {
+            return skuListStr;
+        }
+        try {
+            JSONObject result = JSON.parseObject(resultStr);
+            if (result == null) {
+                return skuListStr;
+            }
+            JSONObject data = result.getJSONObject("data");
+            if (data == null || data.isEmpty()) {
+                log.debug("result.data 为空,回退到原始 sku_list");
+                return skuListStr;
+            }
+
+            // 从原始 sku_list 提取自定义商品的附加字段(如 sku 字段)
+            Map<String, String> customSkuMap = new HashMap<>();
+            if (skuListStr != null && !skuListStr.isEmpty()) {
+                JSONArray originalSkuList = JSON.parseArray(skuListStr);
+                if (originalSkuList != null) {
+                    for (int i = 0; i < originalSkuList.size(); i++) {
+                        JSONObject item = originalSkuList.getJSONObject(i);
+                        String code = item.getString("code");
+                        String sku = item.getString("sku");
+                        if (code != null && sku != null && !sku.isEmpty()) {
+                            customSkuMap.put(code, sku);
+                        }
+                    }
+                }
+            }
+
+            // 从 result.data 构建 sku_list,以 result.data 为准
+            JSONArray mergedSkuList = new JSONArray();
+            int index = 1;
+            for (String code : data.keySet()) {
+                Integer number = data.getInteger(code);
+                JSONObject item = new JSONObject();
+                item.put("code", code);
+                item.put("number", number);
+                item.put("index", index++);
+                // 合并自定义商品的 sku 字段
+                item.put("sku", customSkuMap.getOrDefault(code, ""));
+                mergedSkuList.add(item);
+            }
+
+            log.info("从 result.data 构建 sku_list - 商品数: {}, 原始 sku_list 条目数: {}",
+                    mergedSkuList.size(), skuListStr != null ? JSON.parseArray(skuListStr).size() : 0);
+            return mergedSkuList.toJSONString();
+        } catch (Exception e) {
+            log.error("从 result.data 构建 sku_list 失败,回退到原始 sku_list", e);
+            return skuListStr;
+        }
+    }
+
     /**
      * 从 AI 识别的 sku_list 解析商品编码,查本地商品库补全信息后写入 order_goods
      * 确保 ORDER 回调到达前运营平台也能看到订单商品
@@ -1170,8 +1237,11 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
             Map<String, Object> recognizeResult = hahaClient.getOrderApi().getRecognizeResult(null, activityId);
             if (recognizeResult != null) {
                 String skuListStr = extractParam(recognizeResult, "sku_list");
+                String resultStr = extractParam(recognizeResult, "result");
                 String resourceInfoStr = extractParam(recognizeResult, "resource_info");
                 BigDecimal confidence = parseBigDecimal(recognizeResult.get("confidence"));
+                // 以 result.data 为准构建商品清单
+                String effectiveSkuListStr = buildSkuListFromResultData(resultStr, skuListStr);
 
                 // 提前从 Redis 读取支付分预授权信息
                 String payScoreOrderId = null;
@@ -1213,7 +1283,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
                 }
 
                 Order order = orderService.createOrderFromRecognition(
-                    activityId, deviceId, userId, skuListStr, resourceInfoStr, confidence,
+                    activityId, deviceId, userId, effectiveSkuListStr, resourceInfoStr, confidence,
                     payScoreOrderId, payScoreState, serviceId);
 
                 if (order != null) {
@@ -1247,7 +1317,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
         if (resultStr != null && !resultStr.isEmpty()) {
             JSONObject result = JSON.parseObject(resultStr);
             String type = result.getString("type");
-            JSONArray data = result.getJSONArray("data");
+            JSONObject data = result.getJSONObject("data");
             JSONArray excepts = result.getJSONArray("excepts");
 
             log.info("识别类型: {}, 数据: {}", type, data != null ? data.size() : 0);