1
0
mirror of synced 2026-10-26 02:06:10 +08:00

🆕 #4030 【视频号】新增微信小店赠品与买赠活动模块接口支持

This commit is contained in:
Copilot
2026-07-18 16:38:21 +08:00
committed by GitHub
parent 5d14948c13
commit 5f9fe24d42
12 changed files with 542 additions and 0 deletions

View File

@@ -6,6 +6,13 @@ import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
import me.chanjar.weixin.channel.bean.limit.LimitTaskAddResponse;
import me.chanjar.weixin.channel.bean.limit.LimitTaskListResponse;
import me.chanjar.weixin.channel.bean.limit.LimitTaskParam;
import me.chanjar.weixin.channel.bean.product.GiftActivityAddResponse;
import me.chanjar.weixin.channel.bean.product.GiftActivityInfo;
import me.chanjar.weixin.channel.bean.product.GiftProductAddResponse;
import me.chanjar.weixin.channel.bean.product.GiftProductGetResponse;
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.SkuStockBatchResponse;
import me.chanjar.weixin.channel.bean.product.SkuStockResponse;
import me.chanjar.weixin.channel.bean.product.SpuFastInfo;
@@ -206,6 +213,92 @@ public interface WxChannelProductService {
*/
ProductTagLinkResponse getProductTagLink(String productId) throws WxErrorException;
/**
* 添加非卖商品
*
* @param info 赠品信息
* @return 添加赠品响应
* @throws WxErrorException 异常
*/
GiftProductAddResponse addGiftProduct(GiftProductInfo info) throws WxErrorException;
/**
* 更新非卖商品
*
* @param info 赠品信息
* @return 操作响应
* @throws WxErrorException 异常
*/
WxChannelBaseResponse updateGiftProduct(GiftProductInfo info) throws WxErrorException;
/**
* 在售商品转赠品
*
* @param productId 商品ID
* @return 操作响应
* @throws WxErrorException 异常
*/
WxChannelBaseResponse setProductAsGift(String productId) throws WxErrorException;
/**
* 获取赠品
*
* @param productId 赠品商品ID
* @return 赠品详情响应
* @throws WxErrorException 异常
*/
GiftProductGetResponse getGiftProduct(String productId) throws WxErrorException;
/**
* 获取赠品列表
*
* @param param 查询参数
* @return 赠品列表
* @throws WxErrorException 异常
*/
GiftProductListResponse listGiftProduct(GiftProductListParam param) throws WxErrorException;
/**
* 更新赠品库存
*
* @param productId 赠品商品ID
* @param skuId 赠品sku_id
* @param diffType 修改类型 1增加 2减少 3设置
* 建议使用1或2,不建议使用3,因为使用3在高并发场景可能会出现预期外表现
* @param num 增加、减少或者设置的库存值
* @return 操作响应
* @throws WxErrorException 异常
*/
WxChannelBaseResponse updateGiftStock(String productId, String skuId, Integer diffType, Integer num)
throws WxErrorException;
/**
* 创建赠品活动
*
* @param info 活动信息
* @return 创建赠品活动响应
* @throws WxErrorException 异常
*/
GiftActivityAddResponse addGiftActivity(GiftActivityInfo info) throws WxErrorException;
/**
* 删除赠品活动
*
* @param activityId 活动ID
* @return 操作响应
* @throws WxErrorException 异常
*/
WxChannelBaseResponse deleteGiftActivity(String activityId) throws WxErrorException;
/**
* 停止赠品活动
*
* @param activityId 活动ID
* @return 操作响应
* @throws WxErrorException 异常
*/
WxChannelBaseResponse stopGiftActivity(String activityId) throws WxErrorException;
/**
* 添加限时抢购任务
*

View File

@@ -4,6 +4,15 @@ package me.chanjar.weixin.channel.api.impl;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.ADD_LIMIT_TASK_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.CANCEL_AUDIT_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.DELETE_LIMIT_TASK_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_ACTIVITY_ADD_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_ACTIVITY_DELETE_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_ACTIVITY_STOP_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_PRODUCT_ADD_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_PRODUCT_GET_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_PRODUCT_LIST_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.GIFT_PRODUCT_ON_SALE_SET_URL;
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_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.Spu.SPU_AUDIT_FREE_UPDATE_URL;
@@ -29,6 +38,14 @@ import me.chanjar.weixin.channel.bean.limit.LimitTaskAddResponse;
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.GiftActivityAddParam;
import me.chanjar.weixin.channel.bean.product.GiftActivityAddResponse;
import me.chanjar.weixin.channel.bean.product.GiftActivityInfo;
import me.chanjar.weixin.channel.bean.product.GiftProductAddResponse;
import me.chanjar.weixin.channel.bean.product.GiftProductGetResponse;
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.SkuStockBatchParam;
import me.chanjar.weixin.channel.bean.product.SkuStockBatchResponse;
import me.chanjar.weixin.channel.bean.product.SkuStockParam;
@@ -211,6 +228,72 @@ public class WxChannelProductServiceImpl implements WxChannelProductService {
return ResponseUtils.decode(resJson, ProductTagLinkResponse.class);
}
@Override
public GiftProductAddResponse addGiftProduct(GiftProductInfo info) throws WxErrorException {
String reqJson = JsonUtils.encode(info);
String resJson = shopService.post(GIFT_PRODUCT_ADD_URL, reqJson);
return ResponseUtils.decode(resJson, GiftProductAddResponse.class);
}
@Override
public WxChannelBaseResponse updateGiftProduct(GiftProductInfo info) throws WxErrorException {
String reqJson = JsonUtils.encode(info);
String resJson = shopService.post(GIFT_PRODUCT_UPDATE_URL, reqJson);
return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
}
@Override
public WxChannelBaseResponse setProductAsGift(String productId) throws WxErrorException {
String reqJson = "{\"product_id\":\"" + productId + "\"}";
String resJson = shopService.post(GIFT_PRODUCT_ON_SALE_SET_URL, reqJson);
return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
}
@Override
public GiftProductGetResponse getGiftProduct(String productId) throws WxErrorException {
String reqJson = "{\"product_id\":\"" + productId + "\"}";
String resJson = shopService.post(GIFT_PRODUCT_GET_URL, reqJson);
return ResponseUtils.decode(resJson, GiftProductGetResponse.class);
}
@Override
public GiftProductListResponse listGiftProduct(GiftProductListParam param) throws WxErrorException {
String reqJson = JsonUtils.encode(param);
String resJson = shopService.post(GIFT_PRODUCT_LIST_URL, reqJson);
return ResponseUtils.decode(resJson, GiftProductListResponse.class);
}
@Override
public WxChannelBaseResponse updateGiftStock(String productId, String skuId, Integer diffType, Integer num)
throws WxErrorException {
SkuStockParam param = new SkuStockParam(productId, skuId, diffType, num);
String reqJson = JsonUtils.encode(param);
String resJson = shopService.post(GIFT_PRODUCT_STOCK_UPDATE_URL, reqJson);
return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
}
@Override
public GiftActivityAddResponse addGiftActivity(GiftActivityInfo info) throws WxErrorException {
GiftActivityAddParam param = new GiftActivityAddParam(info);
String reqJson = JsonUtils.encode(param);
String resJson = shopService.post(GIFT_ACTIVITY_ADD_URL, reqJson);
return ResponseUtils.decode(resJson, GiftActivityAddResponse.class);
}
@Override
public WxChannelBaseResponse deleteGiftActivity(String activityId) throws WxErrorException {
String reqJson = "{\"activity_id\":\"" + activityId + "\"}";
String resJson = shopService.post(GIFT_ACTIVITY_DELETE_URL, reqJson);
return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
}
@Override
public WxChannelBaseResponse stopGiftActivity(String activityId) throws WxErrorException {
String reqJson = "{\"activity_id\":\"" + activityId + "\"}";
String resJson = shopService.post(GIFT_ACTIVITY_STOP_URL, reqJson);
return ResponseUtils.decode(resJson, WxChannelBaseResponse.class);
}
@Override
public LimitTaskAddResponse addLimitTask(LimitTaskParam param) throws WxErrorException {
String reqJson = JsonUtils.encode(param);

View File

@@ -0,0 +1,23 @@
package me.chanjar.weixin.channel.bean.product;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 创建买赠活动参数
*
* @author GitHub Copilot
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GiftActivityAddParam implements Serializable {
private static final long serialVersionUID = -3332952823917162308L;
@JsonProperty("gift_activity")
private GiftActivityInfo giftActivity;
}

View File

@@ -0,0 +1,23 @@
package me.chanjar.weixin.channel.bean.product;
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 GiftActivityAddResponse extends WxChannelBaseResponse {
private static final long serialVersionUID = -4527079816331082871L;
@JsonProperty("activity_id")
private String activityId;
}

View File

@@ -0,0 +1,92 @@
package me.chanjar.weixin.channel.bean.product;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.util.List;
import lombok.Data;
/**
* 买赠活动信息
*
* @author GitHub Copilot
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GiftActivityInfo implements Serializable {
private static final long serialVersionUID = 3970308144375119175L;
@JsonProperty("activity_id")
private String activityId;
@JsonProperty("title")
private String title;
@JsonProperty("start_time")
private Long startTime;
@JsonProperty("end_time")
private Long endTime;
@JsonProperty("detail")
private Detail detail;
@Data
public static class Detail implements Serializable {
private static final long serialVersionUID = 1019081831733485084L;
@JsonProperty("show_scene")
private Integer showScene;
@JsonProperty("receive_limit")
private ReceiveLimit receiveLimit;
@JsonProperty("main_products")
private List<MainProduct> mainProducts;
@JsonProperty("gift_set")
private GiftSet giftSet;
}
@Data
public static class ReceiveLimit implements Serializable {
private static final long serialVersionUID = 3332293571373311829L;
@JsonProperty("is_limited")
private Boolean limited;
@JsonProperty("limit_num")
private Integer limitNum;
}
@Data
public static class MainProduct implements Serializable {
private static final long serialVersionUID = 6368866030784193437L;
@JsonProperty("product_id")
private String productId;
}
@Data
public static class GiftSet implements Serializable {
private static final long serialVersionUID = 8473755235926932739L;
@JsonProperty("gift_items")
private List<GiftItem> giftItems;
@JsonProperty("gift_set_num")
private Integer giftSetNum;
}
@Data
public static class GiftItem implements Serializable {
private static final long serialVersionUID = -4130391476834450014L;
@JsonProperty("gift_id")
private String giftId;
@JsonProperty("give_num")
private Integer giveNum;
}
}

View File

@@ -0,0 +1,24 @@
package me.chanjar.weixin.channel.bean.product;
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 GiftProductAddResponse extends WxChannelBaseResponse {
private static final long serialVersionUID = -5971026809157610975L;
/** 赠品商品ID */
@JsonProperty("product_id")
private String productId;
}

