fix(weixin): support classify_list parsing and log classify payload

Log classify response snippets for debugging and parse the official data.classify_list/sub_classify tree to build cats_v2 when categories is absent.

Made-with: Cursor
This commit is contained in:
huangyujie 2026-04-21 17:27:05 +08:00
parent 0c4fb05074
commit 30be524983
1 changed files with 60 additions and 0 deletions

View File

@ -293,6 +293,8 @@ public class ExternalSphPublishService {
+ "access_token=" + URLEncoder.encode(accessToken.trim(), StandardCharsets.UTF_8); + "access_token=" + URLEncoder.encode(accessToken.trim(), StandardCharsets.UTF_8);
String raw = httpClient.postJson(fullUrl, body.toJSONString(), String raw = httpClient.postJson(fullUrl, body.toJSONString(),
Duration.ofSeconds(Math.max(5, props.getHttpReadTimeoutSeconds()))); Duration.ofSeconds(Math.max(5, props.getHttpReadTimeoutSeconds())));
log.info("[SPH] classify response shopId={} outGoodsId={} snippet={}",
req.getShopId(), req.getOutGoodsId(), WeixinShopEcLogSupport.snippet(raw, 2000));
if (!WeixinShopEcHttpClient.isBizOk(raw)) { if (!WeixinShopEcHttpClient.isBizOk(raw)) {
throw new IllegalStateException("类目推荐失败: " + WeixinShopEcHttpClient.formatWxError(raw)); throw new IllegalStateException("类目推荐失败: " + WeixinShopEcHttpClient.formatWxError(raw));
} }
@ -313,6 +315,14 @@ public class ExternalSphPublishService {
private static JSONArray parseRecommendedCatsV2(String raw) { private static JSONArray parseRecommendedCatsV2(String raw) {
JSONObject root = JSON.parseObject(raw); JSONObject root = JSON.parseObject(raw);
JSONObject data = root.getJSONObject("data");
if (data != null) {
JSONArray classifyList = data.getJSONArray("classify_list");
JSONArray fromClassify = parseFromClassifyTree(classifyList);
if (fromClassify != null && !fromClassify.isEmpty()) {
return fromClassify;
}
}
JSONArray categories = root.getJSONArray("categories"); JSONArray categories = root.getJSONArray("categories");
if (categories == null || categories.isEmpty()) { if (categories == null || categories.isEmpty()) {
return null; return null;
@ -356,6 +366,56 @@ public class ExternalSphPublishService {
return null; return null;
} }
private static JSONArray parseFromClassifyTree(JSONArray classifyList) {
if (classifyList == null || classifyList.isEmpty()) {
return null;
}
JSONObject node = pickBestClassifyNode(classifyList);
if (node == null) {
return null;
}
JSONArray out = new JSONArray();
while (node != null) {
Long catIdNum = node.getLong("cat_id");
String catId = catIdNum == null ? node.getString("cat_id") : String.valueOf(catIdNum);
if (StringUtils.hasText(catId)) {
JSONObject one = new JSONObject();
one.put("cat_id", catId.trim());
out.add(one);
}
JSONArray sub = node.getJSONArray("sub_classify");
if (sub == null || sub.isEmpty()) {
break;
}
node = pickBestClassifyNode(sub);
}
return out.isEmpty() ? null : out;
}
private static JSONObject pickBestClassifyNode(JSONArray arr) {
JSONObject bestQualified = null;
double bestQualifiedScore = -1D;
JSONObject bestAny = null;
double bestAnyScore = -1D;
for (Object o : arr) {
if (!(o instanceof JSONObject n)) {
continue;
}
double score = n.getDoubleValue("confidence");
if (bestAny == null || score > bestAnyScore) {
bestAny = n;
bestAnyScore = score;
}
if (n.getBooleanValue("qualification")) {
if (bestQualified == null || score > bestQualifiedScore) {
bestQualified = n;
bestQualifiedScore = score;
}
}
}
return bestQualified != null ? bestQualified : bestAny;
}
private static boolean hasCategoryAuth(JSONObject o) { private static boolean hasCategoryAuth(JSONObject o) {
if (o == null) { if (o == null) {
return false; return false;