From 3a0be1d73ca367e96a38a7f9234acd19a9a0e239 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sat, 22 Aug 2026 12:24:52 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=BF=BD=E7=95=A5=E6=9C=AC=E5=9C=B0=20Supe?= =?UTF-8?q?rpowers=20=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 6b8802547..11bf71865 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,9 @@ sonar-project.properties !/.mvn/wrapper/maven-wrapper.jar *.versionsBackup +# Local Superpowers planning artifacts +docs/superpowers/ + # STS .factorypath *.zip From f34db91356633a2059efa4a3a8c2b84147e1ff59 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sat, 22 Aug 2026 12:39:27 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E5=B0=8F?= =?UTF-8?q?=E5=BA=97=E5=95=86=E5=93=81=E7=AE=A1=E7=90=86=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../channel/api/WxChannelProductService.java | 61 +++++ .../api/impl/WxChannelProductServiceImpl.java | 113 ++++++++ .../AddProductThirdPartySourceParam.java | 22 ++ .../AddProductThirdPartySourceResponse.java | 16 ++ .../ExternalProductMappingNewParam.java | 31 +++ .../ExternalProductMappingNewResponse.java | 17 ++ .../product/ExternalProductMappingParam.java | 20 ++ .../ExternalProductMappingResponse.java | 23 ++ .../product/ProductAuditQuotaResponse.java | 36 +++ .../product/ProductAuditStrategyInfo.java | 18 ++ .../product/ProductAuditStrategyResponse.java | 16 ++ .../product/ProductAuditStrategySetParam.java | 14 + .../product/ProductBrandRecommendParam.java | 20 ++ .../ProductBrandRecommendResponse.java | 20 ++ .../product/ProductCategoryClassifyParam.java | 20 ++ .../ProductCategoryClassifyResponse.java | 41 +++ .../product/ProductCategoryPreCheckParam.java | 14 + .../ProductCategoryPreCheckResponse.java | 19 ++ .../bean/product/ProductSchemeParam.java | 19 ++ .../bean/product/ProductSchemeResponse.java | 14 + .../bean/product/ProductStockFlowParam.java | 33 +++ .../product/ProductStockFlowResponse.java | 25 ++ .../bean/product/ProductTimingSaleParam.java | 16 ++ .../constant/WxChannelApiUrlConstants.java | 26 ++ ...annelProductManagementServiceImplTest.java | 257 ++++++++++++++++++ .../src/test/resources/testng.xml | 1 + 26 files changed, 912 insertions(+) create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyInfo.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategySetParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowParam.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductTimingSaleParam.java create mode 100644 weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java index ce85e9f0a..4fdf9cee4 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java @@ -13,6 +13,26 @@ import me.chanjar.weixin.channel.bean.product.GiftProductInfo; import me.chanjar.weixin.channel.bean.product.GiftProductListParam; import me.chanjar.weixin.channel.bean.product.GiftProductListResponse; +import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceParam; +import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceResponse; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingNewParam; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingNewResponse; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingParam; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditQuotaResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategyResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategySetParam; +import me.chanjar.weixin.channel.bean.product.ProductBrandRecommendParam; +import me.chanjar.weixin.channel.bean.product.ProductBrandRecommendResponse; +import me.chanjar.weixin.channel.bean.product.ProductCategoryClassifyParam; +import me.chanjar.weixin.channel.bean.product.ProductCategoryClassifyResponse; +import me.chanjar.weixin.channel.bean.product.ProductCategoryPreCheckParam; +import me.chanjar.weixin.channel.bean.product.ProductCategoryPreCheckResponse; +import me.chanjar.weixin.channel.bean.product.ProductSchemeParam; +import me.chanjar.weixin.channel.bean.product.ProductSchemeResponse; +import me.chanjar.weixin.channel.bean.product.ProductStockFlowParam; +import me.chanjar.weixin.channel.bean.product.ProductStockFlowResponse; +import me.chanjar.weixin.channel.bean.product.ProductTimingSaleParam; import me.chanjar.weixin.channel.bean.product.SkuStockBatchResponse; import me.chanjar.weixin.channel.bean.product.SkuStockResponse; import me.chanjar.weixin.channel.bean.product.SpuFastInfo; @@ -213,6 +233,47 @@ WxChannelBaseResponse updateStock(String productId, String skuId, Integer diffTy */ ProductTagLinkResponse getProductTagLink(String productId) throws WxErrorException; + /** 获取商品的移动应用跳转 scheme 码. */ + ProductSchemeResponse getProductScheme(ProductSchemeParam param) throws WxErrorException; + + /** 商品类目推荐. */ + ProductCategoryClassifyResponse classifyProductCategory(ProductCategoryClassifyParam param) throws WxErrorException; + + /** 商品立即开售. */ + WxChannelBaseResponse beginTimingSale(ProductTimingSaleParam param) throws WxErrorException; + + /** 取消商品开售. */ + WxChannelBaseResponse cancelTimingSale(String productId) throws WxErrorException; + + /** 站内外商品属性映射. */ + ExternalProductMappingResponse externalProductMapping(ExternalProductMappingParam param) throws WxErrorException; + + /** 发品前校验. */ + ProductCategoryPreCheckResponse categoryPreCheck(ProductCategoryPreCheckParam param) throws WxErrorException; + + /** 获取商品上架策略. */ + ProductAuditStrategyResponse getProductAuditStrategy() throws WxErrorException; + + /** 设置商品上架策略. */ + WxChannelBaseResponse setProductAuditStrategy(ProductAuditStrategySetParam param) throws WxErrorException; + + /** 获取商品提审限额. */ + ProductAuditQuotaResponse getProductAuditQuota() throws WxErrorException; + + /** 商品属性映射及推荐. */ + ExternalProductMappingNewResponse externalProductMappingNew(ExternalProductMappingNewParam param) + throws WxErrorException; + + /** 商品品牌推荐. */ + ProductBrandRecommendResponse productBrandRecommend(ProductBrandRecommendParam param) throws WxErrorException; + + /** 新增第三方货源信息. */ + AddProductThirdPartySourceResponse addProductThirdPartySource(AddProductThirdPartySourceParam param) + throws WxErrorException; + + /** 获取库存流水. */ + ProductStockFlowResponse getStockFlow(ProductStockFlowParam param) throws WxErrorException; + /** * 添加非卖商品 * diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java index b3974e0aa..a7956d318 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelProductServiceImpl.java @@ -14,22 +14,36 @@ import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_PRODUCT_STOCK_UPDATE_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_PRODUCT_UPDATE_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.LIST_LIMIT_TASK_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_ADD_PRODUCT_THIRD_PARTY_SOURCE_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_ADD_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_AUDIT_FREE_UPDATE_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_AUDIT_STRATEGY_GET_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_AUDIT_STRATEGY_SET_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_BEGIN_TIMING_SALE_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_CANCEL_TIMING_SALE_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_CATEGORY_CLASSIFY_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_CATEGORY_PRE_CHECK_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_DELISTING_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_DEL_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_EXTERNAL_PRODUCT_MAPPING_NEW_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_EXTERNAL_PRODUCT_MAPPING_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_AUDIT_QUOTA_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_STOCK_BATCH_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_STOCK_FLOW_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_STOCK_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_GET_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_H5URL_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_LISTING_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_LIST_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_PRODUCT_BRAND_RECOMMEND_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_QRCODE_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_SCHEME_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_TAGLINK_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_UPDATE_STOCK_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_UPDATE_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.STOP_LIMIT_TASK_URL; +import java.util.Collections; import java.util.List; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.channel.api.WxChannelProductService; @@ -38,6 +52,12 @@ import me.chanjar.weixin.channel.bean.limit.LimitTaskListParam; import me.chanjar.weixin.channel.bean.limit.LimitTaskListResponse; import me.chanjar.weixin.channel.bean.limit.LimitTaskParam; +import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceParam; +import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceResponse; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingNewParam; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingNewResponse; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingParam; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingResponse; import me.chanjar.weixin.channel.bean.product.GiftActivityAddParam; import me.chanjar.weixin.channel.bean.product.GiftActivityAddResponse; import me.chanjar.weixin.channel.bean.product.GiftActivityInfo; @@ -46,6 +66,20 @@ import me.chanjar.weixin.channel.bean.product.GiftProductInfo; import me.chanjar.weixin.channel.bean.product.GiftProductListParam; import me.chanjar.weixin.channel.bean.product.GiftProductListResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditQuotaResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategyResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategySetParam; +import me.chanjar.weixin.channel.bean.product.ProductBrandRecommendParam; +import me.chanjar.weixin.channel.bean.product.ProductBrandRecommendResponse; +import me.chanjar.weixin.channel.bean.product.ProductCategoryClassifyParam; +import me.chanjar.weixin.channel.bean.product.ProductCategoryClassifyResponse; +import me.chanjar.weixin.channel.bean.product.ProductCategoryPreCheckParam; +import me.chanjar.weixin.channel.bean.product.ProductCategoryPreCheckResponse; +import me.chanjar.weixin.channel.bean.product.ProductSchemeParam; +import me.chanjar.weixin.channel.bean.product.ProductSchemeResponse; +import me.chanjar.weixin.channel.bean.product.ProductStockFlowParam; +import me.chanjar.weixin.channel.bean.product.ProductStockFlowResponse; +import me.chanjar.weixin.channel.bean.product.ProductTimingSaleParam; import me.chanjar.weixin.channel.bean.product.SkuStockBatchParam; import me.chanjar.weixin.channel.bean.product.SkuStockBatchResponse; import me.chanjar.weixin.channel.bean.product.SkuStockParam; @@ -228,6 +262,85 @@ public ProductTagLinkResponse getProductTagLink(String productId) throws WxError return ResponseUtils.decode(resJson, ProductTagLinkResponse.class); } + @Override + public ProductSchemeResponse getProductScheme(ProductSchemeParam param) throws WxErrorException { + return postAndDecode(SPU_SCHEME_URL, param, ProductSchemeResponse.class); + } + + @Override + public ProductCategoryClassifyResponse classifyProductCategory(ProductCategoryClassifyParam param) + throws WxErrorException { + return postAndDecode(SPU_CATEGORY_CLASSIFY_URL, param, ProductCategoryClassifyResponse.class); + } + + @Override + public WxChannelBaseResponse beginTimingSale(ProductTimingSaleParam param) throws WxErrorException { + return postAndDecode(SPU_BEGIN_TIMING_SALE_URL, param, WxChannelBaseResponse.class); + } + + @Override + public WxChannelBaseResponse cancelTimingSale(String productId) throws WxErrorException { + return postAndDecode(SPU_CANCEL_TIMING_SALE_URL, Collections.singletonMap("product_id", productId), + WxChannelBaseResponse.class); + } + + @Override + public ExternalProductMappingResponse externalProductMapping(ExternalProductMappingParam param) + throws WxErrorException { + return postAndDecode(SPU_EXTERNAL_PRODUCT_MAPPING_URL, param, ExternalProductMappingResponse.class); + } + + @Override + public ProductCategoryPreCheckResponse categoryPreCheck(ProductCategoryPreCheckParam param) + throws WxErrorException { + return postAndDecode(SPU_CATEGORY_PRE_CHECK_URL, param, ProductCategoryPreCheckResponse.class); + } + + @Override + public ProductAuditStrategyResponse getProductAuditStrategy() throws WxErrorException { + return postAndDecode(SPU_AUDIT_STRATEGY_GET_URL, "{}", ProductAuditStrategyResponse.class); + } + + @Override + public WxChannelBaseResponse setProductAuditStrategy(ProductAuditStrategySetParam param) throws WxErrorException { + return postAndDecode(SPU_AUDIT_STRATEGY_SET_URL, param, WxChannelBaseResponse.class); + } + + @Override + public ProductAuditQuotaResponse getProductAuditQuota() throws WxErrorException { + return postAndDecode(SPU_GET_AUDIT_QUOTA_URL, "{}", ProductAuditQuotaResponse.class); + } + + @Override + public ExternalProductMappingNewResponse externalProductMappingNew(ExternalProductMappingNewParam param) + throws WxErrorException { + return postAndDecode(SPU_EXTERNAL_PRODUCT_MAPPING_NEW_URL, param, ExternalProductMappingNewResponse.class); + } + + @Override + public ProductBrandRecommendResponse productBrandRecommend(ProductBrandRecommendParam param) + throws WxErrorException { + return postAndDecode(SPU_PRODUCT_BRAND_RECOMMEND_URL, param, ProductBrandRecommendResponse.class); + } + + @Override + public AddProductThirdPartySourceResponse addProductThirdPartySource(AddProductThirdPartySourceParam param) + throws WxErrorException { + return postAndDecode(SPU_ADD_PRODUCT_THIRD_PARTY_SOURCE_URL, param, AddProductThirdPartySourceResponse.class); + } + + @Override + public ProductStockFlowResponse getStockFlow(ProductStockFlowParam param) throws WxErrorException { + return postAndDecode(SPU_GET_STOCK_FLOW_URL, param, ProductStockFlowResponse.class); + } + + private T postAndDecode(String url, Object param, Class responseType) + throws WxErrorException { + String reqJson = param instanceof String ? (String) param : JsonUtils.encode(param); + String resJson = shopService.post(url, reqJson); + return ResponseUtils.decode(resJson, responseType); + } + @Override public GiftProductAddResponse addGiftProduct(GiftProductInfo info) throws WxErrorException { String reqJson = JsonUtils.encode(info); diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceParam.java new file mode 100644 index 000000000..6f258358b --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceParam.java @@ -0,0 +1,22 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.Serializable; +import lombok.Data; + +/** 新增第三方货源信息请求参数. */ +@Data +public class AddProductThirdPartySourceParam implements Serializable { + private static final long serialVersionUID = -5784320217481497742L; + + @JsonProperty("scene_value") + private Integer sceneValue; + @JsonProperty("publish_method") + private Integer publishMethod; + private JsonNode supplier; + @JsonProperty("supplier_shop_performance") + private JsonNode supplierShopPerformance; + @JsonProperty("product_source_info") + private JsonNode productSourceInfo; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceResponse.java new file mode 100644 index 000000000..aec4cef99 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/AddProductThirdPartySourceResponse.java @@ -0,0 +1,16 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 新增第三方货源信息响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class AddProductThirdPartySourceResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = -7528226120383065861L; + + @JsonProperty("third_party_source_id") + private Long thirdPartySourceId; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewParam.java new file mode 100644 index 000000000..d78ac8d31 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewParam.java @@ -0,0 +1,31 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** 商品属性映射及推荐请求参数. */ +@Data +public class ExternalProductMappingNewParam implements Serializable { + private static final long serialVersionUID = -7982070319116550518L; + + @JsonProperty("cat_id") + private Long catId; + @JsonProperty("external_category_name") + private String externalCategoryName; + @JsonProperty("head_imgs") + private List headImgs; + @JsonProperty("detail_imgs") + private List detailImgs; + private String title; + @JsonProperty("external_attributes") + private List externalAttributes; + + @Data + public static class ExternalAttribute implements Serializable { + private static final long serialVersionUID = 300805187240781417L; + private String key; + private String value; + } +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java new file mode 100644 index 000000000..29897d961 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java @@ -0,0 +1,17 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 商品属性映射及推荐响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ExternalProductMappingNewResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = 4536547956225312823L; + + @JsonProperty("attributes") + private List attributes; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingParam.java new file mode 100644 index 000000000..849ec64ae --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingParam.java @@ -0,0 +1,20 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import lombok.Data; + +/** 站内外商品属性映射请求参数. */ +@Data +public class ExternalProductMappingParam implements Serializable { + private static final long serialVersionUID = 3288069294712374035L; + + @JsonProperty("cat_id") + private Long catId; + @JsonProperty("external_attribute_name") + private String externalAttributeName; + @JsonProperty("external_attribute_value") + private String externalAttributeValue; + @JsonProperty("external_category_name") + private String externalCategoryName; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingResponse.java new file mode 100644 index 000000000..8899edcfd --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingResponse.java @@ -0,0 +1,23 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 站内外商品属性映射响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ExternalProductMappingResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = -8356596972896906087L; + + @JsonProperty("external_attribute_name") + private String externalAttributeName; + @JsonProperty("external_attribute_value") + private String externalAttributeValue; + @JsonProperty("internal_attribute_name") + private String internalAttributeName; + @JsonProperty("internal_attribute_value") + private List internalAttributeValue; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java new file mode 100644 index 000000000..3626dfe93 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java @@ -0,0 +1,36 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 商品提审限额响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductAuditQuotaResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = -6242837308752181147L; + + @JsonProperty("audit_quota") + private AuditQuota auditQuota; + + @Data + public static class AuditQuota { + @JsonProperty("block_status") + private Integer blockStatus; + @JsonProperty("avail_quota") + private Integer availQuota; + @JsonProperty("total_quota") + private Integer totalQuota; + @JsonProperty("unlimited_type") + private Integer unlimitedType; + @JsonProperty("audit_total_quota") + private Integer auditTotalQuota; + @JsonProperty("audit_total_remaining") + private Integer auditTotalRemaining; + @JsonProperty("new_product_total_quota") + private Integer newProductTotalQuota; + @JsonProperty("new_product_remaining") + private Integer newProductRemaining; + } +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyInfo.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyInfo.java new file mode 100644 index 000000000..5bcdcacb8 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyInfo.java @@ -0,0 +1,18 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import lombok.Data; + +/** 商品上架策略信息. */ +@Data +public class ProductAuditStrategyInfo implements Serializable { + private static final long serialVersionUID = -2747596416115475981L; + + @JsonProperty("hide_err_field_flag") + private Integer hideErrFieldFlag; + @JsonProperty("hit_duplicated_flag") + private Integer hitDuplicatedFlag; + @JsonProperty("hit_low_risk_rule_flag") + private Integer hitLowRiskRuleFlag; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyResponse.java new file mode 100644 index 000000000..92684bcba --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategyResponse.java @@ -0,0 +1,16 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 商品上架策略响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductAuditStrategyResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = -1074784511408331849L; + + @JsonProperty("audit_strategy") + private ProductAuditStrategyInfo auditStrategy; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategySetParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategySetParam.java new file mode 100644 index 000000000..b07ff314e --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditStrategySetParam.java @@ -0,0 +1,14 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import lombok.Data; + +/** 设置商品上架策略请求参数. */ +@Data +public class ProductAuditStrategySetParam implements Serializable { + private static final long serialVersionUID = 7542738744842032508L; + + @JsonProperty("audit_strategy") + private ProductAuditStrategyInfo auditStrategy; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendParam.java new file mode 100644 index 000000000..1fbdc0bb0 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendParam.java @@ -0,0 +1,20 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** 商品品牌推荐请求参数. */ +@Data +public class ProductBrandRecommendParam implements Serializable { + private static final long serialVersionUID = 6462717198206491138L; + + @JsonProperty("cat_id") + private Long catId; + @JsonProperty("head_imgs") + private List headImgs; + @JsonProperty("detail_imgs") + private List detailImgs; + private String title; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendResponse.java new file mode 100644 index 000000000..59344058f --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductBrandRecommendResponse.java @@ -0,0 +1,20 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 商品品牌推荐响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductBrandRecommendResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = 4350605866373432810L; + + @JsonProperty("brand_id") + private Long brandId; + @JsonProperty("brand_name_chinese") + private String brandNameChinese; + @JsonProperty("brand_name_english") + private String brandNameEnglish; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyParam.java new file mode 100644 index 000000000..2e0a45243 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyParam.java @@ -0,0 +1,20 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** 商品类目推荐请求参数. */ +@Data +public class ProductCategoryClassifyParam implements Serializable { + private static final long serialVersionUID = 4665563979720739777L; + + @JsonProperty("req_type") + private Integer reqType; + private String title; + @JsonProperty("head_imgs") + private List headImgs; + @JsonProperty("cat_id") + private String catId; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java new file mode 100644 index 000000000..1e3410cbc --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java @@ -0,0 +1,41 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 商品类目推荐响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductCategoryClassifyResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = 8258747142248203374L; + + private List categories; + @JsonProperty("wrong_cat") + private Boolean wrongCat; + + @Data + public static class CategoryInfo { + private List cats; + } + + @Data + public static class CategoryLevel { + @JsonProperty("cat_info") + private Category catInfo; + @JsonProperty("has_permission") + private Boolean hasPermission; + } + + @Data + public static class Category { + @JsonProperty("cat_id") + private String catId; + @JsonProperty("cat_name") + private String catName; + @JsonProperty("is_shop_no_audit") + private Boolean shopNoAudit; + } +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckParam.java new file mode 100644 index 000000000..aab647472 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckParam.java @@ -0,0 +1,14 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import lombok.Data; + +/** 发品前校验请求参数. */ +@Data +public class ProductCategoryPreCheckParam implements Serializable { + private static final long serialVersionUID = 5155253060483296766L; + + @JsonProperty("cat_id") + private Long catId; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckResponse.java new file mode 100644 index 000000000..42a8221a7 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryPreCheckResponse.java @@ -0,0 +1,19 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 发品前校验响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductCategoryPreCheckResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = 7136603000806024499L; + + @JsonProperty("all_pass") + private Boolean allPass; + @JsonProperty("fail_reasons") + private List failReasons; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeParam.java new file mode 100644 index 000000000..f63774c32 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeParam.java @@ -0,0 +1,19 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import lombok.Data; + +/** 获取商品移动应用跳转 scheme 码请求参数. */ +@Data +public class ProductSchemeParam implements Serializable { + private static final long serialVersionUID = 613832623081127830L; + + @JsonProperty("product_id") + private String productId; + @JsonProperty("from_appid") + private String fromAppid; + private Integer expire; + @JsonProperty("ext_info") + private String extInfo; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeResponse.java new file mode 100644 index 000000000..d44c6b4a1 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductSchemeResponse.java @@ -0,0 +1,14 @@ +package me.chanjar.weixin.channel.bean.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 获取商品移动应用跳转 scheme 码响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductSchemeResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = 7310433919100539990L; + + private String openlink; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowParam.java new file mode 100644 index 000000000..1354705bd --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowParam.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** 获取库存流水请求参数. */ +@Data +public class ProductStockFlowParam implements Serializable { + private static final long serialVersionUID = -407227347279113050L; + + @JsonProperty("product_id") + private String productId; + @JsonProperty("sku_id") + private String skuId; + @JsonProperty("stock_type") + private Integer stockType; + @JsonProperty("finder_id") + private String finderId; + @JsonProperty("begin_time") + private Long beginTime; + @JsonProperty("end_time") + private Long endTime; + @JsonProperty("op_type_list") + private List opTypeList; + @JsonProperty("page_size") + private Integer pageSize; + @JsonProperty("next_key") + private String nextKey; + @JsonProperty("stock_type_id") + private String stockTypeId; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java new file mode 100644 index 000000000..69388d762 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java @@ -0,0 +1,25 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** 获取库存流水响应. */ +@Data +@EqualsAndHashCode(callSuper = true) +public class ProductStockFlowResponse extends WxChannelBaseResponse { + private static final long serialVersionUID = 7600529379926896515L; + + private StockFlowData data; + + @Data + public static class StockFlowData { + @JsonProperty("stock_flow_info_list") + private List stockFlowInfoList; + @JsonProperty("next_key") + private String nextKey; + } +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductTimingSaleParam.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductTimingSaleParam.java new file mode 100644 index 000000000..bb0e17396 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductTimingSaleParam.java @@ -0,0 +1,16 @@ +package me.chanjar.weixin.channel.bean.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; +import lombok.Data; + +/** 商品立即开售请求参数. */ +@Data +public class ProductTimingSaleParam implements Serializable { + private static final long serialVersionUID = -7185451543781817487L; + + @JsonProperty("product_id") + private String productId; + @JsonProperty("task_id") + private Long taskId; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java index 0b62bf59d..462c67ee4 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java @@ -158,10 +158,36 @@ public interface Spu { String SPU_H5URL_URL = "https://api.weixin.qq.com/channels/ec/product/h5url/get"; /** 获取商品二维码 */ String SPU_QRCODE_URL = "https://api.weixin.qq.com/channels/ec/product/qrcode/get"; + /** 获取商品移动应用跳转 scheme 码 */ + String SPU_SCHEME_URL = "https://api.weixin.qq.com/channels/ec/product/scheme/get"; /** 获取商品口令 */ String SPU_TAGLINK_URL = "https://api.weixin.qq.com/channels/ec/product/taglink/get"; + /** 商品类目推荐 */ + String SPU_CATEGORY_CLASSIFY_URL = "https://api.weixin.qq.com/channels/ec/product/category/classify"; + /** 商品立即开售 */ + String SPU_BEGIN_TIMING_SALE_URL = "https://api.weixin.qq.com/channels/ec/product/begintimingsale"; + /** 取消商品开售 */ + String SPU_CANCEL_TIMING_SALE_URL = "https://api.weixin.qq.com/channels/ec/product/canceltimingsale"; + /** 站内外商品属性映射 */ + String SPU_EXTERNAL_PRODUCT_MAPPING_URL = "https://api.weixin.qq.com/channels/ec/product/externalproductmapping"; + /** 发品前校验 */ + String SPU_CATEGORY_PRE_CHECK_URL = "https://api.weixin.qq.com/channels/ec/product/categoryprecheck"; + /** 获取商品上架策略 */ + String SPU_AUDIT_STRATEGY_GET_URL = "https://api.weixin.qq.com/channels/ec/product/auditstrategy/get"; + /** 设置商品上架策略 */ + String SPU_AUDIT_STRATEGY_SET_URL = "https://api.weixin.qq.com/channels/ec/product/auditstrategy/set"; + /** 获取商品提审限额 */ + String SPU_GET_AUDIT_QUOTA_URL = "https://api.weixin.qq.com/channels/ec/product/getauditquota"; + /** 商品属性映射及推荐 */ + String SPU_EXTERNAL_PRODUCT_MAPPING_NEW_URL = "https://api.weixin.qq.com/channels/ec/product/externalproductmappingnew"; + /** 商品品牌推荐 */ + String SPU_PRODUCT_BRAND_RECOMMEND_URL = "https://api.weixin.qq.com/channels/ec/product/productbrandrecommend"; + /** 新增第三方货源信息 */ + String SPU_ADD_PRODUCT_THIRD_PARTY_SOURCE_URL = "https://api.weixin.qq.com/channels/ec/product/addproductthirdpartysource"; /** 获取实时库存 */ String SPU_GET_STOCK_URL = "https://api.weixin.qq.com/channels/ec/product/stock/get"; + /** 获取库存流水 */ + String SPU_GET_STOCK_FLOW_URL = "https://api.weixin.qq.com/channels/ec/product/stock/getflow"; /** 获取实时库存 */ String SPU_GET_STOCK_BATCH_URL = "https://api.weixin.qq.com/channels/ec/product/stock/batchget"; /** 更新商品库存 */ diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java new file mode 100644 index 000000000..a5cdafc65 --- /dev/null +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java @@ -0,0 +1,257 @@ +package me.chanjar.weixin.channel.api.impl; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Arrays; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; +import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceParam; +import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceResponse; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingNewParam; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingNewResponse; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingParam; +import me.chanjar.weixin.channel.bean.product.ExternalProductMappingResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditQuotaResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategyInfo; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategyResponse; +import me.chanjar.weixin.channel.bean.product.ProductAuditStrategySetParam; +import me.chanjar.weixin.channel.bean.product.ProductBrandRecommendParam; +import me.chanjar.weixin.channel.bean.product.ProductBrandRecommendResponse; +import me.chanjar.weixin.channel.bean.product.ProductCategoryClassifyParam; +import me.chanjar.weixin.channel.bean.product.ProductCategoryClassifyResponse; +import me.chanjar.weixin.channel.bean.product.ProductCategoryPreCheckParam; +import me.chanjar.weixin.channel.bean.product.ProductCategoryPreCheckResponse; +import me.chanjar.weixin.channel.bean.product.ProductSchemeParam; +import me.chanjar.weixin.channel.bean.product.ProductSchemeResponse; +import me.chanjar.weixin.channel.bean.product.ProductStockFlowParam; +import me.chanjar.weixin.channel.bean.product.ProductStockFlowResponse; +import me.chanjar.weixin.channel.bean.product.ProductTimingSaleParam; +import me.chanjar.weixin.channel.util.JsonUtils; +import me.chanjar.weixin.common.error.WxErrorException; +import org.testng.annotations.Test; + +/** Tests the product-management endpoint contracts without making network calls. */ +public class WxChannelProductManagementServiceImplTest { + + @Test + public void shouldGetProductScheme() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"openlink\":\"weixin://dl/business/?t=abc\"}"); + ProductSchemeParam param = new ProductSchemeParam(); + param.setProductId("10001"); + param.setFromAppid("wx-app"); + param.setExpire(3600); + param.setExtInfo("source"); + + ProductSchemeResponse result = productService(channelService).getProductScheme(param); + + assertRequest(channelService, "/channels/ec/product/scheme/get", "{\"product_id\":\"10001\",\"from_appid\":\"wx-app\",\"expire\":3600,\"ext_info\":\"source\"}"); + assertEquals(result.getOpenlink(), "weixin://dl/business/?t=abc"); + } + + @Test + public void shouldClassifyProductCategoryAndDecodePermission() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"categories\":[{\"cats\":[{\"cat_info\":{\"cat_id\":\"6000\",\"cat_name\":\"童鞋\"},\"has_permission\":true}]}],\"wrong_cat\":false}"); + ProductCategoryClassifyParam param = new ProductCategoryClassifyParam(); + param.setReqType(2); + param.setTitle("儿童雨鞋"); + param.setHeadImgs(Arrays.asList("https://example.com/image")); + param.setCatId("6000"); + + ProductCategoryClassifyResponse result = productService(channelService).classifyProductCategory(param); + + assertRequest(channelService, "/channels/ec/product/category/classify", "{\"req_type\":2,\"title\":\"儿童雨鞋\",\"head_imgs\":[\"https://example.com/image\"],\"cat_id\":\"6000\"}"); + assertEquals(result.getCategories().get(0).getCats().get(0).getCatInfo().getCatId(), "6000"); + assertTrue(result.getCategories().get(0).getCats().get(0).getHasPermission()); + } + + @Test + public void shouldBeginTimingSale() throws WxErrorException { + RecordingChannelService channelService = response(okResponse()); + ProductTimingSaleParam param = new ProductTimingSaleParam(); + param.setProductId("10001"); + param.setTaskId(123L); + + WxChannelBaseResponse result = productService(channelService).beginTimingSale(param); + + assertRequest(channelService, "/channels/ec/product/begintimingsale", "{\"product_id\":\"10001\",\"task_id\":123}"); + assertTrue(result.isSuccess()); + } + + @Test + public void shouldCancelTimingSale() throws WxErrorException { + RecordingChannelService channelService = response(okResponse()); + + WxChannelBaseResponse result = productService(channelService).cancelTimingSale("10001"); + + assertRequest(channelService, "/channels/ec/product/canceltimingsale", "{\"product_id\":\"10001\"}"); + assertTrue(result.isSuccess()); + } + + @Test + public void shouldMapExternalProductAttribute() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"external_attribute_name\":\"材质\",\"external_attribute_value\":\"塑胶\",\"internal_attribute_name\":\"鞋面材质\",\"internal_attribute_value\":[\"塑胶\"]}"); + ExternalProductMappingParam param = new ExternalProductMappingParam(); + param.setCatId(6000L); + param.setExternalAttributeName("材质"); + param.setExternalAttributeValue("塑胶"); + param.setExternalCategoryName("母婴:童鞋"); + + ExternalProductMappingResponse result = productService(channelService).externalProductMapping(param); + + assertRequest(channelService, "/channels/ec/product/externalproductmapping", "{\"cat_id\":6000,\"external_attribute_name\":\"材质\",\"external_attribute_value\":\"塑胶\",\"external_category_name\":\"母婴:童鞋\"}"); + assertEquals(result.getInternalAttributeValue(), Arrays.asList("塑胶")); + } + + @Test + public void shouldPreCheckCategory() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"all_pass\":false,\"fail_reasons\":[\"缺少资质\"]}"); + ProductCategoryPreCheckParam param = new ProductCategoryPreCheckParam(); + param.setCatId(6000L); + + ProductCategoryPreCheckResponse result = productService(channelService).categoryPreCheck(param); + + assertRequest(channelService, "/channels/ec/product/categoryprecheck", "{\"cat_id\":6000}"); + assertEquals(result.getFailReasons(), Arrays.asList("缺少资质")); + } + + @Test + public void shouldGetProductAuditStrategy() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"audit_strategy\":{\"hide_err_field_flag\":1,\"hit_duplicated_flag\":0,\"hit_low_risk_rule_flag\":1}}"); + + ProductAuditStrategyResponse result = productService(channelService).getProductAuditStrategy(); + + assertRequest(channelService, "/channels/ec/product/auditstrategy/get", "{}"); + assertEquals(result.getAuditStrategy().getHideErrFieldFlag(), Integer.valueOf(1)); + } + + @Test + public void shouldSetProductAuditStrategy() throws WxErrorException { + RecordingChannelService channelService = response(okResponse()); + ProductAuditStrategyInfo strategy = new ProductAuditStrategyInfo(); + strategy.setHideErrFieldFlag(1); + ProductAuditStrategySetParam param = new ProductAuditStrategySetParam(); + param.setAuditStrategy(strategy); + + WxChannelBaseResponse result = productService(channelService).setProductAuditStrategy(param); + + assertRequest(channelService, "/channels/ec/product/auditstrategy/set", "{\"audit_strategy\":{\"hide_err_field_flag\":1}}"); + assertTrue(result.isSuccess()); + } + + @Test + public void shouldGetProductAuditQuota() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"audit_quota\":{\"block_status\":0,\"avail_quota\":20,\"total_quota\":100,\"unlimited_type\":0,\"audit_total_quota\":100,\"audit_total_remaining\":80,\"new_product_total_quota\":50,\"new_product_remaining\":40}}"); + + ProductAuditQuotaResponse result = productService(channelService).getProductAuditQuota(); + + assertRequest(channelService, "/channels/ec/product/getauditquota", "{}"); + assertEquals(result.getAuditQuota().getNewProductRemaining(), Integer.valueOf(40)); + } + + @Test + public void shouldMapAndRecommendExternalProductAttributes() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"attributes\":[{\"key\":\"鞋面材质\",\"value\":\"塑胶\"}]}"); + ExternalProductMappingNewParam.ExternalAttribute attribute = new ExternalProductMappingNewParam.ExternalAttribute(); + attribute.setKey("材质"); + attribute.setValue("塑胶"); + ExternalProductMappingNewParam param = new ExternalProductMappingNewParam(); + param.setCatId(6000L); + param.setExternalCategoryName("母婴:童鞋"); + param.setHeadImgs(Arrays.asList("https://example.com/head")); + param.setTitle("儿童雨鞋"); + param.setExternalAttributes(Arrays.asList(attribute)); + + ExternalProductMappingNewResponse result = productService(channelService).externalProductMappingNew(param); + + assertRequest(channelService, "/channels/ec/product/externalproductmappingnew", "{\"cat_id\":6000,\"external_category_name\":\"母婴:童鞋\",\"head_imgs\":[\"https://example.com/head\"],\"title\":\"儿童雨鞋\",\"external_attributes\":[{\"key\":\"材质\",\"value\":\"塑胶\"}]}"); + assertEquals(result.getAttributes().get(0).getKey(), "鞋面材质"); + } + + @Test + public void shouldRecommendProductBrand() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"brand_id\":123,\"brand_name_chinese\":\"品牌\",\"brand_name_english\":\"Brand\"}"); + ProductBrandRecommendParam param = new ProductBrandRecommendParam(); + param.setCatId(6000L); + param.setHeadImgs(Arrays.asList("https://example.com/head")); + param.setTitle("商品"); + + ProductBrandRecommendResponse result = productService(channelService).productBrandRecommend(param); + + assertRequest(channelService, "/channels/ec/product/productbrandrecommend", "{\"cat_id\":6000,\"head_imgs\":[\"https://example.com/head\"],\"title\":\"商品\"}"); + assertEquals(result.getBrandId(), Long.valueOf(123)); + } + + @Test + public void shouldAddThirdPartyProductSource() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"third_party_source_id\":12345}"); + AddProductThirdPartySourceParam param = new AddProductThirdPartySourceParam(); + param.setSceneValue(1); + param.setPublishMethod(2); + + AddProductThirdPartySourceResponse result = productService(channelService).addProductThirdPartySource(param); + + assertRequest(channelService, "/channels/ec/product/addproductthirdpartysource", "{\"scene_value\":1,\"publish_method\":2}"); + assertEquals(result.getThirdPartySourceId(), Long.valueOf(12345)); + } + + @Test + public void shouldGetStockFlowWithRequiredPaginationAndStockTypeId() throws WxErrorException { + RecordingChannelService channelService = response("{\"errcode\":0,\"errmsg\":\"ok\",\"data\":{\"stock_flow_info_list\":[{\"amount\":2}],\"next_key\":\"next\"}}"); + ProductStockFlowParam param = new ProductStockFlowParam(); + param.setProductId("10001"); + param.setSkuId("10002"); + param.setStockType(2); + param.setStockTypeId("activity-1"); + param.setBeginTime(100L); + param.setEndTime(200L); + param.setPageSize(10); + + ProductStockFlowResponse result = productService(channelService).getStockFlow(param); + + assertRequest(channelService, "/channels/ec/product/stock/getflow", "{\"product_id\":\"10001\",\"sku_id\":\"10002\",\"stock_type\":2,\"begin_time\":100,\"end_time\":200,\"page_size\":10,\"stock_type_id\":\"activity-1\"}"); + assertEquals(result.getData().getStockFlowInfoList().size(), 1); + assertEquals(result.getData().getNextKey(), "next"); + } + + private static WxChannelProductServiceImpl productService(RecordingChannelService channelService) { + return new WxChannelProductServiceImpl(channelService); + } + + private static RecordingChannelService response(String response) { + return new RecordingChannelService(response); + } + + private static String okResponse() { + return "{\"errcode\":0,\"errmsg\":\"ok\"}"; + } + + private static void assertRequest(RecordingChannelService channelService, String path, String expectedJson) { + assertTrue(channelService.getUrl().endsWith(path)); + assertEquals(JsonUtils.decode(channelService.getRequestJson(), Object.class), JsonUtils.decode(expectedJson, Object.class)); + } + + private static class RecordingChannelService extends WxChannelServiceHttpClientImpl { + private final String response; + private String url; + private String requestJson; + + RecordingChannelService(String response) { + this.response = response; + } + + @Override + public String post(String url, String postData) { + this.url = url; + this.requestJson = postData; + return response; + } + + String getUrl() { + return url; + } + + String getRequestJson() { + return requestJson; + } + } +} diff --git a/weixin-java-channel/src/test/resources/testng.xml b/weixin-java-channel/src/test/resources/testng.xml index 819ebcf5f..af6c9dc8c 100644 --- a/weixin-java-channel/src/test/resources/testng.xml +++ b/weixin-java-channel/src/test/resources/testng.xml @@ -3,6 +3,7 @@ + From a0c2daa1114b5c41bc84c8b6ec1c8c234ac15c7b Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sat, 22 Aug 2026 12:45:19 +0800 Subject: [PATCH 3/5] =?UTF-8?q?docs:=20=E8=A1=A5=E5=85=85=E5=95=86?= =?UTF-8?q?=E5=93=81=E7=AE=A1=E7=90=86=E6=8E=A5=E5=8F=A3=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../channel/api/WxChannelProductService.java | 102 +++++++++++++++--- .../product/ProductAuditQuotaResponse.java | 5 +- .../ProductCategoryClassifyResponse.java | 13 ++- .../product/ProductStockFlowResponse.java | 5 +- ...annelProductManagementServiceImplTest.java | 25 +++++ 5 files changed, 132 insertions(+), 18 deletions(-) diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java index 4fdf9cee4..85a3ec7c5 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java @@ -233,45 +233,121 @@ WxChannelBaseResponse updateStock(String productId, String skuId, Integer diffTy */ ProductTagLinkResponse getProductTagLink(String productId) throws WxErrorException; - /** 获取商品的移动应用跳转 scheme 码. */ + /** + * 获取商品的移动应用跳转 scheme 码. + * + * @param param 商品 ID、来源 appid、过期时间和附加信息 + * @return 商品跳转 scheme 码 + * @throws WxErrorException 调用微信接口失败 + */ ProductSchemeResponse getProductScheme(ProductSchemeParam param) throws WxErrorException; - /** 商品类目推荐. */ + /** + * 商品类目推荐. + * + * @param param 请求类型、商品标题、主图和可选类目 ID;当请求类型为 2 时必须提供类目 ID + * @return 推荐类目及店铺经营权限 + * @throws WxErrorException 调用微信接口失败 + */ ProductCategoryClassifyResponse classifyProductCategory(ProductCategoryClassifyParam param) throws WxErrorException; - /** 商品立即开售. */ + /** + * 将定时开售商品改为立即开售. + * + * @param param 商品 ID 和定时开售任务 ID + * @return 操作结果 + * @throws WxErrorException 调用微信接口失败 + */ WxChannelBaseResponse beginTimingSale(ProductTimingSaleParam param) throws WxErrorException; - /** 取消商品开售. */ + /** + * 取消商品开售. + * + * @param productId 商品 ID + * @return 操作结果 + * @throws WxErrorException 调用微信接口失败 + */ WxChannelBaseResponse cancelTimingSale(String productId) throws WxErrorException; - /** 站内外商品属性映射. */ + /** + * 查询站内外商品属性映射. + * + * @param param 叶子类目 ID、外部类目和外部属性 + * @return 对应的站内属性及可选属性值 + * @throws WxErrorException 调用微信接口失败 + */ ExternalProductMappingResponse externalProductMapping(ExternalProductMappingParam param) throws WxErrorException; - /** 发品前校验. */ + /** + * 发品前校验店铺类目资质. + * + * @param param 待发布商品的叶子类目 ID + * @return 校验结果和未通过原因 + * @throws WxErrorException 调用微信接口失败 + */ ProductCategoryPreCheckResponse categoryPreCheck(ProductCategoryPreCheckParam param) throws WxErrorException; - /** 获取商品上架策略. */ + /** + * 获取店铺维度的商品上架策略. + * + * @return 当前上架策略 + * @throws WxErrorException 调用微信接口失败 + */ ProductAuditStrategyResponse getProductAuditStrategy() throws WxErrorException; - /** 设置商品上架策略. */ + /** + * 设置店铺维度的商品上架策略. + * + * @param param 要设置的上架策略 + * @return 操作结果 + * @throws WxErrorException 调用微信接口失败 + */ WxChannelBaseResponse setProductAuditStrategy(ProductAuditStrategySetParam param) throws WxErrorException; - /** 获取商品提审限额. */ + /** + * 获取当前店铺的商品提审限额. + * + * @return 提审总额度和新品剩余额度 + * @throws WxErrorException 调用微信接口失败 + */ ProductAuditQuotaResponse getProductAuditQuota() throws WxErrorException; - /** 商品属性映射及推荐. */ + /** + * 商品属性映射及推荐. + * + * @param param 叶子类目、商品标题、主图及可选的外部属性 + * @return 推荐的站内属性 + * @throws WxErrorException 调用微信接口失败 + */ ExternalProductMappingNewResponse externalProductMappingNew(ExternalProductMappingNewParam param) throws WxErrorException; - /** 商品品牌推荐. */ + /** + * 根据商品信息推荐店铺已有资质的品牌. + * + * @param param 商品叶子类目、标题和图片 + * @return 推荐品牌 + * @throws WxErrorException 调用微信接口失败 + */ ProductBrandRecommendResponse productBrandRecommend(ProductBrandRecommendParam param) throws WxErrorException; - /** 新增第三方货源信息. */ + /** + * 新增第三方货源信息. + * + * @param param 场景、发布方式、货主及货源商品信息 + * @return 包含第三方货源 ID 的操作结果 + * @throws WxErrorException 调用微信接口失败 + */ AddProductThirdPartySourceResponse addProductThirdPartySource(AddProductThirdPartySourceParam param) throws WxErrorException; - /** 获取库存流水. */ + /** + * 获取商品库存流水. + * + * @param param 商品、SKU、库存类型、时间范围和分页参数;pageSize 必填,库存类型非 0 和 1 时 stockTypeId 必填 + * @return 库存流水及下一页标识 + * @throws WxErrorException 调用微信接口失败 + */ ProductStockFlowResponse getStockFlow(ProductStockFlowParam param) throws WxErrorException; /** diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java index 3626dfe93..2f17d0e18 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductAuditQuotaResponse.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.channel.bean.product; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; import lombok.Data; import lombok.EqualsAndHashCode; import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; @@ -15,7 +16,9 @@ public class ProductAuditQuotaResponse extends WxChannelBaseResponse { private AuditQuota auditQuota; @Data - public static class AuditQuota { + public static class AuditQuota implements Serializable { + private static final long serialVersionUID = 6066821247844334714L; + @JsonProperty("block_status") private Integer blockStatus; @JsonProperty("avail_quota") diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java index 1e3410cbc..acf31b7f2 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductCategoryClassifyResponse.java @@ -1,6 +1,7 @@ package me.chanjar.weixin.channel.bean.product; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; import java.util.List; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,12 +18,16 @@ public class ProductCategoryClassifyResponse extends WxChannelBaseResponse { private Boolean wrongCat; @Data - public static class CategoryInfo { + public static class CategoryInfo implements Serializable { + private static final long serialVersionUID = -4800760946330901306L; + private List cats; } @Data - public static class CategoryLevel { + public static class CategoryLevel implements Serializable { + private static final long serialVersionUID = 8010801623725584755L; + @JsonProperty("cat_info") private Category catInfo; @JsonProperty("has_permission") @@ -30,7 +35,9 @@ public static class CategoryLevel { } @Data - public static class Category { + public static class Category implements Serializable { + private static final long serialVersionUID = -9013991576741902059L; + @JsonProperty("cat_id") private String catId; @JsonProperty("cat_name") diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java index 69388d762..d94df28e8 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ProductStockFlowResponse.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; +import java.io.Serializable; import java.util.List; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,7 +17,9 @@ public class ProductStockFlowResponse extends WxChannelBaseResponse { private StockFlowData data; @Data - public static class StockFlowData { + public static class StockFlowData implements Serializable { + private static final long serialVersionUID = -4963813730951045381L; + @JsonProperty("stock_flow_info_list") private List stockFlowInfoList; @JsonProperty("next_key") diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java index a5cdafc65..fea7cbc16 100644 --- a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java @@ -3,6 +3,9 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; import java.util.Arrays; import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; import me.chanjar.weixin.channel.bean.product.AddProductThirdPartySourceParam; @@ -213,6 +216,21 @@ public void shouldGetStockFlowWithRequiredPaginationAndStockTypeId() throws WxEr assertEquals(result.getData().getNextKey(), "next"); } + @Test + public void shouldSerializeNestedProductManagementResponses() throws IOException { + ProductAuditQuotaResponse.AuditQuota auditQuota = new ProductAuditQuotaResponse.AuditQuota(); + ProductCategoryClassifyResponse.Category category = new ProductCategoryClassifyResponse.Category(); + ProductCategoryClassifyResponse.CategoryLevel categoryLevel = new ProductCategoryClassifyResponse.CategoryLevel(); + ProductCategoryClassifyResponse.CategoryInfo categoryInfo = new ProductCategoryClassifyResponse.CategoryInfo(); + ProductStockFlowResponse.StockFlowData stockFlowData = new ProductStockFlowResponse.StockFlowData(); + + assertSerializable(auditQuota); + assertSerializable(category); + assertSerializable(categoryLevel); + assertSerializable(categoryInfo); + assertSerializable(stockFlowData); + } + private static WxChannelProductServiceImpl productService(RecordingChannelService channelService) { return new WxChannelProductServiceImpl(channelService); } @@ -230,6 +248,13 @@ private static void assertRequest(RecordingChannelService channelService, String assertEquals(JsonUtils.decode(channelService.getRequestJson(), Object.class), JsonUtils.decode(expectedJson, Object.class)); } + private static void assertSerializable(Object value) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + try (ObjectOutputStream objectOutput = new ObjectOutputStream(output)) { + objectOutput.writeObject(value); + } + } + private static class RecordingChannelService extends WxChannelServiceHttpClientImpl { private final String response; private String url; From 0a22fcf51a2c7cb2dd8d604fdd2ea5886715c739 Mon Sep 17 00:00:00 2001 From: Binary Wang Date: Sat, 22 Aug 2026 13:40:50 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=95=86=E5=93=81?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=8E=A5=E5=8F=A3=E8=AF=84=E5=AE=A1=E6=84=8F?= =?UTF-8?q?=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../channel/api/WxChannelProductService.java | 2 +- .../product/ExternalProductMappingNewResponse.java | 14 +++++++++++++- .../WxChannelProductManagementServiceImplTest.java | 1 + 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java index 85a3ec7c5..fb019eefe 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelProductService.java @@ -344,7 +344,7 @@ AddProductThirdPartySourceResponse addProductThirdPartySource(AddProductThirdPar /** * 获取商品库存流水. * - * @param param 商品、SKU、库存类型、时间范围和分页参数;pageSize 必填,库存类型非 0 和 1 时 stockTypeId 必填 + * @param param 商品、SKU、库存类型、时间范围和分页参数;pageSize 必填,stockType 为 1 时 finderId 必填,库存类型非 0 和 1 时 stockTypeId 必填 * @return 库存流水及下一页标识 * @throws WxErrorException 调用微信接口失败 */ diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java index 29897d961..8342071a4 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/product/ExternalProductMappingNewResponse.java @@ -1,8 +1,10 @@ package me.chanjar.weixin.channel.bean.product; import com.fasterxml.jackson.annotation.JsonProperty; +import java.io.Serializable; import java.util.List; import lombok.Data; +import lombok.NoArgsConstructor; import lombok.EqualsAndHashCode; import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; @@ -13,5 +15,15 @@ public class ExternalProductMappingNewResponse extends WxChannelBaseResponse { private static final long serialVersionUID = 4536547956225312823L; @JsonProperty("attributes") - private List attributes; + private List attributes; + + /** 推荐属性. */ + @Data + @NoArgsConstructor + public static class Attribute implements Serializable { + private static final long serialVersionUID = -4072024462101489333L; + + private String key; + private String value; + } } diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java index fea7cbc16..9ccaeed3d 100644 --- a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelProductManagementServiceImplTest.java @@ -167,6 +167,7 @@ public void shouldMapAndRecommendExternalProductAttributes() throws WxErrorExcep ExternalProductMappingNewResponse result = productService(channelService).externalProductMappingNew(param); assertRequest(channelService, "/channels/ec/product/externalproductmappingnew", "{\"cat_id\":6000,\"external_category_name\":\"母婴:童鞋\",\"head_imgs\":[\"https://example.com/head\"],\"title\":\"儿童雨鞋\",\"external_attributes\":[{\"key\":\"材质\",\"value\":\"塑胶\"}]}"); + assertTrue(result.getAttributes().get(0) instanceof ExternalProductMappingNewResponse.Attribute); assertEquals(result.getAttributes().get(0).getKey(), "鞋面材质"); } From 517e8f5b7635c81cb2c6959a7c85e9436b4a216d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 22 Aug 2026 11:12:05 +0000 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=88=E5=B9=B6?= =?UTF-8?q?=E5=86=B2=E7=AA=81=EF=BC=9A=E5=88=A0=E9=99=A4=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E7=9A=84=20SPU=5FGET=5FSTOCK=5FFLOW=5FURL=20=E5=B8=B8=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com> --- .../weixin/channel/constant/WxChannelApiUrlConstants.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java index 9d494b2f3..149bd0390 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/constant/WxChannelApiUrlConstants.java @@ -192,8 +192,6 @@ public interface Spu { String SPU_GET_STOCK_BATCH_URL = "https://api.weixin.qq.com/channels/ec/product/stock/batchget"; /** 更新商品库存 */ String SPU_UPDATE_STOCK_URL = "https://api.weixin.qq.com/channels/ec/product/stock/update"; - /** 获取库存流水 */ - String SPU_GET_STOCK_FLOW_URL = "https://api.weixin.qq.com/channels/ec/product/stock/getflow"; /** 添加非卖商品 */ String GIFT_PRODUCT_ADD_URL = "https://api.weixin.qq.com/channels/ec/product/gift/add"; /** 更新非卖商品 */