From 2c2d287b37ddc307d74576a48460e4ffd1a0b247 Mon Sep 17 00:00:00 2001 From: 0katekate0 <1960779692@qq.com> Date: Mon, 20 Dec 2021 23:14:04 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=B1=BB=E5=AF=BC=E5=85=A5=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../external/WxCpUserExternalContactInfoTest.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalContactInfoTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalContactInfoTest.java index d0003ccd8..ce5475358 100644 --- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalContactInfoTest.java +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/external/WxCpUserExternalContactInfoTest.java @@ -1,8 +1,13 @@ package me.chanjar.weixin.cp.bean.external; +import com.google.gson.reflect.TypeToken; +import lombok.val; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.external.contact.ExternalContact; import me.chanjar.weixin.cp.bean.external.contact.FollowedUser; import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; import org.testng.annotations.*; import java.util.List; @@ -78,8 +83,8 @@ public class WxCpUserExternalContactInfoTest { " }\n" + " ]\n" + "}"; - - final String testJson = "{\n" + + + final String testJson = "{\n" + " \"errcode\": 0,\n" + " \"errmsg\": \"ok\",\n" + " \"department\": [\n" + @@ -114,7 +119,7 @@ public class WxCpUserExternalContactInfoTest { String toJson = depart.toJson(); // 测试企业微信字段返回 - List department = WxCpGsonBuilder.create().fromJson(GsonParser.parse(two).get("department"), new TypeToken>() { + List department = WxCpGsonBuilder.create().fromJson(GsonParser.parse(testJson).get("department"), new TypeToken>() { }.getType()); final WxCpExternalContactInfo contactInfo = WxCpExternalContactInfo.fromJson(json); -- Gitee From b7645483cbcbf799ca6823997d7f60176b99d8d3 Mon Sep 17 00:00:00 2001 From: 0katekate0 <1960779692@qq.com> Date: Wed, 22 Dec 2021 00:17:18 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E3=80=90=E4=BC=81=E4=B8=9A=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E3=80=91=E5=A2=9E=E5=8A=A0=E7=9B=B4=E6=92=AD=E5=85=AC?= =?UTF-8?q?=E5=85=B1=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/cp/api/WxCpLivingService.java | 28 ++++++++ .../me/chanjar/weixin/cp/api/WxCpService.java | 7 ++ .../cp/api/impl/BaseWxCpServiceImpl.java | 6 ++ .../cp/api/impl/WxCpLivingServiceImpl.java | 33 ++++++++++ .../cp/bean/living/WxCpGetLivingCode.java | 28 ++++++++ .../weixin/cp/constant/WxCpApiPathConsts.java | 6 ++ .../weixin/cp/bean/living/WxCpLivingTest.java | 66 +++++++++++++++++++ 7 files changed, 174 insertions(+) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java create mode 100644 weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java new file mode 100644 index 000000000..2070971ae --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.cp.api; + +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode; +import me.chanjar.weixin.cp.bean.oa.WxCpOaSchedule; + +import java.util.List; + +/** + * 企业微信直播接口. + * 官方文档:https://work.weixin.qq.com/api/doc/90000/90135/93633 + * + * @author Wang_Wong + * @date 2021-12-21 + */ +public interface WxCpLivingService { + + /** + * 获取微信观看直播凭证 + * 详情请见: https://work.weixin.qq.com/api/doc/90000/90135/93641 + * + * @param codeParam 直播凭证请求参数 + * @return living_code 微信观看直播凭证 + * @throws WxErrorException the wx error exception + */ + String getLivingCode(WxCpGetLivingCode codeParam) throws WxErrorException; + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java index 94cd21263..123697b8e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java @@ -392,6 +392,13 @@ public interface WxCpService extends WxService { */ WxCpOaService getOaService(); + /** + * 获取直播相关接口的服务类对象 + * + * @return the Living service + */ + WxCpLivingService getLivingService(); + /** * 获取日历相关接口的服务类对象 * diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java index 89221f1a1..210d54f54 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java @@ -49,6 +49,7 @@ public abstract class BaseWxCpServiceImpl implements WxCpService, RequestH private WxCpTagService tagService = new WxCpTagServiceImpl(this); private WxCpAgentService agentService = new WxCpAgentServiceImpl(this); private WxCpOaService oaService = new WxCpOaServiceImpl(this); + private WxCpLivingService livingService = new WxCpLivingServiceImpl(this); private WxCpTaskCardService taskCardService = new WxCpTaskCardServiceImpl(this); private WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(this); private WxCpGroupRobotService groupRobotService = new WxCpGroupRobotServiceImpl(this); @@ -477,6 +478,11 @@ public abstract class BaseWxCpServiceImpl implements WxCpService, RequestH return oaService; } + @Override + public WxCpLivingService getLivingService() { + return livingService; + } + @Override public WxCpOaCalendarService getOaCalendarService() { return this.oaCalendarService; diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java new file mode 100644 index 000000000..9819b2a8a --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java @@ -0,0 +1,33 @@ +package me.chanjar.weixin.cp.api.impl; + +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.util.json.GsonHelper; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.cp.api.WxCpLivingService; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode; + +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*; + +/** + * 企业微信直播接口实现类. + * + * @author Wang_Wong + * @date 2021-12-21 + */ +@Slf4j +@RequiredArgsConstructor +public class WxCpLivingServiceImpl implements WxCpLivingService { + private final WxCpService cpService; + + @Override + public String getLivingCode(@NonNull WxCpGetLivingCode livingCode) throws WxErrorException { + final String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_CODE); + String responseContent = this.cpService.post(apiUrl, livingCode.toJson()); + return GsonHelper.getString(GsonParser.parse(responseContent), "living_code"); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java new file mode 100644 index 000000000..9281c0a4d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.cp.bean.living; + +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 微信观看直播凭证请求体. + * + * @author Wang_Wong + */ +@Data +public class WxCpGetLivingCode implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + private String livingid; + private String openid; + + public static WxCpGetLivingCode fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpGetLivingCode.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java index 710f7f6a7..77152b76e 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java @@ -118,6 +118,12 @@ public interface WxCpApiPathConsts { String COPY_TEMPLATE = "/cgi-bin/oa/approval/copytemplate"; } + interface Living { + String GET_LIVING_CODE = "/cgi-bin/living/get_living_code"; + String GET_LIVING_INFO = "/cgi-bin/living/get_living_info"; + String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat"; + } + interface Tag { String TAG_CREATE = "/cgi-bin/tag/create"; String TAG_UPDATE = "/cgi-bin/tag/update"; diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java new file mode 100644 index 000000000..1c9f9eb72 --- /dev/null +++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java @@ -0,0 +1,66 @@ +package me.chanjar.weixin.cp.bean.living; + +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import com.google.inject.Binder; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.annotations.XStreamAlias; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.val; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.error.WxRuntimeException; +import me.chanjar.weixin.common.util.json.GsonParser; +import me.chanjar.weixin.common.util.xml.XStreamInitializer; +import me.chanjar.weixin.cp.api.WxCpService; +import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl; +import me.chanjar.weixin.cp.bean.WxCpDepart; +import me.chanjar.weixin.cp.bean.external.contact.ExternalContact; +import me.chanjar.weixin.cp.bean.external.contact.FollowedUser; +import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage; +import me.chanjar.weixin.cp.bean.message.WxCpXmlOutTextMessage; +import me.chanjar.weixin.cp.config.WxCpConfigStorage; +import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl; +import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage; +import me.chanjar.weixin.cp.message.WxCpMessageHandler; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; +import org.eclipse.jetty.util.ajax.JSON; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * 企业微信直播测试类. + * + * @author Wang_Wong + */ +public class WxCpLivingTest { + + private static WxCpConfigStorage wxCpConfigStorage; + private static WxCpService wxCpService; + + @Test + public void test() throws WxErrorException { + + InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml"); + WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream); + + wxCpConfigStorage = config; + wxCpService = new WxCpServiceImpl(); + wxCpService.setWxCpConfigStorage(config); + + WxCpGetLivingCode wxCpGetLivingCode = new WxCpGetLivingCode(); + wxCpGetLivingCode.setLivingid("lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw"); + wxCpGetLivingCode.setOpenid("o50by5NezHciWnoexJsrI49ILNqI"); + + String livingCode = wxCpService.getLivingService().getLivingCode(wxCpGetLivingCode); + System.out.println(JSON.toString(livingCode)); + + } + +} -- Gitee From 8b1439a6d2b64d169ad17247998f77f38beb7b26 Mon Sep 17 00:00:00 2001 From: wangkai Date: Wed, 22 Dec 2021 23:08:41 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=9B=B4=E6=92=AD=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weixin/cp/api/WxCpLivingService.java | 18 ++++- .../cp/api/impl/WxCpLivingServiceImpl.java | 17 +++- .../weixin/cp/bean/living/WxCpLivingInfo.java | 80 ++++++++++++++++++ .../weixin/cp/bean/living/WxCpStatInfo.java | 81 +++++++++++++++++++ .../weixin/cp/constant/WxCpApiPathConsts.java | 4 +- .../weixin/cp/bean/living/WxCpLivingTest.java | 37 +++------ 6 files changed, 204 insertions(+), 33 deletions(-) create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java index 2070971ae..a9e910470 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java @@ -2,9 +2,7 @@ package me.chanjar.weixin.cp.api; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode; -import me.chanjar.weixin.cp.bean.oa.WxCpOaSchedule; - -import java.util.List; +import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo; /** * 企业微信直播接口. @@ -17,7 +15,8 @@ public interface WxCpLivingService { /** * 获取微信观看直播凭证 - * 详情请见: https://work.weixin.qq.com/api/doc/90000/90135/93641 + * 请求方式: POST(HTTPS) + * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/get_living_code?access_token=ACCESS_TOKEN * * @param codeParam 直播凭证请求参数 * @return living_code 微信观看直播凭证 @@ -25,4 +24,15 @@ public interface WxCpLivingService { */ String getLivingCode(WxCpGetLivingCode codeParam) throws WxErrorException; + /** + * 获取直播详情 + * 请求方式:GET(HTTPS) + * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_living_info?access_token=ACCESS_TOKEN&livingid=LIVINGID + * + * @param livingId 直播id + * @return 获取的直播详情 + * @throws WxErrorException the wx error exception + */ + WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java index 9819b2a8a..9bc5f4a11 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.cp.api.impl; +import com.google.gson.reflect.TypeToken; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -9,8 +10,11 @@ import me.chanjar.weixin.common.util.json.GsonParser; import me.chanjar.weixin.cp.api.WxCpLivingService; import me.chanjar.weixin.cp.api.WxCpService; import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode; +import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; -import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*; +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_CODE; +import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_INFO; /** * 企业微信直播接口实现类. @@ -30,4 +34,15 @@ public class WxCpLivingServiceImpl implements WxCpLivingService { return GsonHelper.getString(GsonParser.parse(responseContent), "living_code"); } + @Override + public WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException { + String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_INFO) + livingId; + String responseContent = this.cpService.get(apiUrl, null); + return WxCpGsonBuilder.create() + .fromJson(GsonParser.parse(responseContent).get("living_info"), + new TypeToken() { + }.getType() + ); + } + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java new file mode 100644 index 000000000..302decda1 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java @@ -0,0 +1,80 @@ +package me.chanjar.weixin.cp.bean.living; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; + +/** + * 直播信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpLivingInfo implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + @SerializedName("theme") + private String theme; + + @SerializedName("living_start") + private Long livingStart; + + @SerializedName("living_duration") + private Long livingDurationme; + + @SerializedName("status") + private Integer status; + + @SerializedName("reserve_living_duration") + private Long reserveLivingDuration; + + @SerializedName("reserve_start") + private Long reserveStart; + + @SerializedName("description") + private String description; + + @SerializedName("anchor_userid") + private String anchorUserid; + + @SerializedName("main_department") + private Long mainDepartment; + + @SerializedName("viewer_num") + private Integer viewerNum; + + @SerializedName("comment_num") + private Integer commentNum; + + @SerializedName("mic_num") + private Integer micNum; + + @SerializedName("open_replay") + private Integer openReplay; + + @SerializedName("replay_status") + private Integer replayStatus; + + @SerializedName("type") + private Integer type; + + @SerializedName("push_stream_url") + private String pushStreamUrl; + + @SerializedName("online_count") + private Integer onlineCount; + + @SerializedName("subscribe_count") + private Integer subscribeCount; + + public static WxCpLivingInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpLivingInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java new file mode 100644 index 000000000..389f8b86d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java @@ -0,0 +1,81 @@ +package me.chanjar.weixin.cp.bean.living; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +import java.io.Serializable; +import java.util.List; + +/** + * 直播信息. + * + * @author Wang_Wong + */ +@Data +public class WxCpStatInfo implements Serializable { + private static final long serialVersionUID = -5028321625140879571L; + + private Integer ending; + + @SerializedName("next_key") + private String nextKey; + + @SerializedName("users") + private List users; + + @SerializedName("external_users") + private List externalUsers; + + @Getter + @Setter + public static class User implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + private String userid; + + @SerializedName("watch_time") + private Long watchTime; + + @SerializedName("is_comment") + private Integer isComment; + + @SerializedName("is_mic") + private Integer isMic; + + } + + @Getter + @Setter + public static class ExternalUser implements Serializable { + private static final long serialVersionUID = -5696099236344075582L; + + private String userid; + private String name; + private Integer type; + + @SerializedName("external_userid") + private String externalUserid; + + @SerializedName("watch_time") + private Long watchTime; + + @SerializedName("is_comment") + private Integer isComment; + + @SerializedName("is_mic") + private Integer isMic; + + } + + public static WxCpStatInfo fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpStatInfo.class); + } + + public String toJson() { + return WxCpGsonBuilder.create().toJson(this); + } + +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java index 77152b76e..1e5f28203 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java @@ -1,8 +1,6 @@ package me.chanjar.weixin.cp.constant; -import lombok.experimental.UtilityClass; - /** *
  *  企业微信api地址常量类
@@ -120,7 +118,7 @@ public interface WxCpApiPathConsts {
 
   interface Living {
     String GET_LIVING_CODE = "/cgi-bin/living/get_living_code";
-    String GET_LIVING_INFO = "/cgi-bin/living/get_living_info";
+    String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid=";
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
   }
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
index 1c9f9eb72..1ee1d9365 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
@@ -1,44 +1,22 @@
 package me.chanjar.weixin.cp.bean.living;
 
-import com.google.gson.JsonObject;
-import com.google.gson.reflect.TypeToken;
-import com.google.inject.Binder;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.val;
+import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.common.error.WxRuntimeException;
-import me.chanjar.weixin.common.util.json.GsonParser;
-import me.chanjar.weixin.common.util.xml.XStreamInitializer;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
-import me.chanjar.weixin.cp.bean.WxCpDepart;
-import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
-import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
-import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
-import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
-import me.chanjar.weixin.cp.bean.message.WxCpXmlOutTextMessage;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
-import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
-import me.chanjar.weixin.cp.message.WxCpMessageHandler;
-import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 import org.eclipse.jetty.util.ajax.JSON;
 import org.testng.annotations.Test;
 
-import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * 企业微信直播测试类.
  *
  * @author Wang_Wong
  */
+@Slf4j
 public class WxCpLivingTest {
 
   private static WxCpConfigStorage wxCpConfigStorage;
@@ -59,7 +37,16 @@ public class WxCpLivingTest {
     wxCpGetLivingCode.setOpenid("o50by5NezHciWnoexJsrI49ILNqI");
 
     String livingCode = wxCpService.getLivingService().getLivingCode(wxCpGetLivingCode);
-    System.out.println(JSON.toString(livingCode));
+    log.info(JSON.toString(livingCode));
+
+    String json = wxCpGetLivingCode.toJson();
+    log.info(json);
+
+    WxCpGetLivingCode getLivingCode = WxCpGetLivingCode.fromJson(json);
+    log.info(getLivingCode.toJson());
+
+    WxCpLivingInfo livingInfo = wxCpService.getLivingService().getLivingInfo("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg");
+    log.info(livingInfo.toJson());
 
   }
 
-- 
Gitee


From ae942ebefa1bc1694cb41a4318685583a4f48a82 Mon Sep 17 00:00:00 2001
From: 0katekate0 <1960779692@qq.com>
Date: Thu, 23 Dec 2021 00:22:43 +0800
Subject: [PATCH 04/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?=
 =?UTF-8?q?=E7=9B=B4=E6=92=AD=E8=A7=82=E7=9C=8B=E6=98=8E=E7=BB=86=E6=8E=A5?=
 =?UTF-8?q?=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 21 ++++++++++++--
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 25 +++++++++++++----
 .../cp/bean/living/WxCpGetLivingCode.java     | 28 -------------------
 .../{WxCpStatInfo.java => WxCpWatchStat.java} | 25 +++++++++++------
 .../{bean/living => api}/WxCpLivingTest.java  | 25 ++++++++---------
 5 files changed, 67 insertions(+), 57 deletions(-)
 delete mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
 rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/{WxCpStatInfo.java => WxCpWatchStat.java} (71%)
 rename weixin-java-cp/src/test/java/me/chanjar/weixin/cp/{bean/living => api}/WxCpLivingTest.java (55%)

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index a9e910470..f035ad5c8 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -1,8 +1,9 @@
 package me.chanjar.weixin.cp.api;
 
+import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 
 /**
  * 企业微信直播接口.
@@ -22,7 +23,7 @@ public interface WxCpLivingService {
    * @return living_code 微信观看直播凭证
    * @throws WxErrorException the wx error exception
    */
-  String getLivingCode(WxCpGetLivingCode codeParam) throws WxErrorException;
+  String getLivingCode(@NonNull String openId, @NonNull String livingId) throws WxErrorException;
 
   /**
    * 获取直播详情
@@ -33,6 +34,20 @@ public interface WxCpLivingService {
    * @return 获取的直播详情
    * @throws WxErrorException the wx error exception
    */
-  WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException;
+  WxCpLivingInfo getLivingInfo(@NonNull String livingId) throws WxErrorException;
+
+  /**
+   * 获取直播观看明细
+   * 通过该接口可以获取所有观看直播的人员统计
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_watch_stat?access_token=ACCESS_TOKEN
+   *
+   * @param livingId 直播的id
+   * @param nextKey 上一次调用时返回的next_key,初次调用可以填”0”
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
 
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index 9bc5f4a11..ff16f0780 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.cp.api.impl;
 
+import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -9,12 +10,11 @@ import me.chanjar.weixin.common.util.json.GsonHelper;
 import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
-import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
-import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_CODE;
-import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_INFO;
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*;
 
 /**
  * 企业微信直播接口实现类.
@@ -28,9 +28,12 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
   private final WxCpService cpService;
 
   @Override
-  public String getLivingCode(@NonNull WxCpGetLivingCode livingCode) throws WxErrorException {
+  public String getLivingCode(String openId, String livingId) throws WxErrorException {
     final String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_CODE);
-    String responseContent = this.cpService.post(apiUrl, livingCode.toJson());
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("openid", openId);
+    jsonObject.addProperty("livingid", livingId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
     return GsonHelper.getString(GsonParser.parse(responseContent), "living_code");
   }
 
@@ -45,4 +48,16 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
       );
   }
 
+  @Override
+  public WxCpWatchStat getWatchStat(String livingId, Integer nextKey) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_WATCH_STAT);
+    JsonObject jsonObject = new JsonObject();
+    if (nextKey != null) {
+      jsonObject.addProperty("next_key", String.valueOf(nextKey));
+    }
+    jsonObject.addProperty("livingid", livingId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpWatchStat.fromJson(responseContent);
+  }
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
deleted file mode 100644
index 9281c0a4d..000000000
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package me.chanjar.weixin.cp.bean.living;
-
-import lombok.Data;
-import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
-
-import java.io.Serializable;
-
-/**
- * 微信观看直播凭证请求体.
- *
- * @author Wang_Wong
- */
-@Data
-public class WxCpGetLivingCode implements Serializable {
-  private static final long serialVersionUID = -5028321625140879571L;
-
-  private String livingid;
-  private String openid;
-
-  public static WxCpGetLivingCode fromJson(String json) {
-    return WxCpGsonBuilder.create().fromJson(json, WxCpGetLivingCode.class);
-  }
-
-  public String toJson() {
-    return WxCpGsonBuilder.create().toJson(this);
-  }
-
-}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
similarity index 71%
rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java
rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
index 389f8b86d..f14bb3348 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
@@ -15,7 +15,7 @@ import java.util.List;
  * @author Wang_Wong
  */
 @Data
-public class WxCpStatInfo implements Serializable {
+public class WxCpWatchStat implements Serializable {
   private static final long serialVersionUID = -5028321625140879571L;
 
   private Integer ending;
@@ -23,11 +23,21 @@ public class WxCpStatInfo implements Serializable {
   @SerializedName("next_key")
   private String nextKey;
 
-  @SerializedName("users")
-  private List users;
+  @SerializedName("stat_info")
+  private StatInfo statInfo;
 
-  @SerializedName("external_users")
-  private List externalUsers;
+  @Getter
+  @Setter
+  public static class StatInfo implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    @SerializedName("users")
+    private List users;
+
+    @SerializedName("external_users")
+    private List externalUsers;
+
+  }
 
   @Getter
   @Setter
@@ -52,7 +62,6 @@ public class WxCpStatInfo implements Serializable {
   public static class ExternalUser implements Serializable {
     private static final long serialVersionUID = -5696099236344075582L;
 
-    private String userid;
     private String name;
     private Integer type;
 
@@ -70,8 +79,8 @@ public class WxCpStatInfo implements Serializable {
 
   }
 
-  public static WxCpStatInfo fromJson(String json) {
-    return WxCpGsonBuilder.create().fromJson(json, WxCpStatInfo.class);
+  public static WxCpWatchStat fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpWatchStat.class);
   }
 
   public String toJson() {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
similarity index 55%
rename from weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
rename to weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 1ee1d9365..76d2c8129 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -1,9 +1,10 @@
-package me.chanjar.weixin.cp.bean.living;
+package me.chanjar.weixin.cp.api;
 
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
 import org.eclipse.jetty.util.ajax.JSON;
@@ -32,22 +33,20 @@ public class WxCpLivingTest {
     wxCpService = new WxCpServiceImpl();
     wxCpService.setWxCpConfigStorage(config);
 
-    WxCpGetLivingCode wxCpGetLivingCode = new WxCpGetLivingCode();
-    wxCpGetLivingCode.setLivingid("lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
-    wxCpGetLivingCode.setOpenid("o50by5NezHciWnoexJsrI49ILNqI");
-
-    String livingCode = wxCpService.getLivingService().getLivingCode(wxCpGetLivingCode);
+    String livingCode = wxCpService.getLivingService().getLivingCode("o50by5NezHciWnoexJsrI49ILNqI", "lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
     log.info(JSON.toString(livingCode));
 
-    String json = wxCpGetLivingCode.toJson();
-    log.info(json);
-
-    WxCpGetLivingCode getLivingCode = WxCpGetLivingCode.fromJson(json);
-    log.info(getLivingCode.toJson());
-
     WxCpLivingInfo livingInfo = wxCpService.getLivingService().getLivingInfo("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg");
     log.info(livingInfo.toJson());
 
+    WxCpWatchStat watchStat = wxCpService.getLivingService().getWatchStat("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg", 0);
+    log.info(watchStat.toJson());
+
+    final String watchStateJson = "{\"errcode\":0,\"errmsg\":\"ok\",\"ending\":1,\"next_key\":\"NEXT_KEY\",\"stat_info\":{\"users\":[{\"userid\":\"userid\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1}],\"external_users\":[{\"external_userid\":\"external_userid1\",\"type\":1,\"name\":\"user name\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1},{\"external_userid\":\"external_userid2\",\"type\":2,\"name\":\"user_name\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1}]}}";
+
+    WxCpWatchStat wxCpWatchStat = WxCpWatchStat.fromJson(watchStateJson);
+    log.info(wxCpWatchStat.toJson());
+
   }
 
 }
-- 
Gitee


From b77bb07d4e821db24b8eb900f88ab0577894ab9a Mon Sep 17 00:00:00 2001
From: wangkai 
Date: Thu, 23 Dec 2021 17:23:31 +0800
Subject: [PATCH 05/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?=
 =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=95=86=E5=9F=8E?=
 =?UTF-8?q?=E7=9A=84=E7=9B=B4=E6=92=AD=E8=A7=82=E4=BC=97=E4=BF=A1=E6=81=AF?=
 =?UTF-8?q?=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 19 ++++++++-
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 10 +++++
 .../weixin/cp/bean/living/WxCpLivingInfo.java |  2 +-
 .../cp/bean/living/WxCpLivingShareInfo.java   | 40 +++++++++++++++++++
 .../weixin/cp/bean/living/WxCpWatchStat.java  |  2 +-
 .../weixin/cp/constant/WxCpApiPathConsts.java |  1 +
 .../chanjar/weixin/cp/api/WxCpLivingTest.java |  9 +++++
 7 files changed, 79 insertions(+), 4 deletions(-)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index f035ad5c8..afbef01a1 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.api;
 import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 
 /**
@@ -19,7 +20,8 @@ public interface WxCpLivingService {
    * 请求方式: POST(HTTPS)
    * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/get_living_code?access_token=ACCESS_TOKEN
    *
-   * @param codeParam 直播凭证请求参数
+   * @param openId 用户openid
+   * @param livingId 直播id
    * @return living_code 微信观看直播凭证
    * @throws WxErrorException the wx error exception
    */
@@ -43,11 +45,24 @@ public interface WxCpLivingService {
    * 请求方式:POST(HTTPS)
    * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_watch_stat?access_token=ACCESS_TOKEN
    *
-   * @param livingId 直播的id
+   * @param livingId 直播id
    * @param nextKey 上一次调用时返回的next_key,初次调用可以填”0”
    * @return
    * @throws WxErrorException
    */
   WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
 
+  /**
+   * 获取跳转小程序商城的直播观众信息
+   * 通过此接口,开发者可获取跳转小程序商城的直播间(“推广产品”直播)观众id、邀请人id及对应直播间id,以打通卖货直播的“人货场”信息闭环。
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_living_share_info?access_token=ACCESS_TOKEN
+   *
+   * @param wwShareCode "推广产品"直播观众跳转小程序商城时会在小程序path中带上ww_share_code=xxxxx参数
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException;
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index ff16f0780..f7ad63bd0 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -11,6 +11,7 @@ import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
@@ -60,4 +61,13 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
     return WxCpWatchStat.fromJson(responseContent);
   }
 
+  @Override
+  public WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_SHARE_INFO);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("ww_share_code", wwShareCode);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpLivingShareInfo.fromJson(responseContent);
+  }
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
index 302decda1..b7010e57e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
@@ -7,7 +7,7 @@ import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 import java.io.Serializable;
 
 /**
- * 直播信息.
+ * 直播详情信息.
  *
  * @author Wang_Wong
  */
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java
new file mode 100644
index 000000000..f0b96cc96
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 跳转小程序商城的直播观众信息.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpLivingShareInfo implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  private String livingid;
+
+  @SerializedName("viewer_userid")
+  private String viewerUserid;
+
+  @SerializedName("viewer_external_userid")
+  private String viewerExternalUserid;
+
+  @SerializedName("invitor_userid")
+  private String invitorUserid;
+
+  @SerializedName("invitor_external_userid")
+  private String invitorExternalUserid;
+
+  public static WxCpLivingShareInfo fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingShareInfo.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
index f14bb3348..4a77bdd45 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
@@ -10,7 +10,7 @@ import java.io.Serializable;
 import java.util.List;
 
 /**
- * 直播信息.
+ * 直播观看明细.
  *
  * @author Wang_Wong
  */
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index 1e5f28203..f2129306b 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -120,6 +120,7 @@ public interface WxCpApiPathConsts {
     String GET_LIVING_CODE = "/cgi-bin/living/get_living_code";
     String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid=";
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
+    String GET_LIVING_SHARE_INFO = "/cgi-bin/living/get_living_share_info";
   }
 
   interface Tag {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 76d2c8129..2fb0267cf 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
@@ -36,9 +37,11 @@ public class WxCpLivingTest {
     String livingCode = wxCpService.getLivingService().getLivingCode("o50by5NezHciWnoexJsrI49ILNqI", "lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
     log.info(JSON.toString(livingCode));
 
+    // 直播详情
     WxCpLivingInfo livingInfo = wxCpService.getLivingService().getLivingInfo("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg");
     log.info(livingInfo.toJson());
 
+    // 直播观看明细
     WxCpWatchStat watchStat = wxCpService.getLivingService().getWatchStat("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg", 0);
     log.info(watchStat.toJson());
 
@@ -47,6 +50,12 @@ public class WxCpLivingTest {
     WxCpWatchStat wxCpWatchStat = WxCpWatchStat.fromJson(watchStateJson);
     log.info(wxCpWatchStat.toJson());
 
+    // 直播观众信息
+    final String livingShareInfo = "{\"errcode\":0,\"errmsg\":\"ok\",\"livingid\":\"livingid\",\"viewer_userid\":\"viewer_userid\",\"viewer_external_userid\":\"viewer_external_userid\",\"invitor_userid\":\"invitor_userid\",\"invitor_external_userid\":\"invitor_external_userid\"}";
+
+    WxCpLivingShareInfo wxCpLivingShareInfo = WxCpLivingShareInfo.fromJson(livingShareInfo);
+    log.info(wxCpLivingShareInfo.toJson());
+
   }
 
 }
-- 
Gitee


From eec95d2b670be38c50adaebac09dc1182bfc4950 Mon Sep 17 00:00:00 2001
From: wangkai 
Date: Thu, 23 Dec 2021 18:31:09 +0800
Subject: [PATCH 06/12] =?UTF-8?q?=E3=80=90=E4=BC=81=E4=B8=9A=E5=BE=AE?=
 =?UTF-8?q?=E4=BF=A1=E3=80=91=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96=E6=88=90?=
 =?UTF-8?q?=E5=91=98=E7=9B=B4=E6=92=ADID=E5=88=97=E8=A1=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 16 +++++
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 19 +++++-
 .../cp/bean/living/WxCpLivingResult.java      | 62 +++++++++++++++++++
 .../weixin/cp/constant/WxCpApiPathConsts.java |  1 +
 .../chanjar/weixin/cp/api/WxCpLivingTest.java | 10 +++
 5 files changed, 106 insertions(+), 2 deletions(-)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index afbef01a1..321651f42 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.api;
 import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 
@@ -52,6 +53,21 @@ public interface WxCpLivingService {
    */
   WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
 
+  /**
+   * 获取成员直播ID列表
+   * 通过此接口可以获取指定成员的所有直播ID
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_user_all_livingid?access_token=ACCESS_TOKEN
+   *
+   * @param userId 企业成员的userid
+   * @param cursor 上一次调用时返回的next_cursor,第一次拉取可以不填
+   * @param limit 每次拉取的数据量,默认值和最大值都为100
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingResult.LivingIdResult getUserAllLivingId(@NonNull String userId, String cursor, Integer limit) throws WxErrorException;
+
   /**
    * 获取跳转小程序商城的直播观众信息
    * 通过此接口,开发者可获取跳转小程序商城的直播间(“推广产品”直播)观众id、邀请人id及对应直播间id,以打通卖货直播的“人货场”信息闭环。
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index f7ad63bd0..ade8fc3ce 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -2,7 +2,6 @@ package me.chanjar.weixin.cp.api.impl;
 
 import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
-import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -11,6 +10,7 @@ import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
@@ -62,7 +62,22 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
   }
 
   @Override
-  public WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException {
+  public WxCpLivingResult.LivingIdResult getUserAllLivingId(String userId, String cursor, Integer limit) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_USER_ALL_LIVINGID);
+    JsonObject jsonObject = new JsonObject();
+    if (cursor != null) {
+      jsonObject.addProperty("cursor", cursor);
+    }
+    if (limit != null) {
+      jsonObject.addProperty("limit", limit);
+    }
+    jsonObject.addProperty("userid", userId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpLivingResult.LivingIdResult.fromJson(responseContent);
+  }
+
+  @Override
+  public WxCpLivingShareInfo getLivingShareInfo(String wwShareCode) throws WxErrorException {
     String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_SHARE_INFO);
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("ww_share_code", wwShareCode);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
new file mode 100644
index 000000000..35842e08f
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
@@ -0,0 +1,62 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 直播返回对象.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpLivingResult implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  private Integer errcode;
+  private String errmsg;
+
+  @Getter
+  @Setter
+  public static class LivingCeateResult implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    @SerializedName("livingid")
+    private String livingid;
+
+  }
+
+  @Getter
+  @Setter
+  public static class LivingIdResult implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    @SerializedName("next_cursor")
+    private String nextCursor;
+
+    @SerializedName("livingid_list")
+    private String[] livingidList;
+
+    public static LivingIdResult fromJson(String json) {
+      return WxCpGsonBuilder.create().fromJson(json, LivingIdResult.class);
+    }
+
+    public String toJson() {
+      return WxCpGsonBuilder.create().toJson(this);
+    }
+
+  }
+
+  public static WxCpLivingResult fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingResult.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index f2129306b..8887ef4cd 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -121,6 +121,7 @@ public interface WxCpApiPathConsts {
     String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid=";
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
     String GET_LIVING_SHARE_INFO = "/cgi-bin/living/get_living_share_info";
+    String GET_USER_ALL_LIVINGID = "/cgi-bin/living/get_user_all_livingid";
   }
 
   interface Tag {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 2fb0267cf..2db8e3327 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@@ -15,6 +16,7 @@ import java.io.InputStream;
 
 /**
  * 企业微信直播测试类.
+ * 官方文档:https://open.work.weixin.qq.com/api/doc/90000/90135/93632
  *
  * @author Wang_Wong
  */
@@ -56,6 +58,14 @@ public class WxCpLivingTest {
     WxCpLivingShareInfo wxCpLivingShareInfo = WxCpLivingShareInfo.fromJson(livingShareInfo);
     log.info(wxCpLivingShareInfo.toJson());
 
+    // 获取成员直播ID列表
+    WxCpLivingResult.LivingIdResult livingResult = wxCpService.getLivingService().getUserAllLivingId("ChenHu", null, null);
+    log.info(livingResult.toJson());
+
+    String livinglist = "{\"errcode\":0,\"errmsg\":\"ok\",\"next_cursor\":\"next_cursor\",\"livingid_list\":[\"livingid1\",\"livingid2\"]}";
+    WxCpLivingResult.LivingIdResult livingIdResult = WxCpLivingResult.LivingIdResult.fromJson(livinglist);
+    log.info(livingIdResult.toJson());
+
   }
 
 }
-- 
Gitee


From 524080c5f5487b9cfda5cee194931d0faecea781 Mon Sep 17 00:00:00 2001
From: 0katekate0 <1960779692@qq.com>
Date: Wed, 22 Dec 2021 00:17:18 +0800
Subject: [PATCH 07/12] =?UTF-8?q?=E3=80=90=E4=BC=81=E4=B8=9A=E5=BE=AE?=
 =?UTF-8?q?=E4=BF=A1=E3=80=91=E5=A2=9E=E5=8A=A0=E7=9B=B4=E6=92=AD=E5=85=AC?=
 =?UTF-8?q?=E5=85=B1=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 28 ++++++++
 .../me/chanjar/weixin/cp/api/WxCpService.java |  7 ++
 .../cp/api/impl/BaseWxCpServiceImpl.java      |  6 ++
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 33 ++++++++++
 .../cp/bean/living/WxCpGetLivingCode.java     | 28 ++++++++
 .../weixin/cp/constant/WxCpApiPathConsts.java |  6 ++
 .../weixin/cp/bean/living/WxCpLivingTest.java | 66 +++++++++++++++++++
 7 files changed, 174 insertions(+)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
 create mode 100644 weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
new file mode 100644
index 000000000..2070971ae
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.cp.api;
+
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
+import me.chanjar.weixin.cp.bean.oa.WxCpOaSchedule;
+
+import java.util.List;
+
+/**
+ * 企业微信直播接口.
+ * 官方文档:https://work.weixin.qq.com/api/doc/90000/90135/93633
+ *
+ * @author Wang_Wong
+ * @date 2021-12-21
+ */
+public interface WxCpLivingService {
+
+  /**
+   * 获取微信观看直播凭证
+   * 详情请见: https://work.weixin.qq.com/api/doc/90000/90135/93641
+   *
+   * @param codeParam 直播凭证请求参数
+   * @return living_code 微信观看直播凭证
+   * @throws WxErrorException the wx error exception
+   */
+  String getLivingCode(WxCpGetLivingCode codeParam) throws WxErrorException;
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
index 94cd21263..123697b8e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpService.java
@@ -392,6 +392,13 @@ public interface WxCpService extends WxService {
    */
   WxCpOaService getOaService();
 
+  /**
+   * 获取直播相关接口的服务类对象
+   *
+   * @return the Living service
+   */
+  WxCpLivingService getLivingService();
+
   /**
    * 获取日历相关接口的服务类对象
    *
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java
index 89221f1a1..210d54f54 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/BaseWxCpServiceImpl.java
@@ -49,6 +49,7 @@ public abstract class BaseWxCpServiceImpl implements WxCpService, RequestH
   private WxCpTagService tagService = new WxCpTagServiceImpl(this);
   private WxCpAgentService agentService = new WxCpAgentServiceImpl(this);
   private WxCpOaService oaService = new WxCpOaServiceImpl(this);
+  private WxCpLivingService livingService = new WxCpLivingServiceImpl(this);
   private WxCpTaskCardService taskCardService = new WxCpTaskCardServiceImpl(this);
   private WxCpExternalContactService externalContactService = new WxCpExternalContactServiceImpl(this);
   private WxCpGroupRobotService groupRobotService = new WxCpGroupRobotServiceImpl(this);
@@ -477,6 +478,11 @@ public abstract class BaseWxCpServiceImpl implements WxCpService, RequestH
     return oaService;
   }
 
+  @Override
+  public WxCpLivingService getLivingService() {
+    return livingService;
+  }
+
   @Override
   public WxCpOaCalendarService getOaCalendarService() {
     return this.oaCalendarService;
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
new file mode 100644
index 000000000..9819b2a8a
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -0,0 +1,33 @@
+package me.chanjar.weixin.cp.api.impl;
+
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.util.json.GsonHelper;
+import me.chanjar.weixin.common.util.json.GsonParser;
+import me.chanjar.weixin.cp.api.WxCpLivingService;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
+
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*;
+
+/**
+ * 企业微信直播接口实现类.
+ *
+ * @author Wang_Wong
+ * @date 2021-12-21
+ */
+@Slf4j
+@RequiredArgsConstructor
+public class WxCpLivingServiceImpl implements WxCpLivingService {
+  private final WxCpService cpService;
+
+  @Override
+  public String getLivingCode(@NonNull WxCpGetLivingCode livingCode) throws WxErrorException {
+    final String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_CODE);
+    String responseContent = this.cpService.post(apiUrl, livingCode.toJson());
+    return GsonHelper.getString(GsonParser.parse(responseContent), "living_code");
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
new file mode 100644
index 000000000..9281c0a4d
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
@@ -0,0 +1,28 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import lombok.Data;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 微信观看直播凭证请求体.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpGetLivingCode implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  private String livingid;
+  private String openid;
+
+  public static WxCpGetLivingCode fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpGetLivingCode.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index 710f7f6a7..77152b76e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -118,6 +118,12 @@ public interface WxCpApiPathConsts {
     String COPY_TEMPLATE = "/cgi-bin/oa/approval/copytemplate";
   }
 
+  interface Living {
+    String GET_LIVING_CODE = "/cgi-bin/living/get_living_code";
+    String GET_LIVING_INFO = "/cgi-bin/living/get_living_info";
+    String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
+  }
+
   interface Tag {
     String TAG_CREATE = "/cgi-bin/tag/create";
     String TAG_UPDATE = "/cgi-bin/tag/update";
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
new file mode 100644
index 000000000..1c9f9eb72
--- /dev/null
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
@@ -0,0 +1,66 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
+import com.google.inject.Binder;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.val;
+import me.chanjar.weixin.common.error.WxErrorException;
+import me.chanjar.weixin.common.error.WxRuntimeException;
+import me.chanjar.weixin.common.util.json.GsonParser;
+import me.chanjar.weixin.common.util.xml.XStreamInitializer;
+import me.chanjar.weixin.cp.api.WxCpService;
+import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
+import me.chanjar.weixin.cp.bean.WxCpDepart;
+import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
+import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
+import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
+import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
+import me.chanjar.weixin.cp.bean.message.WxCpXmlOutTextMessage;
+import me.chanjar.weixin.cp.config.WxCpConfigStorage;
+import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
+import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
+import me.chanjar.weixin.cp.message.WxCpMessageHandler;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+import org.eclipse.jetty.util.ajax.JSON;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * 企业微信直播测试类.
+ *
+ * @author Wang_Wong
+ */
+public class WxCpLivingTest {
+
+  private static WxCpConfigStorage wxCpConfigStorage;
+  private static WxCpService wxCpService;
+
+  @Test
+  public void test() throws WxErrorException {
+
+    InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml");
+    WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream);
+
+    wxCpConfigStorage = config;
+    wxCpService = new WxCpServiceImpl();
+    wxCpService.setWxCpConfigStorage(config);
+
+    WxCpGetLivingCode wxCpGetLivingCode = new WxCpGetLivingCode();
+    wxCpGetLivingCode.setLivingid("lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
+    wxCpGetLivingCode.setOpenid("o50by5NezHciWnoexJsrI49ILNqI");
+
+    String livingCode = wxCpService.getLivingService().getLivingCode(wxCpGetLivingCode);
+    System.out.println(JSON.toString(livingCode));
+
+  }
+
+}
-- 
Gitee


From c7a5bc8b94cd0c01e171c01a243b55a282d8e5d7 Mon Sep 17 00:00:00 2001
From: wangkai 
Date: Wed, 22 Dec 2021 23:08:41 +0800
Subject: [PATCH 08/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?=
 =?UTF-8?q?=E7=9B=B4=E6=92=AD=E8=AF=A6=E6=83=85=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 18 ++++-
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 17 +++-
 .../weixin/cp/bean/living/WxCpLivingInfo.java | 80 ++++++++++++++++++
 .../weixin/cp/bean/living/WxCpStatInfo.java   | 81 +++++++++++++++++++
 .../weixin/cp/constant/WxCpApiPathConsts.java |  4 +-
 .../weixin/cp/bean/living/WxCpLivingTest.java | 37 +++------
 6 files changed, 204 insertions(+), 33 deletions(-)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index 2070971ae..a9e910470 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -2,9 +2,7 @@ package me.chanjar.weixin.cp.api;
 
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
-import me.chanjar.weixin.cp.bean.oa.WxCpOaSchedule;
-
-import java.util.List;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
 
 /**
  * 企业微信直播接口.
@@ -17,7 +15,8 @@ public interface WxCpLivingService {
 
   /**
    * 获取微信观看直播凭证
-   * 详情请见: https://work.weixin.qq.com/api/doc/90000/90135/93641
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/get_living_code?access_token=ACCESS_TOKEN
    *
    * @param codeParam 直播凭证请求参数
    * @return living_code 微信观看直播凭证
@@ -25,4 +24,15 @@ public interface WxCpLivingService {
    */
   String getLivingCode(WxCpGetLivingCode codeParam) throws WxErrorException;
 
+  /**
+   * 获取直播详情
+   * 请求方式:GET(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_living_info?access_token=ACCESS_TOKEN&livingid=LIVINGID
+   *
+   * @param livingId 直播id
+   * @return 获取的直播详情
+   * @throws WxErrorException the wx error exception
+   */
+  WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException;
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index 9819b2a8a..9bc5f4a11 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.cp.api.impl;
 
+import com.google.gson.reflect.TypeToken;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -9,8 +10,11 @@ import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
-import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*;
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_CODE;
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_INFO;
 
 /**
  * 企业微信直播接口实现类.
@@ -30,4 +34,15 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
     return GsonHelper.getString(GsonParser.parse(responseContent), "living_code");
   }
 
+  @Override
+  public WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_INFO) + livingId;
+    String responseContent = this.cpService.get(apiUrl, null);
+    return WxCpGsonBuilder.create()
+      .fromJson(GsonParser.parse(responseContent).get("living_info"),
+        new TypeToken() {
+        }.getType()
+      );
+  }
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
new file mode 100644
index 000000000..302decda1
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
@@ -0,0 +1,80 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 直播信息.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpLivingInfo implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  @SerializedName("theme")
+  private String theme;
+
+  @SerializedName("living_start")
+  private Long livingStart;
+
+  @SerializedName("living_duration")
+  private Long livingDurationme;
+
+  @SerializedName("status")
+  private Integer status;
+
+  @SerializedName("reserve_living_duration")
+  private Long reserveLivingDuration;
+
+  @SerializedName("reserve_start")
+  private Long reserveStart;
+
+  @SerializedName("description")
+  private String description;
+
+  @SerializedName("anchor_userid")
+  private String anchorUserid;
+
+  @SerializedName("main_department")
+  private Long mainDepartment;
+
+  @SerializedName("viewer_num")
+  private Integer viewerNum;
+
+  @SerializedName("comment_num")
+  private Integer commentNum;
+
+  @SerializedName("mic_num")
+  private Integer micNum;
+
+  @SerializedName("open_replay")
+  private Integer openReplay;
+
+  @SerializedName("replay_status")
+  private Integer replayStatus;
+
+  @SerializedName("type")
+  private Integer type;
+
+  @SerializedName("push_stream_url")
+  private String pushStreamUrl;
+
+  @SerializedName("online_count")
+  private Integer onlineCount;
+
+  @SerializedName("subscribe_count")
+  private Integer subscribeCount;
+
+  public static WxCpLivingInfo fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingInfo.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java
new file mode 100644
index 000000000..389f8b86d
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java
@@ -0,0 +1,81 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 直播信息.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpStatInfo implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  private Integer ending;
+
+  @SerializedName("next_key")
+  private String nextKey;
+
+  @SerializedName("users")
+  private List users;
+
+  @SerializedName("external_users")
+  private List externalUsers;
+
+  @Getter
+  @Setter
+  public static class User implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    private String userid;
+
+    @SerializedName("watch_time")
+    private Long watchTime;
+
+    @SerializedName("is_comment")
+    private Integer isComment;
+
+    @SerializedName("is_mic")
+    private Integer isMic;
+
+  }
+
+  @Getter
+  @Setter
+  public static class ExternalUser implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    private String userid;
+    private String name;
+    private Integer type;
+
+    @SerializedName("external_userid")
+    private String externalUserid;
+
+    @SerializedName("watch_time")
+    private Long watchTime;
+
+    @SerializedName("is_comment")
+    private Integer isComment;
+
+    @SerializedName("is_mic")
+    private Integer isMic;
+
+  }
+
+  public static WxCpStatInfo fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpStatInfo.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index 77152b76e..1e5f28203 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -1,8 +1,6 @@
 package me.chanjar.weixin.cp.constant;
 
 
-import lombok.experimental.UtilityClass;
-
 /**
  * 
  *  企业微信api地址常量类
@@ -120,7 +118,7 @@ public interface WxCpApiPathConsts {
 
   interface Living {
     String GET_LIVING_CODE = "/cgi-bin/living/get_living_code";
-    String GET_LIVING_INFO = "/cgi-bin/living/get_living_info";
+    String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid=";
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
   }
 
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
index 1c9f9eb72..1ee1d9365 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
@@ -1,44 +1,22 @@
 package me.chanjar.weixin.cp.bean.living;
 
-import com.google.gson.JsonObject;
-import com.google.gson.reflect.TypeToken;
-import com.google.inject.Binder;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.val;
+import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.common.error.WxRuntimeException;
-import me.chanjar.weixin.common.util.json.GsonParser;
-import me.chanjar.weixin.common.util.xml.XStreamInitializer;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
-import me.chanjar.weixin.cp.bean.WxCpDepart;
-import me.chanjar.weixin.cp.bean.external.contact.ExternalContact;
-import me.chanjar.weixin.cp.bean.external.contact.FollowedUser;
-import me.chanjar.weixin.cp.bean.external.contact.WxCpExternalContactInfo;
-import me.chanjar.weixin.cp.bean.message.WxCpXmlOutMessage;
-import me.chanjar.weixin.cp.bean.message.WxCpXmlOutTextMessage;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
-import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
-import me.chanjar.weixin.cp.message.WxCpMessageHandler;
-import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 import org.eclipse.jetty.util.ajax.JSON;
 import org.testng.annotations.Test;
 
-import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
 
 /**
  * 企业微信直播测试类.
  *
  * @author Wang_Wong
  */
+@Slf4j
 public class WxCpLivingTest {
 
   private static WxCpConfigStorage wxCpConfigStorage;
@@ -59,7 +37,16 @@ public class WxCpLivingTest {
     wxCpGetLivingCode.setOpenid("o50by5NezHciWnoexJsrI49ILNqI");
 
     String livingCode = wxCpService.getLivingService().getLivingCode(wxCpGetLivingCode);
-    System.out.println(JSON.toString(livingCode));
+    log.info(JSON.toString(livingCode));
+
+    String json = wxCpGetLivingCode.toJson();
+    log.info(json);
+
+    WxCpGetLivingCode getLivingCode = WxCpGetLivingCode.fromJson(json);
+    log.info(getLivingCode.toJson());
+
+    WxCpLivingInfo livingInfo = wxCpService.getLivingService().getLivingInfo("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg");
+    log.info(livingInfo.toJson());
 
   }
 
-- 
Gitee


From 0e7ed1362c7011675ac2b0ca92510a6d1f51be65 Mon Sep 17 00:00:00 2001
From: 0katekate0 <1960779692@qq.com>
Date: Thu, 23 Dec 2021 00:22:43 +0800
Subject: [PATCH 09/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?=
 =?UTF-8?q?=E7=9B=B4=E6=92=AD=E8=A7=82=E7=9C=8B=E6=98=8E=E7=BB=86=E6=8E=A5?=
 =?UTF-8?q?=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 21 ++++++++++++--
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 25 +++++++++++++----
 .../cp/bean/living/WxCpGetLivingCode.java     | 28 -------------------
 .../{WxCpStatInfo.java => WxCpWatchStat.java} | 25 +++++++++++------
 .../{bean/living => api}/WxCpLivingTest.java  | 25 ++++++++---------
 5 files changed, 67 insertions(+), 57 deletions(-)
 delete mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
 rename weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/{WxCpStatInfo.java => WxCpWatchStat.java} (71%)
 rename weixin-java-cp/src/test/java/me/chanjar/weixin/cp/{bean/living => api}/WxCpLivingTest.java (55%)

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index a9e910470..f035ad5c8 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -1,8 +1,9 @@
 package me.chanjar.weixin.cp.api;
 
+import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 
 /**
  * 企业微信直播接口.
@@ -22,7 +23,7 @@ public interface WxCpLivingService {
    * @return living_code 微信观看直播凭证
    * @throws WxErrorException the wx error exception
    */
-  String getLivingCode(WxCpGetLivingCode codeParam) throws WxErrorException;
+  String getLivingCode(@NonNull String openId, @NonNull String livingId) throws WxErrorException;
 
   /**
    * 获取直播详情
@@ -33,6 +34,20 @@ public interface WxCpLivingService {
    * @return 获取的直播详情
    * @throws WxErrorException the wx error exception
    */
-  WxCpLivingInfo getLivingInfo(String livingId) throws WxErrorException;
+  WxCpLivingInfo getLivingInfo(@NonNull String livingId) throws WxErrorException;
+
+  /**
+   * 获取直播观看明细
+   * 通过该接口可以获取所有观看直播的人员统计
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_watch_stat?access_token=ACCESS_TOKEN
+   *
+   * @param livingId 直播的id
+   * @param nextKey 上一次调用时返回的next_key,初次调用可以填”0”
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
 
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index 9bc5f4a11..ff16f0780 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -1,5 +1,6 @@
 package me.chanjar.weixin.cp.api.impl;
 
+import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -9,12 +10,11 @@ import me.chanjar.weixin.common.util.json.GsonHelper;
 import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
-import me.chanjar.weixin.cp.bean.living.WxCpGetLivingCode;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
-import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_CODE;
-import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.GET_LIVING_INFO;
+import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*;
 
 /**
  * 企业微信直播接口实现类.
@@ -28,9 +28,12 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
   private final WxCpService cpService;
 
   @Override
-  public String getLivingCode(@NonNull WxCpGetLivingCode livingCode) throws WxErrorException {
+  public String getLivingCode(String openId, String livingId) throws WxErrorException {
     final String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_CODE);
-    String responseContent = this.cpService.post(apiUrl, livingCode.toJson());
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("openid", openId);
+    jsonObject.addProperty("livingid", livingId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
     return GsonHelper.getString(GsonParser.parse(responseContent), "living_code");
   }
 
@@ -45,4 +48,16 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
       );
   }
 
+  @Override
+  public WxCpWatchStat getWatchStat(String livingId, Integer nextKey) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_WATCH_STAT);
+    JsonObject jsonObject = new JsonObject();
+    if (nextKey != null) {
+      jsonObject.addProperty("next_key", String.valueOf(nextKey));
+    }
+    jsonObject.addProperty("livingid", livingId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpWatchStat.fromJson(responseContent);
+  }
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
deleted file mode 100644
index 9281c0a4d..000000000
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpGetLivingCode.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package me.chanjar.weixin.cp.bean.living;
-
-import lombok.Data;
-import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
-
-import java.io.Serializable;
-
-/**
- * 微信观看直播凭证请求体.
- *
- * @author Wang_Wong
- */
-@Data
-public class WxCpGetLivingCode implements Serializable {
-  private static final long serialVersionUID = -5028321625140879571L;
-
-  private String livingid;
-  private String openid;
-
-  public static WxCpGetLivingCode fromJson(String json) {
-    return WxCpGsonBuilder.create().fromJson(json, WxCpGetLivingCode.class);
-  }
-
-  public String toJson() {
-    return WxCpGsonBuilder.create().toJson(this);
-  }
-
-}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
similarity index 71%
rename from weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java
rename to weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
index 389f8b86d..f14bb3348 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpStatInfo.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
@@ -15,7 +15,7 @@ import java.util.List;
  * @author Wang_Wong
  */
 @Data
-public class WxCpStatInfo implements Serializable {
+public class WxCpWatchStat implements Serializable {
   private static final long serialVersionUID = -5028321625140879571L;
 
   private Integer ending;
@@ -23,11 +23,21 @@ public class WxCpStatInfo implements Serializable {
   @SerializedName("next_key")
   private String nextKey;
 
-  @SerializedName("users")
-  private List users;
+  @SerializedName("stat_info")
+  private StatInfo statInfo;
 
-  @SerializedName("external_users")
-  private List externalUsers;
+  @Getter
+  @Setter
+  public static class StatInfo implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    @SerializedName("users")
+    private List users;
+
+    @SerializedName("external_users")
+    private List externalUsers;
+
+  }
 
   @Getter
   @Setter
@@ -52,7 +62,6 @@ public class WxCpStatInfo implements Serializable {
   public static class ExternalUser implements Serializable {
     private static final long serialVersionUID = -5696099236344075582L;
 
-    private String userid;
     private String name;
     private Integer type;
 
@@ -70,8 +79,8 @@ public class WxCpStatInfo implements Serializable {
 
   }
 
-  public static WxCpStatInfo fromJson(String json) {
-    return WxCpGsonBuilder.create().fromJson(json, WxCpStatInfo.class);
+  public static WxCpWatchStat fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpWatchStat.class);
   }
 
   public String toJson() {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
similarity index 55%
rename from weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
rename to weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 1ee1d9365..76d2c8129 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/bean/living/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -1,9 +1,10 @@
-package me.chanjar.weixin.cp.bean.living;
+package me.chanjar.weixin.cp.api;
 
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
 import org.eclipse.jetty.util.ajax.JSON;
@@ -32,22 +33,20 @@ public class WxCpLivingTest {
     wxCpService = new WxCpServiceImpl();
     wxCpService.setWxCpConfigStorage(config);
 
-    WxCpGetLivingCode wxCpGetLivingCode = new WxCpGetLivingCode();
-    wxCpGetLivingCode.setLivingid("lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
-    wxCpGetLivingCode.setOpenid("o50by5NezHciWnoexJsrI49ILNqI");
-
-    String livingCode = wxCpService.getLivingService().getLivingCode(wxCpGetLivingCode);
+    String livingCode = wxCpService.getLivingService().getLivingCode("o50by5NezHciWnoexJsrI49ILNqI", "lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
     log.info(JSON.toString(livingCode));
 
-    String json = wxCpGetLivingCode.toJson();
-    log.info(json);
-
-    WxCpGetLivingCode getLivingCode = WxCpGetLivingCode.fromJson(json);
-    log.info(getLivingCode.toJson());
-
     WxCpLivingInfo livingInfo = wxCpService.getLivingService().getLivingInfo("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg");
     log.info(livingInfo.toJson());
 
+    WxCpWatchStat watchStat = wxCpService.getLivingService().getWatchStat("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg", 0);
+    log.info(watchStat.toJson());
+
+    final String watchStateJson = "{\"errcode\":0,\"errmsg\":\"ok\",\"ending\":1,\"next_key\":\"NEXT_KEY\",\"stat_info\":{\"users\":[{\"userid\":\"userid\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1}],\"external_users\":[{\"external_userid\":\"external_userid1\",\"type\":1,\"name\":\"user name\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1},{\"external_userid\":\"external_userid2\",\"type\":2,\"name\":\"user_name\",\"watch_time\":30,\"is_comment\":1,\"is_mic\":1}]}}";
+
+    WxCpWatchStat wxCpWatchStat = WxCpWatchStat.fromJson(watchStateJson);
+    log.info(wxCpWatchStat.toJson());
+
   }
 
 }
-- 
Gitee


From a26f929dc9a64d613a23cc17b9166f0aeb58a247 Mon Sep 17 00:00:00 2001
From: wangkai 
Date: Thu, 23 Dec 2021 17:23:31 +0800
Subject: [PATCH 10/12] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96?=
 =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E5=B0=8F=E7=A8=8B=E5=BA=8F=E5=95=86=E5=9F=8E?=
 =?UTF-8?q?=E7=9A=84=E7=9B=B4=E6=92=AD=E8=A7=82=E4=BC=97=E4=BF=A1=E6=81=AF?=
 =?UTF-8?q?=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 19 ++++++++-
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 10 +++++
 .../weixin/cp/bean/living/WxCpLivingInfo.java |  2 +-
 .../cp/bean/living/WxCpLivingShareInfo.java   | 40 +++++++++++++++++++
 .../weixin/cp/bean/living/WxCpWatchStat.java  |  2 +-
 .../weixin/cp/constant/WxCpApiPathConsts.java |  1 +
 .../chanjar/weixin/cp/api/WxCpLivingTest.java |  9 +++++
 7 files changed, 79 insertions(+), 4 deletions(-)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index f035ad5c8..afbef01a1 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.api;
 import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 
 /**
@@ -19,7 +20,8 @@ public interface WxCpLivingService {
    * 请求方式: POST(HTTPS)
    * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/get_living_code?access_token=ACCESS_TOKEN
    *
-   * @param codeParam 直播凭证请求参数
+   * @param openId 用户openid
+   * @param livingId 直播id
    * @return living_code 微信观看直播凭证
    * @throws WxErrorException the wx error exception
    */
@@ -43,11 +45,24 @@ public interface WxCpLivingService {
    * 请求方式:POST(HTTPS)
    * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_watch_stat?access_token=ACCESS_TOKEN
    *
-   * @param livingId 直播的id
+   * @param livingId 直播id
    * @param nextKey 上一次调用时返回的next_key,初次调用可以填”0”
    * @return
    * @throws WxErrorException
    */
   WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
 
+  /**
+   * 获取跳转小程序商城的直播观众信息
+   * 通过此接口,开发者可获取跳转小程序商城的直播间(“推广产品”直播)观众id、邀请人id及对应直播间id,以打通卖货直播的“人货场”信息闭环。
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_living_share_info?access_token=ACCESS_TOKEN
+   *
+   * @param wwShareCode "推广产品"直播观众跳转小程序商城时会在小程序path中带上ww_share_code=xxxxx参数
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException;
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index ff16f0780..f7ad63bd0 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -11,6 +11,7 @@ import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
@@ -60,4 +61,13 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
     return WxCpWatchStat.fromJson(responseContent);
   }
 
+  @Override
+  public WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_SHARE_INFO);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("ww_share_code", wwShareCode);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpLivingShareInfo.fromJson(responseContent);
+  }
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
index 302decda1..b7010e57e 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingInfo.java
@@ -7,7 +7,7 @@ import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 import java.io.Serializable;
 
 /**
- * 直播信息.
+ * 直播详情信息.
  *
  * @author Wang_Wong
  */
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java
new file mode 100644
index 000000000..f0b96cc96
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingShareInfo.java
@@ -0,0 +1,40 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 跳转小程序商城的直播观众信息.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpLivingShareInfo implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  private String livingid;
+
+  @SerializedName("viewer_userid")
+  private String viewerUserid;
+
+  @SerializedName("viewer_external_userid")
+  private String viewerExternalUserid;
+
+  @SerializedName("invitor_userid")
+  private String invitorUserid;
+
+  @SerializedName("invitor_external_userid")
+  private String invitorExternalUserid;
+
+  public static WxCpLivingShareInfo fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingShareInfo.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
index f14bb3348..4a77bdd45 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpWatchStat.java
@@ -10,7 +10,7 @@ import java.io.Serializable;
 import java.util.List;
 
 /**
- * 直播信息.
+ * 直播观看明细.
  *
  * @author Wang_Wong
  */
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index 1e5f28203..f2129306b 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -120,6 +120,7 @@ public interface WxCpApiPathConsts {
     String GET_LIVING_CODE = "/cgi-bin/living/get_living_code";
     String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid=";
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
+    String GET_LIVING_SHARE_INFO = "/cgi-bin/living/get_living_share_info";
   }
 
   interface Tag {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 76d2c8129..2fb0267cf 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
@@ -36,9 +37,11 @@ public class WxCpLivingTest {
     String livingCode = wxCpService.getLivingService().getLivingCode("o50by5NezHciWnoexJsrI49ILNqI", "lvOQpTDwAAD2MYuOq9y_bmLNMJfbbdGw");
     log.info(JSON.toString(livingCode));
 
+    // 直播详情
     WxCpLivingInfo livingInfo = wxCpService.getLivingService().getLivingInfo("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg");
     log.info(livingInfo.toJson());
 
+    // 直播观看明细
     WxCpWatchStat watchStat = wxCpService.getLivingService().getWatchStat("lvOQpTDwAAcP9wNOSSxTwpbni-TMPNSg", 0);
     log.info(watchStat.toJson());
 
@@ -47,6 +50,12 @@ public class WxCpLivingTest {
     WxCpWatchStat wxCpWatchStat = WxCpWatchStat.fromJson(watchStateJson);
     log.info(wxCpWatchStat.toJson());
 
+    // 直播观众信息
+    final String livingShareInfo = "{\"errcode\":0,\"errmsg\":\"ok\",\"livingid\":\"livingid\",\"viewer_userid\":\"viewer_userid\",\"viewer_external_userid\":\"viewer_external_userid\",\"invitor_userid\":\"invitor_userid\",\"invitor_external_userid\":\"invitor_external_userid\"}";
+
+    WxCpLivingShareInfo wxCpLivingShareInfo = WxCpLivingShareInfo.fromJson(livingShareInfo);
+    log.info(wxCpLivingShareInfo.toJson());
+
   }
 
 }
-- 
Gitee


From 972ef4cd2c4e9851d498e2d4429a3f2a3b8538ec Mon Sep 17 00:00:00 2001
From: wangkai 
Date: Thu, 23 Dec 2021 18:31:09 +0800
Subject: [PATCH 11/12] =?UTF-8?q?=E3=80=90=E4=BC=81=E4=B8=9A=E5=BE=AE?=
 =?UTF-8?q?=E4=BF=A1=E3=80=91=E5=A2=9E=E5=8A=A0=E8=8E=B7=E5=8F=96=E6=88=90?=
 =?UTF-8?q?=E5=91=98=E7=9B=B4=E6=92=ADID=E5=88=97=E8=A1=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 16 +++++
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 19 +++++-
 .../cp/bean/living/WxCpLivingResult.java      | 62 +++++++++++++++++++
 .../weixin/cp/constant/WxCpApiPathConsts.java |  1 +
 .../chanjar/weixin/cp/api/WxCpLivingTest.java | 10 +++
 5 files changed, 106 insertions(+), 2 deletions(-)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index afbef01a1..321651f42 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -3,6 +3,7 @@ package me.chanjar.weixin.cp.api;
 import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 
@@ -52,6 +53,21 @@ public interface WxCpLivingService {
    */
   WxCpWatchStat getWatchStat(@NonNull String livingId, Integer nextKey) throws WxErrorException;
 
+  /**
+   * 获取成员直播ID列表
+   * 通过此接口可以获取指定成员的所有直播ID
+   *
+   * 请求方式:POST(HTTPS)
+   * 请求地址:https://qyapi.weixin.qq.com/cgi-bin/living/get_user_all_livingid?access_token=ACCESS_TOKEN
+   *
+   * @param userId 企业成员的userid
+   * @param cursor 上一次调用时返回的next_cursor,第一次拉取可以不填
+   * @param limit 每次拉取的数据量,默认值和最大值都为100
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingResult.LivingIdResult getUserAllLivingId(@NonNull String userId, String cursor, Integer limit) throws WxErrorException;
+
   /**
    * 获取跳转小程序商城的直播观众信息
    * 通过此接口,开发者可获取跳转小程序商城的直播间(“推广产品”直播)观众id、邀请人id及对应直播间id,以打通卖货直播的“人货场”信息闭环。
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index f7ad63bd0..ade8fc3ce 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -2,7 +2,6 @@ package me.chanjar.weixin.cp.api.impl;
 
 import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
-import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -11,6 +10,7 @@ import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
@@ -62,7 +62,22 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
   }
 
   @Override
-  public WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException {
+  public WxCpLivingResult.LivingIdResult getUserAllLivingId(String userId, String cursor, Integer limit) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_USER_ALL_LIVINGID);
+    JsonObject jsonObject = new JsonObject();
+    if (cursor != null) {
+      jsonObject.addProperty("cursor", cursor);
+    }
+    if (limit != null) {
+      jsonObject.addProperty("limit", limit);
+    }
+    jsonObject.addProperty("userid", userId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpLivingResult.LivingIdResult.fromJson(responseContent);
+  }
+
+  @Override
+  public WxCpLivingShareInfo getLivingShareInfo(String wwShareCode) throws WxErrorException {
     String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(GET_LIVING_SHARE_INFO);
     JsonObject jsonObject = new JsonObject();
     jsonObject.addProperty("ww_share_code", wwShareCode);
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
new file mode 100644
index 000000000..35842e08f
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
@@ -0,0 +1,62 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 直播返回对象.
+ *
+ * @author Wang_Wong
+ */
+@Data
+public class WxCpLivingResult implements Serializable {
+  private static final long serialVersionUID = -5028321625140879571L;
+
+  private Integer errcode;
+  private String errmsg;
+
+  @Getter
+  @Setter
+  public static class LivingCeateResult implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    @SerializedName("livingid")
+    private String livingid;
+
+  }
+
+  @Getter
+  @Setter
+  public static class LivingIdResult implements Serializable {
+    private static final long serialVersionUID = -5696099236344075582L;
+
+    @SerializedName("next_cursor")
+    private String nextCursor;
+
+    @SerializedName("livingid_list")
+    private String[] livingidList;
+
+    public static LivingIdResult fromJson(String json) {
+      return WxCpGsonBuilder.create().fromJson(json, LivingIdResult.class);
+    }
+
+    public String toJson() {
+      return WxCpGsonBuilder.create().toJson(this);
+    }
+
+  }
+
+  public static WxCpLivingResult fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingResult.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index f2129306b..8887ef4cd 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -121,6 +121,7 @@ public interface WxCpApiPathConsts {
     String GET_LIVING_INFO = "/cgi-bin/living/get_living_info?livingid=";
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
     String GET_LIVING_SHARE_INFO = "/cgi-bin/living/get_living_share_info";
+    String GET_USER_ALL_LIVINGID = "/cgi-bin/living/get_user_all_livingid";
   }
 
   interface Tag {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 2fb0267cf..2db8e3327 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
+import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
 import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
 import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
@@ -15,6 +16,7 @@ import java.io.InputStream;
 
 /**
  * 企业微信直播测试类.
+ * 官方文档:https://open.work.weixin.qq.com/api/doc/90000/90135/93632
  *
  * @author Wang_Wong
  */
@@ -56,6 +58,14 @@ public class WxCpLivingTest {
     WxCpLivingShareInfo wxCpLivingShareInfo = WxCpLivingShareInfo.fromJson(livingShareInfo);
     log.info(wxCpLivingShareInfo.toJson());
 
+    // 获取成员直播ID列表
+    WxCpLivingResult.LivingIdResult livingResult = wxCpService.getLivingService().getUserAllLivingId("ChenHu", null, null);
+    log.info(livingResult.toJson());
+
+    String livinglist = "{\"errcode\":0,\"errmsg\":\"ok\",\"next_cursor\":\"next_cursor\",\"livingid_list\":[\"livingid1\",\"livingid2\"]}";
+    WxCpLivingResult.LivingIdResult livingIdResult = WxCpLivingResult.LivingIdResult.fromJson(livinglist);
+    log.info(livingIdResult.toJson());
+
   }
 
 }
-- 
Gitee


From ff9012f817260a6386132076a68730a9037980b7 Mon Sep 17 00:00:00 2001
From: wangkai 
Date: Thu, 23 Dec 2021 22:39:46 +0800
Subject: [PATCH 12/12] =?UTF-8?q?=E3=80=90=E4=BC=81=E4=B8=9A=E5=BE=AE?=
 =?UTF-8?q?=E4=BF=A1=E3=80=91=E5=A2=9E=E5=8A=A0=E9=A2=84=E7=BA=A6=E7=9B=B4?=
 =?UTF-8?q?=E6=92=AD=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../weixin/cp/api/WxCpLivingService.java      | 49 ++++++++++-
 .../cp/api/impl/WxCpLivingServiceImpl.java    | 38 +++++++-
 .../bean/living/WxCpLivingCreateRequest.java  | 86 +++++++++++++++++++
 .../bean/living/WxCpLivingModifyRequest.java  | 56 ++++++++++++
 .../cp/bean/living/WxCpLivingResult.java      | 13 +--
 .../weixin/cp/constant/WxCpApiPathConsts.java |  5 ++
 .../chanjar/weixin/cp/api/WxCpLivingTest.java | 36 +++++++-
 7 files changed, 261 insertions(+), 22 deletions(-)
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java
 create mode 100644 weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingModifyRequest.java

diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
index 321651f42..4b417e90f 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpLivingService.java
@@ -2,10 +2,7 @@ package me.chanjar.weixin.cp.api;
 
 import lombok.NonNull;
 import me.chanjar.weixin.common.error.WxErrorException;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
-import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
+import me.chanjar.weixin.cp.bean.living.*;
 
 /**
  * 企业微信直播接口.
@@ -81,4 +78,48 @@ public interface WxCpLivingService {
    */
   WxCpLivingShareInfo getLivingShareInfo(@NonNull String wwShareCode) throws WxErrorException;
 
+  /**
+   * 创建预约直播
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/create?access_token=ACCESS_TOKEN
+   *
+   * @param request 创建预约直播请求参数.
+   * @return
+   * @throws WxErrorException
+   */
+  String livingCreate(WxCpLivingCreateRequest request) throws WxErrorException;
+
+  /**
+   * 修改预约直播
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/modify?access_token=ACCESS_TOKEN
+   *
+   * @param request 修改预约直播请求参数.
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingResult livingModify(WxCpLivingModifyRequest request) throws WxErrorException;
+
+  /**
+   * 取消预约直播
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/cancel?access_token=ACCESS_TOKEN
+   *
+   * @param livingId 直播id,仅允许取消预约状态下的直播id
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingResult livingCancel(@NonNull String livingId) throws WxErrorException;
+
+  /**
+   * 删除直播回放
+   * 请求方式: POST(HTTPS)
+   * 请求地址: https://qyapi.weixin.qq.com/cgi-bin/living/delete_replay_data?access_token=ACCESS_TOKEN
+   *
+   * @param livingId 直播id
+   * @return
+   * @throws WxErrorException
+   */
+  WxCpLivingResult deleteReplayData(@NonNull String livingId) throws WxErrorException;
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
index ade8fc3ce..5fdf18cf8 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpLivingServiceImpl.java
@@ -2,6 +2,7 @@ package me.chanjar.weixin.cp.api.impl;
 
 import com.google.gson.JsonObject;
 import com.google.gson.reflect.TypeToken;
+import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
@@ -9,10 +10,7 @@ import me.chanjar.weixin.common.util.json.GsonHelper;
 import me.chanjar.weixin.common.util.json.GsonParser;
 import me.chanjar.weixin.cp.api.WxCpLivingService;
 import me.chanjar.weixin.cp.api.WxCpService;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
-import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
+import me.chanjar.weixin.cp.bean.living.*;
 import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
 
 import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.Living.*;
@@ -85,4 +83,36 @@ public class WxCpLivingServiceImpl implements WxCpLivingService {
     return WxCpLivingShareInfo.fromJson(responseContent);
   }
 
+  @Override
+  public String livingCreate(WxCpLivingCreateRequest request) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(CREATE);
+    String responseContent = this.cpService.post(apiUrl, request.toJson());
+    return GsonHelper.getString(GsonParser.parse(responseContent), "livingid");
+  }
+
+  @Override
+  public WxCpLivingResult livingModify(WxCpLivingModifyRequest request) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(MODIFY);
+    String responseContent = this.cpService.post(apiUrl, request.toJson());
+    return WxCpLivingResult.fromJson(responseContent);
+  }
+
+  @Override
+  public WxCpLivingResult livingCancel(@NonNull String livingId) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(CANCEL);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("livingid", livingId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpLivingResult.fromJson(responseContent);
+  }
+
+  @Override
+  public WxCpLivingResult deleteReplayData(@NonNull String livingId) throws WxErrorException {
+    String apiUrl = this.cpService.getWxCpConfigStorage().getApiUrl(DELETE_REPLAY_DATA);
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("livingid", livingId);
+    String responseContent = this.cpService.post(apiUrl, jsonObject.toString());
+    return WxCpLivingResult.fromJson(responseContent);
+  }
+
 }
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java
new file mode 100644
index 000000000..6da6b81e5
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingCreateRequest.java
@@ -0,0 +1,86 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 创建预约直播请求.
+ *
+ * @author Wang_Wong
+ * @date 2021-12-23
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class WxCpLivingCreateRequest implements Serializable {
+  private static final long serialVersionUID = -4960239393895754138L;
+
+  @SerializedName("anchor_userid")
+  private String anchorUserid;
+
+  @SerializedName("theme")
+  private String theme;
+
+  @SerializedName("living_start")
+  private Long livingStart;
+
+  @SerializedName("living_duration")
+  private Long livingDuration;
+
+  @SerializedName("remind_time")
+  private Long remindTime;
+
+  @SerializedName("description")
+  private String description;
+
+  @SerializedName("type")
+  private Integer type;
+
+  @SerializedName("agentid")
+  private Integer agentId;
+
+  @SerializedName("activity_cover_mediaid")
+  private String activityCoverMediaid;
+
+  @SerializedName("activity_share_mediaid")
+  private String activityShareMediaid;
+
+  @SerializedName("activity_detail")
+  private ActivityDetail activityDetail;
+
+  public static class ActivityDetail implements Serializable {
+
+    @SerializedName("image_list")
+    private String[] imageList;
+
+    @SerializedName("description")
+    private String description;
+
+    public static ActivityDetail fromJson(String json) {
+      return WxCpGsonBuilder.create().fromJson(json, ActivityDetail.class);
+    }
+
+    public String toJson() {
+      return WxCpGsonBuilder.create().toJson(this);
+    }
+
+  }
+
+  public static WxCpLivingCreateRequest fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingCreateRequest.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingModifyRequest.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingModifyRequest.java
new file mode 100644
index 000000000..00d193820
--- /dev/null
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingModifyRequest.java
@@ -0,0 +1,56 @@
+package me.chanjar.weixin.cp.bean.living;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
+
+import java.io.Serializable;
+
+/**
+ * 创建预约直播请求.
+ *
+ * @author Wang_Wong
+ * @date 2021-12-23
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+public class WxCpLivingModifyRequest implements Serializable {
+  private static final long serialVersionUID = -4960239393895754138L;
+
+  @SerializedName("livingid")
+  private String livingId;
+
+  @SerializedName("theme")
+  private String theme;
+
+  @SerializedName("living_start")
+  private Long livingStart;
+
+  @SerializedName("living_duration")
+  private Long livingDuration;
+
+  @SerializedName("remind_time")
+  private Long remindTime;
+
+  @SerializedName("description")
+  private String description;
+
+  @SerializedName("type")
+  private Integer type;
+
+  public static WxCpLivingModifyRequest fromJson(String json) {
+    return WxCpGsonBuilder.create().fromJson(json, WxCpLivingModifyRequest.class);
+  }
+
+  public String toJson() {
+    return WxCpGsonBuilder.create().toJson(this);
+  }
+
+}
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
index 35842e08f..3312eec77 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/living/WxCpLivingResult.java
@@ -17,18 +17,11 @@ import java.io.Serializable;
 public class WxCpLivingResult implements Serializable {
   private static final long serialVersionUID = -5028321625140879571L;
 
+  @SerializedName("errcode")
   private Integer errcode;
-  private String errmsg;
-
-  @Getter
-  @Setter
-  public static class LivingCeateResult implements Serializable {
-    private static final long serialVersionUID = -5696099236344075582L;
-
-    @SerializedName("livingid")
-    private String livingid;
 
-  }
+  @SerializedName("errmsg")
+  private String errmsg;
 
   @Getter
   @Setter
diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
index 8887ef4cd..c807b0f04 100644
--- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
+++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/constant/WxCpApiPathConsts.java
@@ -122,6 +122,11 @@ public interface WxCpApiPathConsts {
     String GET_WATCH_STAT = "/cgi-bin/living/get_watch_stat";
     String GET_LIVING_SHARE_INFO = "/cgi-bin/living/get_living_share_info";
     String GET_USER_ALL_LIVINGID = "/cgi-bin/living/get_user_all_livingid";
+
+    String CREATE = "/cgi-bin/living/create";
+    String MODIFY = "/cgi-bin/living/modify";
+    String CANCEL = "/cgi-bin/living/cancel";
+    String DELETE_REPLAY_DATA = "/cgi-bin/living/delete_replay_data";
   }
 
   interface Tag {
diff --git a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
index 2db8e3327..295f0497f 100644
--- a/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
+++ b/weixin-java-cp/src/test/java/me/chanjar/weixin/cp/api/WxCpLivingTest.java
@@ -3,16 +3,14 @@ package me.chanjar.weixin.cp.api;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingInfo;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingResult;
-import me.chanjar.weixin.cp.bean.living.WxCpLivingShareInfo;
-import me.chanjar.weixin.cp.bean.living.WxCpWatchStat;
+import me.chanjar.weixin.cp.bean.living.*;
 import me.chanjar.weixin.cp.config.WxCpConfigStorage;
 import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
 import org.eclipse.jetty.util.ajax.JSON;
 import org.testng.annotations.Test;
 
 import java.io.InputStream;
+import java.util.Date;
 
 /**
  * 企业微信直播测试类.
@@ -66,6 +64,36 @@ public class WxCpLivingTest {
     WxCpLivingResult.LivingIdResult livingIdResult = WxCpLivingResult.LivingIdResult.fromJson(livinglist);
     log.info(livingIdResult.toJson());
 
+
+    log.info("{}", new Date().getTime());
+    // 创建预约直播
+    String create = "{\"anchor_userid\":\"ChenHu\",\"theme\":\"theme\",\"living_start\":164037820420,\"living_duration\":3600,\"description\":\"test description\",\"type\":4,\"remind_time\":60,\"activity_cover_mediaid\":\"MEDIA_ID\",\"activity_share_mediaid\":\"MEDIA_ID\",\"activity_detail\":{\"description\":\"活动描述,非活动类型的直播不用传\",\"image_list\":[\"xxxx1\",\"xxxx1\"]}}";
+    WxCpLivingCreateRequest request = WxCpLivingCreateRequest.fromJson(create);
+    String livingId = wxCpService.getLivingService().livingCreate(request);
+    log.info("livingId为:{}", livingId);
+
+
+    String modify = "{\"livingid\": \""+ livingId +"\",\"theme\":\"theme\",\"living_start\":164047820420,\"living_duration\":3600,\"description\":\"描述:description\",\"type\":1,\"remind_time\":60}";
+    WxCpLivingModifyRequest modifyReq = WxCpLivingModifyRequest.fromJson(modify);
+    WxCpLivingResult result = wxCpService.getLivingService().livingModify(modifyReq);
+    log.info("result:{}", result.toJson());
+
+
+    // 取消预约直播
+//    WxCpLivingResult result2 = wxCpService.getLivingService().livingCancel("lvOQpTDwAA0KyLmWZhf_LIENzYIBVD2g");
+    WxCpLivingResult result2 = wxCpService.getLivingService().livingCancel(livingId);
+    log.info("取消预约直播为:{}", result2.toJson());
+
+
+    // 删除直播回放
+//    WxCpLivingResult response = wxCpService.getLivingService().deleteReplayData("lvOQpTDwAAVdCHyXMgSK63TKPfKDII7w");
+//    log.info(response.toJson());
+
+
+  }
+
+  public static void main(String[] args){
+    log.info("{}", new Date().getTime());
   }
 
 }
-- 
Gitee