From eb5d00f9986bf2c9dcfa96bbc97fd7541c4ba665 Mon Sep 17 00:00:00 2001 From: huangyujie <27665451@qq.com> Date: Wed, 25 Mar 2026 19:14:46 +0800 Subject: [PATCH] =?UTF-8?q?fix(pdd):=20=E5=8F=91=E5=93=81=E5=89=8D?= =?UTF-8?q?=E5=BD=92=E4=B8=80=E5=8C=96=E5=9B=BE=E7=89=87=20URL=EF=BC=8C?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E4=B8=BB=E6=A1=A3=20JSON=20=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1(path/url/name)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 拼多多 thumb_url/carousel_gallery 仅接受 http(s) 字符串;若 sku 图或轮播误存为整段 JSON 会报图片 url 不合法。发布前从对象/数组中抽取 url 或 path。 Made-with: Cursor --- .../external/pdd/PddGoodsAddParamBuilder.java | 87 ++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/service/src/main/java/cn/qihangerp/service/external/pdd/PddGoodsAddParamBuilder.java b/service/src/main/java/cn/qihangerp/service/external/pdd/PddGoodsAddParamBuilder.java index 3ec597eb..188971d1 100644 --- a/service/src/main/java/cn/qihangerp/service/external/pdd/PddGoodsAddParamBuilder.java +++ b/service/src/main/java/cn/qihangerp/service/external/pdd/PddGoodsAddParamBuilder.java @@ -120,7 +120,7 @@ public class PddGoodsAddParamBuilder { sku.put("quantity", row.getStockQty() != null ? row.getStockQty().longValue() : 0L); sku.put("weight", row.getWeightGram() != null ? row.getWeightGram() : 1000L); sku.put("spec_id_list", ov.getSpecIdList()); - sku.put("thumb_url", StringUtils.hasText(row.getSkuImageUrl()) ? row.getSkuImageUrl() : thumbFallback); + sku.put("thumb_url", firstNonBlankImageUrl(row.getSkuImageUrl(), thumbFallback)); if (StringUtils.hasText(row.getOuterErpSkuId())) { sku.put("out_sku_sn", row.getOuterErpSkuId()); } @@ -231,7 +231,7 @@ public class PddGoodsAddParamBuilder { sku.put("quantity", qty); sku.put("weight", row.getWeightGram() != null ? row.getWeightGram() : 1000L); sku.put("spec_id_list", "[]"); - sku.put("thumb_url", StringUtils.hasText(row.getSkuImageUrl()) ? row.getSkuImageUrl() : carousel.get(0)); + sku.put("thumb_url", firstNonBlankImageUrl(row.getSkuImageUrl(), carousel.get(0))); if (StringUtils.hasText(row.getOuterErpSkuId())) { sku.put("out_sku_sn", row.getOuterErpSkuId()); } @@ -590,19 +590,84 @@ public class PddGoodsAddParamBuilder { private static List resolveCarousel(OGoods goods, ExternalGoodsUpsertRequest req) { List out = new ArrayList<>(); - if (StringUtils.hasText(goods.getImage())) { - out.add(goods.getImage().trim()); - } + addNormalizedCarouselUrl(out, goods != null ? goods.getImage() : null); if (req != null && !CollectionUtils.isEmpty(req.getImages())) { for (String u : req.getImages()) { - if (StringUtils.hasText(u) && !out.contains(u.trim())) { - out.add(u.trim()); - } + addNormalizedCarouselUrl(out, u); } } return out; } + /** + * 主档/前端可能把图片存成 {@code {"url":"...","path":"...","name":"..."}} 整段 JSON; + * 拼多多 {@code carousel_gallery}/{@code thumb_url} 仅接受可访问的 http(s) 字符串。 + */ + private static String normalizePddImageUrl(String raw) { + if (!StringUtils.hasText(raw)) { + return null; + } + String t = raw.trim(); + if (t.startsWith("http://") || t.startsWith("https://")) { + return t; + } + if (t.startsWith("{")) { + try { + JSONObject o = JSON.parseObject(t); + if (o != null) { + String u = o.getString("url"); + if (!StringUtils.hasText(u)) { + u = o.getString("path"); + } + if (StringUtils.hasText(u)) { + return u.trim(); + } + } + } catch (Exception ignored) { + } + return null; + } + if (t.startsWith("[")) { + try { + JSONArray arr = JSON.parseArray(t); + if (arr != null && !arr.isEmpty()) { + Object first = arr.get(0); + if (first instanceof String s) { + return normalizePddImageUrl(s); + } + if (first instanceof JSONObject jo) { + String u = jo.getString("url"); + if (!StringUtils.hasText(u)) { + u = jo.getString("path"); + } + if (StringUtils.hasText(u)) { + return u.trim(); + } + } + } + } catch (Exception ignored) { + } + return null; + } + return t; + } + + private static void addNormalizedCarouselUrl(List out, String raw) { + String n = normalizePddImageUrl(raw); + if (StringUtils.hasText(n) && !out.contains(n)) { + out.add(n); + } + } + + private static String firstNonBlankImageUrl(String primary, String fallback) { + String a = normalizePddImageUrl(primary); + if (StringUtils.hasText(a)) { + return a; + } + String b = normalizePddImageUrl(fallback); + return StringUtils.hasText(b) ? b : ""; + } + private static List resolveDetailImages(OGoods goods) { if (!StringUtils.hasText(goods.getCanonicalExt())) { return List.of(); @@ -618,9 +683,11 @@ public class PddGoodsAddParamBuilder { } List list = new ArrayList<>(); for (int i = 0; i < arr.size(); i++) { - String u = arr.getString(i); + Object el = arr.get(i); + String raw = el instanceof String s ? s : (el != null ? el.toString() : null); + String u = normalizePddImageUrl(raw); if (StringUtils.hasText(u)) { - list.add(u.trim()); + list.add(u); } } return list;