fix(weixin): require classify category and disable fallback cat
Use classify result as mandatory cats_v2 source. If classify fails or no authorized category chain is returned, fail fast with explicit error instead of falling back to fixed leaf category. Made-with: Cursor
This commit is contained in:
parent
864fd47907
commit
0c4fb05074
|
|
@ -235,11 +235,7 @@ public class ExternalSphPublishService {
|
||||||
root.put("head_imgs", head);
|
root.put("head_imgs", head);
|
||||||
root.put("deliver_method", 0);
|
root.put("deliver_method", 0);
|
||||||
root.put("deliver_acct_type", new JSONArray());
|
root.put("deliver_acct_type", new JSONArray());
|
||||||
JSONArray catsV2 = new JSONArray();
|
JSONArray catsV2 = resolveCatsV2OrThrow(req, imgs.headImgUrls(), accessToken);
|
||||||
JSONObject leaf = new JSONObject();
|
|
||||||
long leafCatId = resolveLeafCatId(req, imgs.headImgUrls(), accessToken);
|
|
||||||
leaf.put("cat_id", String.valueOf(leafCatId));
|
|
||||||
catsV2.add(leaf);
|
|
||||||
root.put("cats_v2", catsV2);
|
root.put("cats_v2", catsV2);
|
||||||
JSONObject extra = new JSONObject();
|
JSONObject extra = new JSONObject();
|
||||||
extra.put("seven_day_return", 0);
|
extra.put("seven_day_return", 0);
|
||||||
|
|
@ -269,13 +265,15 @@ public class ExternalSphPublishService {
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long resolveLeafCatId(ExternalGoodsUpsertRequest req, List<String> headImgUrls, String accessToken) {
|
private JSONArray resolveCatsV2OrThrow(ExternalGoodsUpsertRequest req, List<String> headImgUrls, String accessToken) {
|
||||||
long fixedCat = props.getFixedLeafCatIdV2();
|
|
||||||
if (!StringUtils.hasText(props.getProductClassifyUrl())) {
|
if (!StringUtils.hasText(props.getProductClassifyUrl())) {
|
||||||
return fixedCat;
|
throw new IllegalStateException("external.sph.product-classify-url 未配置,无法获取推荐类目");
|
||||||
}
|
}
|
||||||
if (!StringUtils.hasText(accessToken) || CollectionUtils.isEmpty(headImgUrls)) {
|
if (!StringUtils.hasText(accessToken)) {
|
||||||
return fixedCat;
|
throw new IllegalStateException("缺少 accessToken,无法调用类目推荐接口");
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(headImgUrls)) {
|
||||||
|
throw new IllegalStateException("缺少主图,无法调用类目推荐接口");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
JSONObject body = new JSONObject();
|
JSONObject body = new JSONObject();
|
||||||
|
|
@ -289,9 +287,6 @@ public class ExternalSphPublishService {
|
||||||
head.add(u);
|
head.add(u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (head.isEmpty()) {
|
|
||||||
return fixedCat;
|
|
||||||
}
|
|
||||||
body.put("head_imgs", head);
|
body.put("head_imgs", head);
|
||||||
String url = props.getProductClassifyUrl();
|
String url = props.getProductClassifyUrl();
|
||||||
String fullUrl = url + (url.contains("?") ? "&" : "?")
|
String fullUrl = url + (url.contains("?") ? "&" : "?")
|
||||||
|
|
@ -299,49 +294,66 @@ public class ExternalSphPublishService {
|
||||||
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())));
|
||||||
if (!WeixinShopEcHttpClient.isBizOk(raw)) {
|
if (!WeixinShopEcHttpClient.isBizOk(raw)) {
|
||||||
log.warn("[SPH] classify failed shopId={} outGoodsId={} err={} snippet={}",
|
throw new IllegalStateException("类目推荐失败: " + WeixinShopEcHttpClient.formatWxError(raw));
|
||||||
req.getShopId(), req.getOutGoodsId(), WeixinShopEcHttpClient.formatWxError(raw),
|
|
||||||
WeixinShopEcLogSupport.snippet(raw, 500));
|
|
||||||
return fixedCat;
|
|
||||||
}
|
}
|
||||||
Long recommended = parseRecommendedLeafCatId(raw);
|
JSONArray catsV2 = parseRecommendedCatsV2(raw);
|
||||||
if (recommended == null || recommended <= 0) {
|
if (catsV2 == null || catsV2.isEmpty()) {
|
||||||
return fixedCat;
|
throw new IllegalStateException("类目推荐成功但未返回可用类目链");
|
||||||
}
|
}
|
||||||
log.info("[SPH] classify ok shopId={} outGoodsId={} recommendedLeafCatId={} fixedLeafCatId={}",
|
String leafCat = catsV2.getJSONObject(catsV2.size() - 1).getString("cat_id");
|
||||||
req.getShopId(), req.getOutGoodsId(), recommended, fixedCat);
|
log.info("[SPH] classify ok shopId={} outGoodsId={} catsV2Size={} leafCatId={} catsV2={}",
|
||||||
return recommended;
|
req.getShopId(), req.getOutGoodsId(), catsV2.size(), leafCat, catsV2);
|
||||||
|
return catsV2;
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
throw e;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("[SPH] classify exception shopId={} outGoodsId={} err={}",
|
throw new IllegalStateException("类目推荐异常: " + e.getMessage(), e);
|
||||||
req.getShopId(), req.getOutGoodsId(), e.getMessage());
|
|
||||||
return fixedCat;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Long parseRecommendedLeafCatId(String raw) {
|
private static JSONArray parseRecommendedCatsV2(String raw) {
|
||||||
JSONObject root = JSON.parseObject(raw);
|
JSONObject root = JSON.parseObject(raw);
|
||||||
JSONArray categories = root.getJSONArray("categories");
|
JSONArray categories = root.getJSONArray("categories");
|
||||||
if (categories == null || categories.isEmpty()) {
|
if (categories == null || categories.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Long fallback = null;
|
|
||||||
for (Object obj : categories) {
|
for (Object obj : categories) {
|
||||||
if (!(obj instanceof JSONObject item)) {
|
if (!(obj instanceof JSONObject item)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
JSONObject cats = item.getJSONObject("cats");
|
JSONObject cats = item.getJSONObject("cats");
|
||||||
Long leaf = extractLeafCatId(cats);
|
JSONArray catInfo = cats == null ? null : cats.getJSONArray("cat_info");
|
||||||
if (leaf == null || leaf <= 0) {
|
if (catInfo == null || catInfo.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (fallback == null) {
|
|
||||||
fallback = leaf;
|
|
||||||
}
|
|
||||||
if (hasCategoryAuth(item) || hasCategoryAuth(cats)) {
|
if (hasCategoryAuth(item) || hasCategoryAuth(cats)) {
|
||||||
return leaf;
|
JSONArray out = new JSONArray();
|
||||||
|
for (Object c : catInfo) {
|
||||||
|
if (!(c instanceof JSONObject cObj)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String catId = cObj.getString("cat_id");
|
||||||
|
if (!StringUtils.hasText(catId) && cObj.containsKey("cat_id")) {
|
||||||
|
Object n = cObj.get("cat_id");
|
||||||
|
catId = n == null ? null : String.valueOf(n);
|
||||||
|
}
|
||||||
|
if (!StringUtils.hasText(catId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
JSONObject one = new JSONObject();
|
||||||
|
String catIdTrim = catId == null ? "" : catId.trim();
|
||||||
|
if (!StringUtils.hasText(catIdTrim)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
one.put("cat_id", catIdTrim);
|
||||||
|
out.add(one);
|
||||||
|
}
|
||||||
|
if (!out.isEmpty()) {
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fallback;
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasCategoryAuth(JSONObject o) {
|
private static boolean hasCategoryAuth(JSONObject o) {
|
||||||
|
|
@ -360,37 +372,6 @@ public class ExternalSphPublishService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Long extractLeafCatId(JSONObject cats) {
|
|
||||||
if (cats == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
JSONArray catInfo = cats.getJSONArray("cat_info");
|
|
||||||
if (catInfo == null || catInfo.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (int i = catInfo.size() - 1; i >= 0; i--) {
|
|
||||||
Object c = catInfo.get(i);
|
|
||||||
if (c instanceof JSONObject cObj) {
|
|
||||||
String catId = cObj.getString("cat_id");
|
|
||||||
if (StringUtils.hasText(catId)) {
|
|
||||||
try {
|
|
||||||
return Long.parseLong(catId.trim());
|
|
||||||
} catch (NumberFormatException ignore) {
|
|
||||||
// ignore and continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cObj.containsKey("cat_id")) {
|
|
||||||
try {
|
|
||||||
return cObj.getLong("cat_id");
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
// ignore and continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JSONArray buildSkus(List<OGoodsSku> skuRows, ExternalGoodsUpsertRequest req, String defaultThumbWxUrl,
|
private JSONArray buildSkus(List<OGoodsSku> skuRows, ExternalGoodsUpsertRequest req, String defaultThumbWxUrl,
|
||||||
String accessToken) {
|
String accessToken) {
|
||||||
JSONArray arr = new JSONArray();
|
JSONArray arr = new JSONArray();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue