+ * 直播间操作返回结果 + * Created by lipengjun on 2020/6/29. + *+ * + * @author lipengjun (939961241@qq.com) + */ +@Data +public class WxMaLiveResult implements Serializable { + private static final long serialVersionUID = 1L; + private Integer errcode; + private String errmsg; + private Integer total; + private Integer auditId; + private Integer goodsId; + private List
+ * 直播间商品相关操作接口 + * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/liveplayer/commodity-api.html + * Created by lipengjun on 2020/6/29. + *+ * + * @author lipengjun (939961241@qq.com) + */ +public interface WxMaLiveGoodsService { + String ADD_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/goods/add"; + String RESET_AUDIT_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/goods/resetaudit"; + String AUDIT_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/goods/audit"; + String DELETE_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/goods/delete"; + String UPDATE_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/goods/update"; + String GET_GOODS_WARE_HOUSE = "https://api.weixin.qq.com/wxa/business/getgoodswarehouse"; + String GET_APPROVED_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/goods/getapproved"; + + /** + * 商品添加并提审 + *
+ * 调用此接口上传并提审需要直播的商品信息,审核通过后商品录入【小程序直播】商品库 + * 注意:开发者必须保存【商品ID】与【审核单ID】,如果丢失,则无法调用其他相关接口 + * 调用额度:500次/一天 + * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/goods/add?access_token=ACCESS_TOKEN + *+ * + * @param goods 商品 + * @return 返回auditId、goodsId + * @throws WxErrorException . + */ + WxMaLiveResult addGoods(WxMaLiveInfo.Goods goods) throws WxErrorException; + + /** + * 撤回审核 + *
+ * 调用此接口,可撤回直播商品的提审申请,消耗的提审次数不返还 + * 调用额度:500次/一天 + * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/goods/resetaudit?access_token=ACCESS_TOKEN + *+ * @param auditId 审核单ID + * @param goodsId 商品ID + * @return 撤回审核是否成功 + * @throws WxErrorException . + */ + boolean resetAudit(Integer auditId, Integer goodsId) throws WxErrorException; + + /** + * 重新提交审核 + *+ * 调用此接口,可撤回直播商品的提审申请,消耗的提审次数不返还 + * 调用额度:500次/一天(与接口'商品添加并提审'共用500次限制) + * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/goods/audit?access_token=ACCESS_TOKEN + *+ * @param goodsId 商品ID + * @return 审核单ID + * @throws WxErrorException . + */ + String auditGoods(Integer goodsId) throws WxErrorException; + + /** + * 删除商品 + *+ * 调用此接口,可删除【小程序直播】商品库中的商品,删除后直播间上架的该商品也将被同步删除,不可恢复; + * 调用额度:1000次/一天 + * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/goods/delete?access_token=ACCESS_TOKEN + *+ * @param goodsId 商品ID + * @return 删除商品是否成功 + * @throws WxErrorException . + */ + boolean deleteGoods(Integer goodsId) throws WxErrorException; + + /** + * 更新商品 + *+ * 调用此接口可以更新商品信息,审核通过的商品仅允许更新价格类型与价格,审核中的商品不允许更新,未审核的商品允许更新所有字段, 只传入需要更新的字段。 + * 调用额度:1000次/一天 + * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/goods/update?access_token=ACCESS_TOKEN + *+ * + * @param goods 商品 + * @return 更新商品是否成功 + * @throws WxErrorException . + */ + boolean updateGoods(WxMaLiveInfo.Goods goods) throws WxErrorException; + + /** + * 获取商品状态 + *+ * 调用此接口可获取商品的信息与审核状态 + * 调用额度:1000次/一天 + * http请求方式:POST https://api.weixin.qq.com/wxa/business/getgoodswarehouse?access_token=ACCESS_TOKEN + *+ * @param goodsIds 商品ID集 + * @return 商品状态信息 + * @throws WxErrorException . + */ + WxMaLiveResult getGoodsWareHouse(ListgoodsIds) throws WxErrorException; + + /** + * 获取商品列表 + * + * 调用此接口可获取商品列表 + * 调用额度:10000次/一天 + * http请求方式:GET https://api.weixin.qq.com/wxaapi/broadcast/goods/getapproved?access_token=ACCESS_TOKEN + *+ * @param offset 分页条数起点 + * @param limit 分页大小,默认30,不超过100 + * @param status 商品状态,0:未审核。1:审核中,2:审核通过,3:审核驳回 + * @return 商品列表 + * @throws WxErrorException . + */ + WxMaLiveResult getApprovedGoods(Integer offset, Integer limit, Integer status) throws WxErrorException; +} + diff --git a/yshop-weixin/src/main/java/co/yixiang/mp/service/WxMaLiveService.java b/yshop-weixin/src/main/java/co/yixiang/mp/service/WxMaLiveService.java new file mode 100644 index 00000000..026718ff --- /dev/null +++ b/yshop-weixin/src/main/java/co/yixiang/mp/service/WxMaLiveService.java @@ -0,0 +1,94 @@ +package co.yixiang.mp.service; + +import co.yixiang.mp.bean.WxMaLiveInfo; +import co.yixiang.mp.bean.WxMaLiveResult; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.util.List; + +/** + *+ * 直播相关操作接口. + * Created by yjwang on 2020/4/5. + *+ * + * @author yjwang + */ +public interface WxMaLiveService { + String GET_LIVE_INFO = "https://api.weixin.qq.com/wxa/business/getliveinfo"; + String CREATE_ROOM = "https://api.weixin.qq.com/wxaapi/broadcast/room/create"; + String ADD_GOODS = "https://api.weixin.qq.com/wxaapi/broadcast/room/addgoods"; + + /** + * 创建直播间 + *+ * 调用此接口创建直播间,创建成功后将在直播间列表展示,调用额度:10000次/一天 + * 文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/liveplayer/studio-api.html#1 + * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/room/create?access_token=ACCESS_TOKEN + *+ * + * @param roomInfo 直播间信息 + * @return . + * @throws WxErrorException . + */ + Integer createRoom(WxMaLiveInfo.RoomInfo roomInfo) throws WxErrorException; + + /** + * 获取直播房间列表.(分页) + * + * @param start 起始拉取房间,start = 0 表示从第 1 个房间开始拉取 + * @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内 + * @return . + * @throws WxErrorException . + */ + WxMaLiveResult getLiveInfo(Integer start, Integer limit) throws WxErrorException; + + /** + * 获取所有直播间信息(没有分页直接获取全部) + * + * @return . + * @throws WxErrorException . + */ + ListgetLiveInfos() throws WxErrorException; + + /** + * 获取直播房间回放数据信息. + * + * @param action 获取回放 + * @param roomId 直播间 id + * @param start 起始拉取视频,start = 0 表示从第 1 个视频片段开始拉取 + * @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内 + * @return . + * @throws WxErrorException . + */ + WxMaLiveResult getLiveReplay(String action, Integer roomId, Integer start, Integer limit) throws WxErrorException; + + /** + * 获取直播房间回放数据信息. + * + * 获取回放 (默认:get_replay) + * + * @param roomId 直播间 id + * @param start 起始拉取视频,start = 0 表示从第 1 个视频片段开始拉取 + * @param limit 每次拉取的个数上限,不要设置过大,建议 100 以内 + * @return . + * @throws WxErrorException . + */ + WxMaLiveResult getLiveReplay(Integer roomId, Integer start, Integer limit) throws WxErrorException; + + /** + * 直播间导入商品 + *
+ * 调用接口往指定直播间导入已入库的商品 + * 调用频率 + * 调用额度:10000次/一天 + *
+ * http请求方式:POST https://api.weixin.qq.com/wxaapi/broadcast/room/addgoods?access_token=ACCESS_TOKEN + *
+ * @param roomId 房间ID + * @param goodsIds 数组列表,可传入多个,里面填写 商品 ID + * @return 导入商品是否成功 + * @throws WxErrorException . + */ + boolean addGoodsToRoom(Integer roomId, ListgoodsIds) throws WxErrorException; +} diff --git a/yshop-weixin/src/main/java/co/yixiang/mp/service/impl/WxMaLiveGoodsServiceImpl.java b/yshop-weixin/src/main/java/co/yixiang/mp/service/impl/WxMaLiveGoodsServiceImpl.java new file mode 100644 index 00000000..2141c509 --- /dev/null +++ b/yshop-weixin/src/main/java/co/yixiang/mp/service/impl/WxMaLiveGoodsServiceImpl.java @@ -0,0 +1,130 @@ +package co.yixiang.mp.service.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import co.yixiang.mp.bean.WxMaLiveInfo; +import co.yixiang.mp.bean.WxMaLiveResult; +import co.yixiang.mp.config.WxMaConfiguration; +import co.yixiang.mp.service.WxMaLiveGoodsService; +import co.yixiang.utils.GsonParser; +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.AllArgsConstructor; +import me.chanjar.weixin.common.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@AllArgsConstructor +public class WxMaLiveGoodsServiceImpl implements WxMaLiveGoodsService { + + @Override + public WxMaLiveResult addGoods(WxMaLiveInfo.Goods goods) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("goodsInfo", goods); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(ADD_GOODS, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaLiveResult.fromJson(jsonObject.toString()); + } + + @Override + public boolean resetAudit(Integer auditId, Integer goodsId) throws WxErrorException { + Map map = new HashMap<>(4); + map.put("auditId", auditId); + map.put("goodsId", goodsId); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(RESET_AUDIT_GOODS, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return true; + } + + @Override + public String auditGoods(Integer goodsId) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("goodsId", goodsId); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(AUDIT_GOODS, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return jsonObject.get("auditId").getAsString(); + } + + @Override + public boolean deleteGoods(Integer goodsId) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("goodsId", goodsId); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(DELETE_GOODS, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return true; + } + + @Override + public boolean updateGoods(WxMaLiveInfo.Goods goods) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("goodsInfo", goods); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(UPDATE_GOODS, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return true; + } + + @Override + public WxMaLiveResult getGoodsWareHouse(List goodsIds) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("goods_ids", goodsIds); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(GET_GOODS_WARE_HOUSE, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return WxMaLiveResult.fromJson(jsonObject.toString()); + } + + @Override + public WxMaLiveResult getApprovedGoods(Integer offset, Integer limit, Integer status) throws WxErrorException { + ImmutableMap params = ImmutableMap.of("status", status, "offset", offset, "limit", limit); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.get(GET_APPROVED_GOODS, Joiner.on("&").withKeyValueSeparator("=").join(params)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + JsonArray goodsArr = jsonObject.getAsJsonArray("goods"); + if (goodsArr.size() > 0) { + for (int i = 0; i < goodsArr.size(); i++) { + // 接口返回key是驼峰 + JsonObject goods = (JsonObject) goodsArr.get(i); + goods.addProperty("goods_id", goods.get("goodsId").getAsInt()); + goods.addProperty("cover_img_url", goods.get("coverImgUrl").getAsString()); + goods.addProperty("price_type", goods.get("priceType").getAsInt()); + goods.addProperty("third_party_tag", goods.get("thirdPartyTag").getAsInt()); + goods.addProperty("audit_status", status); + } + } + return WxMaLiveResult.fromJson(jsonObject.toString()); + } + +} diff --git a/yshop-weixin/src/main/java/co/yixiang/mp/service/impl/WxMaLiveServiceImpl.java b/yshop-weixin/src/main/java/co/yixiang/mp/service/impl/WxMaLiveServiceImpl.java new file mode 100644 index 00000000..88b8a0c8 --- /dev/null +++ b/yshop-weixin/src/main/java/co/yixiang/mp/service/impl/WxMaLiveServiceImpl.java @@ -0,0 +1,121 @@ +package co.yixiang.mp.service.impl; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.util.json.WxMaGsonBuilder; +import co.yixiang.mp.bean.WxMaLiveInfo; +import co.yixiang.mp.bean.WxMaLiveResult; +import co.yixiang.mp.config.WxMaConfiguration; +import co.yixiang.mp.service.WxMaLiveService; +import co.yixiang.utils.GsonParser; +import com.google.gson.JsonObject; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.WxType; +import me.chanjar.weixin.common.error.WxError; +import me.chanjar.weixin.common.error.WxErrorException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + * Created by yjwang on 2020/4/5. + *+ * + * @author yjwang + */ +@Slf4j +@AllArgsConstructor +public class WxMaLiveServiceImpl implements WxMaLiveService { + + + @Override + public Integer createRoom(WxMaLiveInfo.RoomInfo roomInfo) throws WxErrorException { + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(CREATE_ROOM, WxMaGsonBuilder.create().toJson(roomInfo)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return jsonObject.get("roomId").getAsInt(); + } + + @Override + public WxMaLiveResult getLiveInfo(Integer start, Integer limit) throws WxErrorException { + JsonObject jsonObject = getLiveInfo(start, limit, null); + return WxMaLiveResult.fromJson(jsonObject.toString()); + } + + @Override + public ListgetLiveInfos() throws WxErrorException { + List results = new ArrayList<>(); + int start = 0; + Integer limit = 80; + Integer total = 0; + WxMaLiveResult liveInfo; + do { + if (total != 0 && total <= start) { + break; + } + liveInfo = getLiveInfo(start, limit); + if (liveInfo == null) { + return null; + } + results.addAll(liveInfo.getRoomInfos()); + total = liveInfo.getTotal(); + start = results.size(); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + log.error("InterruptedException", e); + } + } while (results.size() <= total); + + return results; + } + + @Override + public WxMaLiveResult getLiveReplay(String action, Integer roomId, Integer start, Integer limit) throws WxErrorException { + Map map = new HashMap<>(4); + map.put("action", action); + map.put("room_id", roomId); + JsonObject jsonObject = getLiveInfo(start, limit, map); + return WxMaLiveResult.fromJson(jsonObject.toString()); + } + + @Override + public WxMaLiveResult getLiveReplay(Integer roomId, Integer start, Integer limit) throws WxErrorException { + return getLiveReplay("get_replay", roomId, start, limit); + } + + @Override + public boolean addGoodsToRoom(Integer roomId, List goodsIds) throws WxErrorException { + Map map = new HashMap<>(2); + map.put("roomId", roomId); + map.put("ids", goodsIds); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(ADD_GOODS, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return true; + } + + private JsonObject getLiveInfo(Integer start, Integer limit, Map map) throws WxErrorException { + if (map == null) { + map = new HashMap(2); + } + map.put("start", start); + map.put("limit", limit); + WxMaService wxMaService = WxMaConfiguration.getWxMaService(); + String responseContent = wxMaService.post(GET_LIVE_INFO, WxMaGsonBuilder.create().toJson(map)); + JsonObject jsonObject = GsonParser.parse(responseContent); + if (jsonObject.get("errcode").getAsInt() != 0) { + throw new WxErrorException(WxError.fromJson(responseContent, WxType.MiniApp)); + } + return jsonObject; + } +}