View File

@@ -0,0 +1,28 @@
package me.chanjar.weixin.channel.bean.product;
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 GiftProductGetResponse extends WxChannelBaseResponse {
private static final long serialVersionUID = 5331169221157446692L;
/** 赠品线上数据 */
@JsonProperty("product")
private GiftProductInfo product;
/** 赠品草稿数据 */
@JsonProperty("edit_product")
private GiftProductInfo editProduct;
}

View File

@@ -0,0 +1,11 @@
package me.chanjar.weixin.channel.bean.product;
/**
* 赠品商品信息
*
* @author GitHub Copilot
*/
public class GiftProductInfo extends SpuUpdateInfo {
private static final long serialVersionUID = -4366133550331058445L;
}

View File

@@ -0,0 +1,31 @@
package me.chanjar.weixin.channel.bean.product;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import me.chanjar.weixin.channel.bean.base.StreamPageParam;
/**
* 赠品列表查询参数
*
* @author GitHub Copilot
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GiftProductListParam extends StreamPageParam {
private static final long serialVersionUID = 7583500622060651067L;
/** 赠品状态 */
@JsonProperty("status")
private Integer status;
public GiftProductListParam() {
}
public GiftProductListParam(Integer pageSize, String nextKey, Integer status) {
this.pageSize = pageSize;
this.nextKey = nextKey;
this.status = status;
}
}

