From 5d14948c136608067ca195d300896b780f97321a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Sat, 18 Jul 2026 16:22:07 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20#4029=20=E3=80=90=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=8F=B7=E3=80=91=E5=A2=9E=E5=8A=A0=E5=BE=AE=E4=BF=A1=E5=B0=8F?= =?UTF-8?q?=E5=BA=97=E5=BA=97=E9=93=BA=E9=93=BE=E6=8E=A5=E4=B8=8E=E6=94=B6?= =?UTF-8?q?=E8=97=8F=E7=AE=A1=E7=90=86=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../channel/api/WxChannelBasicService.java | 28 ++++++++++ .../channel/api/WxChannelFavoriteService.java | 21 +++++++ .../weixin/channel/api/WxChannelService.java | 7 +++ .../api/impl/BaseWxChannelServiceImpl.java | 9 +++ .../api/impl/WxChannelBasicServiceImpl.java | 25 +++++++++ .../impl/WxChannelFavoriteServiceImpl.java | 29 ++++++++++ .../bean/favorite/FavoriteCountResponse.java | 38 +++++++++++++ .../channel/bean/shop/ShopH5UrlResponse.java | 22 ++++++++ .../channel/bean/shop/ShopQrCodeResponse.java | 22 ++++++++ .../bean/shop/ShopTagLinkResponse.java | 22 ++++++++ .../constant/WxChannelApiUrlConstants.java | 13 +++++ .../WxChannelFavoriteServiceImplTest.java | 35 ++++++++++++ .../WxChannelShopLinkServiceImplTest.java | 56 +++++++++++++++++++ 13 files changed, 327 insertions(+) create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFavoriteService.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImpl.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/favorite/FavoriteCountResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopH5UrlResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopQrCodeResponse.java create mode 100644 weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopTagLinkResponse.java create mode 100644 weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImplTest.java create mode 100644 weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelShopLinkServiceImplTest.java diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java index a687aaeb5..4d2133a56 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelBasicService.java @@ -5,7 +5,10 @@ import me.chanjar.weixin.channel.bean.address.AddressCodeResponse; import me.chanjar.weixin.channel.bean.image.ChannelImageInfo; import me.chanjar.weixin.channel.bean.image.ChannelImageResponse; import me.chanjar.weixin.channel.bean.image.QualificationFileResponse; +import me.chanjar.weixin.channel.bean.shop.ShopH5UrlResponse; import me.chanjar.weixin.channel.bean.shop.ShopInfoResponse; +import me.chanjar.weixin.channel.bean.shop.ShopQrCodeResponse; +import me.chanjar.weixin.channel.bean.shop.ShopTagLinkResponse; import me.chanjar.weixin.common.error.WxErrorException; /** @@ -22,6 +25,31 @@ public interface WxChannelBasicService { */ ShopInfoResponse getShopInfo() throws WxErrorException; + /** + * 获取店铺H5链接 + * + * @return 店铺H5链接 + * @throws WxErrorException 异常 + */ + ShopH5UrlResponse getShopH5Url() throws WxErrorException; + + /** + * 获取店铺二维码 + * + * @param qrcodeType 二维码类型,1:二维码;2:标准物料;3:送礼物物料 + * @return 店铺二维码 + * @throws WxErrorException 异常 + */ + ShopQrCodeResponse getShopQrCode(int qrcodeType) throws WxErrorException; + + /** + * 获取店铺口令 + * + * @return 店铺口令 + * @throws WxErrorException 异常 + */ + ShopTagLinkResponse getShopTagLink() throws WxErrorException; + /** * 上传图片 * diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFavoriteService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFavoriteService.java new file mode 100644 index 000000000..c1c03cc61 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelFavoriteService.java @@ -0,0 +1,21 @@ +package me.chanjar.weixin.channel.api; + +import me.chanjar.weixin.channel.bean.favorite.FavoriteCountResponse; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 视频号小店 收藏管理接口 + * + * @author GitHub Copilot + * @link 收藏管理接口文档 + */ +public interface WxChannelFavoriteService { + + /** + * 获取店铺收藏的人数 + * + * @return 店铺收藏人数响应 + * @throws WxErrorException 异常 + */ + FavoriteCountResponse getFavoriteCount() throws WxErrorException; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java index 754e76a62..4681e977d 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/WxChannelService.java @@ -196,4 +196,11 @@ public interface WxChannelService extends BaseWxChannelService { */ WxTalentService getTalentService(); + /** + * 收藏管理服务 + * + * @return 收藏管理服务 + */ + WxChannelFavoriteService getFavoriteService(); + } diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java index 1d40889c1..c695b6293 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/BaseWxChannelServiceImpl.java @@ -62,6 +62,7 @@ public abstract class BaseWxChannelServiceImpl implements WxChannelService private WxChannelLiveDashboardService liveDashboardService = null; private WxChannelQicService qicService = null; private WxTalentService talentService = null; + private WxChannelFavoriteService favoriteService = null; protected WxChannelConfig config; private int retrySleepMillis = 1000; @@ -491,4 +492,12 @@ public abstract class BaseWxChannelServiceImpl implements WxChannelService return talentService; } + @Override + public synchronized WxChannelFavoriteService getFavoriteService() { + if (favoriteService == null) { + favoriteService = new WxChannelFavoriteServiceImpl(this); + } + return favoriteService; + } + } diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java index 6eb699da2..45a869216 100644 --- a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelBasicServiceImpl.java @@ -2,7 +2,10 @@ package me.chanjar.weixin.channel.api.impl; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_ADDRESS_CODE; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_IMG_URL; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_SHOP_H5URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_SHOP_INFO; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_SHOP_QRCODE; +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.GET_SHOP_TAGLINK; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.IMG_UPLOAD_URL; import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Basics.UPLOAD_QUALIFICATION_FILE; @@ -16,7 +19,10 @@ import me.chanjar.weixin.channel.bean.image.ChannelImageInfo; import me.chanjar.weixin.channel.bean.image.ChannelImageResponse; import me.chanjar.weixin.channel.bean.image.QualificationFileResponse; import me.chanjar.weixin.channel.bean.image.UploadImageResponse; +import me.chanjar.weixin.channel.bean.shop.ShopH5UrlResponse; import me.chanjar.weixin.channel.bean.shop.ShopInfoResponse; +import me.chanjar.weixin.channel.bean.shop.ShopQrCodeResponse; +import me.chanjar.weixin.channel.bean.shop.ShopTagLinkResponse; import me.chanjar.weixin.channel.executor.ChannelFileUploadRequestExecutor; import me.chanjar.weixin.channel.executor.ChannelMediaDownloadRequestExecutor; import me.chanjar.weixin.channel.util.ResponseUtils; @@ -93,4 +99,23 @@ public class WxChannelBasicServiceImpl implements WxChannelBasicService { return ResponseUtils.decode(resJson, AddressCodeResponse.class); } + @Override + public ShopH5UrlResponse getShopH5Url() throws WxErrorException { + String resJson = shopService.post(GET_SHOP_H5URL, "{}"); + return ResponseUtils.decode(resJson, ShopH5UrlResponse.class); + } + + @Override + public ShopQrCodeResponse getShopQrCode(int qrcodeType) throws WxErrorException { + String reqJson = "{\"qrcode_type\":" + qrcodeType + "}"; + String resJson = shopService.post(GET_SHOP_QRCODE, reqJson); + return ResponseUtils.decode(resJson, ShopQrCodeResponse.class); + } + + @Override + public ShopTagLinkResponse getShopTagLink() throws WxErrorException { + String resJson = shopService.post(GET_SHOP_TAGLINK, "{}"); + return ResponseUtils.decode(resJson, ShopTagLinkResponse.class); + } + } diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImpl.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImpl.java new file mode 100644 index 000000000..8165f4798 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImpl.java @@ -0,0 +1,29 @@ +package me.chanjar.weixin.channel.api.impl; + +import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Favorite.GET_FAVORITE_COUNT; + +import me.chanjar.weixin.channel.api.WxChannelFavoriteService; +import me.chanjar.weixin.channel.bean.favorite.FavoriteCountResponse; +import me.chanjar.weixin.channel.util.ResponseUtils; +import me.chanjar.weixin.common.error.WxErrorException; + +/** + * 视频号小店 收藏管理接口实现 + * + * @author GitHub Copilot + */ +public class WxChannelFavoriteServiceImpl implements WxChannelFavoriteService { + + /** 微信商店服务 */ + private final BaseWxChannelServiceImpl shopService; + + public WxChannelFavoriteServiceImpl(BaseWxChannelServiceImpl shopService) { + this.shopService = shopService; + } + + @Override + public FavoriteCountResponse getFavoriteCount() throws WxErrorException { + String resJson = shopService.post(GET_FAVORITE_COUNT, "{}"); + return ResponseUtils.decode(resJson, FavoriteCountResponse.class); + } +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/favorite/FavoriteCountResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/favorite/FavoriteCountResponse.java new file mode 100644 index 000000000..9acdf93d7 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/favorite/FavoriteCountResponse.java @@ -0,0 +1,38 @@ +package me.chanjar.weixin.channel.bean.favorite; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** + * 店铺收藏人数 响应 + * + * @author GitHub Copilot + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class FavoriteCountResponse extends WxChannelBaseResponse { + + /** 店铺首页收藏用户数 */ + @JsonProperty("favor_uv_acc_shop_homepage") + private Long favorUvAccShopHomepage; + + /** 订单详情页收藏用户数 */ + @JsonProperty("favor_uv_acc_order_detail") + private Long favorUvAccOrderDetail; + + /** 商品详情页收藏用户数 */ + @JsonProperty("favor_uv_acc_product_detail") + private Long favorUvAccProductDetail; + + /** 其他场景收藏用户数 */ + @JsonProperty("favor_uv_acc_other_scene") + private Long favorUvAccOtherScene; + + /** 所有收藏用户数 */ + @JsonProperty("favor_uv_acc_all") + private Long favorUvAccAll; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopH5UrlResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopH5UrlResponse.java new file mode 100644 index 000000000..5700073c0 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopH5UrlResponse.java @@ -0,0 +1,22 @@ +package me.chanjar.weixin.channel.bean.shop; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** + * 店铺H5链接 响应 + * + * @author GitHub Copilot + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ShopH5UrlResponse extends WxChannelBaseResponse { + + /** 店铺H5链接 */ + @JsonProperty("shop_h5url") + private String shopH5url; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopQrCodeResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopQrCodeResponse.java new file mode 100644 index 000000000..1859f2e3f --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopQrCodeResponse.java @@ -0,0 +1,22 @@ +package me.chanjar.weixin.channel.bean.shop; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** + * 店铺二维码 响应 + * + * @author GitHub Copilot + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ShopQrCodeResponse extends WxChannelBaseResponse { + + /** 店铺二维码链接 */ + @JsonProperty("shop_qrcode") + private String shopQrcode; +} diff --git a/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopTagLinkResponse.java b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopTagLinkResponse.java new file mode 100644 index 000000000..8b82d2110 --- /dev/null +++ b/weixin-java-channel/src/main/java/me/chanjar/weixin/channel/bean/shop/ShopTagLinkResponse.java @@ -0,0 +1,22 @@ +package me.chanjar.weixin.channel.bean.shop; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse; + +/** + * 店铺口令 响应 + * + * @author GitHub Copilot + */ +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ShopTagLinkResponse extends WxChannelBaseResponse { + + /** 店铺微信口令 */ + @JsonProperty("shop_taglink") + private String shopTaglink; +} 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 0da45eee6..a26dff1d8 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 @@ -34,6 +34,19 @@ public class WxChannelApiUrlConstants { String GET_IMG_URL = "https://api.weixin.qq.com/channels/ec/basics/media/get"; /** 获取地址编码 */ String GET_ADDRESS_CODE = "https://api.weixin.qq.com/channels/ec/basics/addresscode/get"; + /** 获取店铺H5链接 */ + String GET_SHOP_H5URL = "https://api.weixin.qq.com/channels/ec/basics/shop/h5url/get"; + /** 获取店铺二维码 */ + String GET_SHOP_QRCODE = "https://api.weixin.qq.com/channels/ec/basics/shop/qrcode/get"; + /** 获取店铺口令 */ + String GET_SHOP_TAGLINK = "https://api.weixin.qq.com/channels/ec/basics/shop/taglink/get"; + } + + /** 收藏管理相关接口 */ + public interface Favorite { + + /** 获取店铺收藏的人数 */ + String GET_FAVORITE_COUNT = "https://api.weixin.qq.com/channels/ec/favorites/count/get"; } /** 商品类目相关接口 */ diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImplTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImplTest.java new file mode 100644 index 000000000..1e5dfd7c5 --- /dev/null +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelFavoriteServiceImplTest.java @@ -0,0 +1,35 @@ +package me.chanjar.weixin.channel.api.impl; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import com.google.inject.Inject; +import me.chanjar.weixin.channel.api.WxChannelFavoriteService; +import me.chanjar.weixin.channel.api.WxChannelService; +import me.chanjar.weixin.channel.bean.favorite.FavoriteCountResponse; +import me.chanjar.weixin.channel.test.ApiTestModule; +import me.chanjar.weixin.channel.util.JsonUtils; +import me.chanjar.weixin.common.error.WxErrorException; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * 收藏管理接口 测试 + * + * @author GitHub Copilot + */ +@Guice(modules = ApiTestModule.class) +public class WxChannelFavoriteServiceImplTest { + + @Inject + private WxChannelService channelService; + + @Test + public void testGetFavoriteCount() throws WxErrorException { + WxChannelFavoriteService favoriteService = channelService.getFavoriteService(); + FavoriteCountResponse response = favoriteService.getFavoriteCount(); + assertNotNull(response); + assertTrue(response.isSuccess()); + System.out.println(JsonUtils.encode(response)); + } +} diff --git a/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelShopLinkServiceImplTest.java b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelShopLinkServiceImplTest.java new file mode 100644 index 000000000..87785a539 --- /dev/null +++ b/weixin-java-channel/src/test/java/me/chanjar/weixin/channel/api/impl/WxChannelShopLinkServiceImplTest.java @@ -0,0 +1,56 @@ +package me.chanjar.weixin.channel.api.impl; + +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + +import com.google.inject.Inject; +import me.chanjar.weixin.channel.api.WxChannelBasicService; +import me.chanjar.weixin.channel.api.WxChannelService; +import me.chanjar.weixin.channel.bean.shop.ShopH5UrlResponse; +import me.chanjar.weixin.channel.bean.shop.ShopQrCodeResponse; +import me.chanjar.weixin.channel.bean.shop.ShopTagLinkResponse; +import me.chanjar.weixin.channel.test.ApiTestModule; +import me.chanjar.weixin.channel.util.JsonUtils; +import me.chanjar.weixin.common.error.WxErrorException; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +/** + * 店铺链接接口 测试 + * + * @author GitHub Copilot + */ +@Guice(modules = ApiTestModule.class) +public class WxChannelShopLinkServiceImplTest { + + @Inject + private WxChannelService channelService; + + @Test + public void testGetShopH5Url() throws WxErrorException { + WxChannelBasicService basicService = channelService.getBasicService(); + ShopH5UrlResponse response = basicService.getShopH5Url(); + assertNotNull(response); + assertTrue(response.isSuccess()); + System.out.println(JsonUtils.encode(response)); + } + + @Test + public void testGetShopQrCode() throws WxErrorException { + WxChannelBasicService basicService = channelService.getBasicService(); + // qrcodeType: 1=二维码, 2=标准物料, 3=送礼物物料 + ShopQrCodeResponse response = basicService.getShopQrCode(1); + assertNotNull(response); + assertTrue(response.isSuccess()); + System.out.println(JsonUtils.encode(response)); + } + + @Test + public void testGetShopTagLink() throws WxErrorException { + WxChannelBasicService basicService = channelService.getBasicService(); + ShopTagLinkResponse response = basicService.getShopTagLink(); + assertNotNull(response); + assertTrue(response.isSuccess()); + System.out.println(JsonUtils.encode(response)); + } +}