View File

@@ -0,0 +1,33 @@
package me.chanjar.weixin.channel.bean.product;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
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 GiftProductListResponse extends WxChannelBaseResponse {
private static final long serialVersionUID = -2734111694780970778L;
/** 总数 */
@JsonProperty("total_num")
private Integer totalNum;
/** 本次翻页的上下文,用于请求下一页 */
@JsonProperty("next_key")
private String nextKey;
/** 赠品商品 id 列表 */
@JsonProperty("product_ids")
private List<String> ids;
}

View File

@@ -166,6 +166,24 @@ public class WxChannelApiUrlConstants {
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 GIFT_PRODUCT_ADD_URL = "https://api.weixin.qq.com/channels/ec/product/gift/add";
/** 更新非卖商品 */
String GIFT_PRODUCT_UPDATE_URL = "https://api.weixin.qq.com/channels/ec/product/gift/update";
/** 在售商品转赠品 */
String GIFT_PRODUCT_ON_SALE_SET_URL = "https://api.weixin.qq.com/channels/ec/product/gift/onsale/set";
/** 获取赠品 */
String GIFT_PRODUCT_GET_URL = "https://api.weixin.qq.com/channels/ec/product/gift/get";
/** 获取赠品列表 */
String GIFT_PRODUCT_LIST_URL = "https://api.weixin.qq.com/channels/ec/product/gift/list/get";
/** 更新赠品库存 */
String GIFT_PRODUCT_STOCK_UPDATE_URL = "https://api.weixin.qq.com/channels/ec/product/gift/stock/update";
/** 创建赠品活动 */
String GIFT_ACTIVITY_ADD_URL = "https://api.weixin.qq.com/channels/ec/product/activity/add";
/** 删除赠品活动 */
String GIFT_ACTIVITY_DELETE_URL = "https://api.weixin.qq.com/channels/ec/product/activity/del";
/** 停止赠品活动 */
String GIFT_ACTIVITY_STOP_URL = "https://api.weixin.qq.com/channels/ec/product/activity/stop";
/** 添加限时抢购任务 */
String ADD_LIMIT_TASK_URL = "https://api.weixin.qq.com/channels/ec/product/limiteddiscounttask/add";
/** 拉取限时抢购任务列表 */

View File

@@ -12,6 +12,13 @@ import me.chanjar.weixin.channel.bean.base.WxChannelBaseResponse;
import me.chanjar.weixin.channel.bean.limit.LimitTaskAddResponse;
import me.chanjar.weixin.channel.bean.limit.LimitTaskListResponse;
import me.chanjar.weixin.channel.bean.limit.LimitTaskParam;
import me.chanjar.weixin.channel.bean.product.GiftActivityAddResponse;
import me.chanjar.weixin.channel.bean.product.GiftActivityInfo;
import me.chanjar.weixin.channel.bean.product.GiftProductAddResponse;
import me.chanjar.weixin.channel.bean.product.GiftProductGetResponse;
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.SkuStockBatchResponse;
import me.chanjar.weixin.channel.bean.product.SkuStockResponse;
import me.chanjar.weixin.channel.bean.product.SpuGetResponse;
@@ -212,4 +219,80 @@ public class WxChannelProductServiceImplTest {
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testAddGiftProduct() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
GiftProductInfo info = new GiftProductInfo();
GiftProductAddResponse response = productService.addGiftProduct(info);
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testUpdateGiftProduct() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
GiftProductInfo info = new GiftProductInfo();
WxChannelBaseResponse response = productService.updateGiftProduct(info);
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testSetProductAsGift() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
WxChannelBaseResponse response = productService.setProductAsGift("");
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testGetGiftProduct() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
GiftProductGetResponse response = productService.getGiftProduct("");
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testListGiftProduct() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
GiftProductListParam param = new GiftProductListParam(10, null, null);
GiftProductListResponse response = productService.listGiftProduct(param);
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testUpdateGiftStock() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
WxChannelBaseResponse response = productService.updateGiftStock("", "", 1, 10);
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testAddGiftActivity() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
GiftActivityInfo info = new GiftActivityInfo();
GiftActivityAddResponse response = productService.addGiftActivity(info);
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testDeleteGiftActivity() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
WxChannelBaseResponse response = productService.deleteGiftActivity("");
assertNotNull(response);
assertTrue(response.isSuccess());
}
@Test
public void testStopGiftActivity() throws WxErrorException {
WxChannelProductService productService = channelService.getProductService();
WxChannelBaseResponse response = productService.stopGiftActivity("");
assertNotNull(response);
assertTrue(response.isSuccess());
}
}