diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java index 76ab62350..8e04977ff 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpExternalContactService.java @@ -1,6 +1,10 @@ package me.chanjar.weixin.cp.api; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import lombok.NonNull; +import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.external.*; @@ -921,5 +925,35 @@ public interface WxCpExternalContactService { */ WxCpProductAlbumResult getProductAlbum(String productId) throws WxErrorException; + /** + *
+ * 上传附件资源 + * https://open.work.weixin.qq.com/api/doc/90001/90143/95178 + *+ * @param mediaType + * @param fileType + * @param attachmentType + * @param inputStream + * @return + * @throws WxErrorException + * @throws IOException + */ + WxMediaUploadResult uploadAttachment(String mediaType, String fileType, Integer attachmentType, + InputStream inputStream) throws WxErrorException, IOException; + + /** + *
+ * 上传附件资源 + * https://open.work.weixin.qq.com/api/doc/90001/90143/95178 + *+ * @param mediaType + * @param attachmentType + * @param file + * @return + * @throws WxErrorException + */ + WxMediaUploadResult uploadAttachment(String mediaType, Integer attachmentType, File file) + throws WxErrorException; + } diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java index a77b42a6c..0da548905 100644 --- a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/WxCpKfService.java @@ -1,5 +1,6 @@ package me.chanjar.weixin.cp.api; +import java.util.List; import me.chanjar.weixin.common.error.WxErrorException; import me.chanjar.weixin.cp.bean.WxCpBaseResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountAdd; @@ -9,6 +10,14 @@ import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountLink; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountLinkResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountListResp; import me.chanjar.weixin.cp.bean.kf.WxCpKfAccountUpd; +import me.chanjar.weixin.cp.bean.kf.WxCpKfCustomerBatchGetResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgListResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendRequest; +import me.chanjar.weixin.cp.bean.kf.WxCpKfMsgSendResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfServiceStateTransResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerListResp; +import me.chanjar.weixin.cp.bean.kf.WxCpKfServicerOpResp; /** * 微信客服接口 @@ -67,4 +76,116 @@ public interface WxCpKfService { */ WxCpKfAccountLinkResp getAccountLink(WxCpKfAccountLink link) throws WxErrorException; + /** + * 接待人员管理 + * 添加指定客服帐号的接待人员,每个客服帐号目前最多可添加500个接待人员。 + * @param openKfid 客服帐号ID + * @param userIdList 接待人员userid列表。第三方应用填密文userid,即open_userid + * 可填充个数:1 ~ 100。超过100个需分批调用。 + * @return 添加客服账号结果 + * @throws WxErrorException 异常 + */ + WxCpKfServicerOpResp addServicer(String openKfid, List
+ * 参数:touser + * 是否必须:是 + * 类型:string + * 说明:指定接收消息的客户UserID + *+ */ + @SerializedName("touser") + private String toUser; + /** + *
+ * 参数:open_kfid + * 是否必须:是 + * 类型:string + * 说明:指定发送消息的客服帐号ID + *+ */ + @SerializedName("open_kfid") + private String openKfid; + /** + *
+ * 参数:msgid + * 是否必须:否 + * 类型:string + * 说明:指定消息ID + *+ */ + @SerializedName("msgid") + private String msgId; + /** + *
+ * 参数:msgtype + * 是否必须:是 + * 类型:string + * 说明:消息类型,(text,image,voice,video,file,link,miniprogram,msgmenu,location) + *+ */ + @SerializedName("msgtype") + private String msgType; + /** + *
+ * 参数:text + * 是否必须:是 + * 类型:obj + * 说明:文本消息 + *+ */ + private WxCpKfTextMsg text; + + /** + *
+ * 参数:image + * 是否必须:是 + * 类型:obj + * 说明:图片消息 + *+ */ + private WxCpKfResourceMsg image; + /** + *
+ * 参数:voice + * 是否必须:是 + * 类型:obj + * 说明:语音消息 + *+ */ + private WxCpKfResourceMsg voice; + /** + *
+ * 参数:video + * 是否必须:是 + * 类型:obj + * 说明:视频消息 + *+ */ + private WxCpKfResourceMsg video; + /** + *
+ * 参数:file + * 是否必须:是 + * 类型:obj + * 说明:文件消息 + *+ */ + private WxCpKfResourceMsg file; + /** + *
+ * 参数:link + * 是否必须:是 + * 类型:obj + * 说明:链接消息 + *+ */ + private WxCpKfLinkMsg link; + /** + *
+ * 参数:miniprogram + * 是否必须:是 + * 类型:obj + * 说明:小程序消息 + *+ */ + @SerializedName("miniprogram") + private WxCpKfMiniProgramMsg miniProgram; + + /** + *
+ * 参数:msgmenu + * 是否必须:是 + * 类型:obj + * 说明:菜单消息 + *+ */ + @SerializedName("msgmenu") + private WxCpKfMenuMsg msgMenu; + + /** + *
+ * 参数:location + * 是否必须:是 + * 类型:obj + * 说明:菜单消息 + *+ */ + @SerializedName("location") + private WxCpKfLocationMsg location; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfMsgSendResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfMsgSendResp.java new file mode 100644 index 000000000..416edba3b --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfMsgSendResp.java @@ -0,0 +1,24 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * @author leiin + * @date 2022/1/26 7:41 下午 + */ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Data +public class WxCpKfMsgSendResp extends WxCpBaseResp { + @SerializedName("msgid") + private String msgId; + + public static WxCpKfMsgSendResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpKfMsgSendResp.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceStateResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceStateResp.java new file mode 100644 index 000000000..da4aabcdb --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceStateResp.java @@ -0,0 +1,28 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * @author leiin + * @date 2022/1/26 5:00 下午 + */ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Data +public class WxCpKfServiceStateResp extends WxCpBaseResp { + + private static final long serialVersionUID = 8077134413448067090L; + @SerializedName("service_state") + private Integer serviceState; + @SerializedName("servicer_userid") + private String servicerUserId; + + public static WxCpKfServiceStateResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpKfServiceStateResp.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceStateTransResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceStateTransResp.java new file mode 100644 index 000000000..a4988873c --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServiceStateTransResp.java @@ -0,0 +1,27 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * @author leiin + * @date 2022/1/26 5:03 下午 + */ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Data +public class WxCpKfServiceStateTransResp extends WxCpBaseResp { + + private static final long serialVersionUID = -7874378445629022791L; + + @SerializedName("msg_code") + private String msgCode; + + public static WxCpKfServiceStateTransResp fromJson(String json) { + return WxCpGsonBuilder.create().fromJson(json, WxCpKfServiceStateTransResp.class); + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServicerListResp.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServicerListResp.java new file mode 100644 index 000000000..c37e5df13 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/WxCpKfServicerListResp.java @@ -0,0 +1,35 @@ +package me.chanjar.weixin.cp.bean.kf; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import me.chanjar.weixin.cp.bean.WxCpBaseResp; +import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; + +/** + * @author leiin + * @date 2022/1/26 4:29 下午 + */ +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@Data +public class WxCpKfServicerListResp extends WxCpBaseResp { + + private static final long serialVersionUID = -5079770046571012449L; + @SerializedName("servicer_list") + private List
+ * 是否必须:否 + * 说明:菜单ID。不少于1字节 不多于128字节 + *+ */ + private String id; + /** + *
+ * 是否必须:是 + * 说明:菜单显示内容。不少于1字节 不多于128字节 + *+ */ + private String content; + } + + @Getter + @Setter + public static class MenuView { + /** + *
+ * 是否必须:是 + * 说明:点击后跳转的链接。不少于1字节 不多于2048字节 + *+ */ + private String url; + /** + *
+ * 是否必须:是 + * 说明:菜单显示内容。不少于1字节 不多于1024字节 + *+ */ + private String content; + } + + @Getter + @Setter + public static class MiniProgram { + /** + *
+ * 是否必须:是 + * 说明:小程序appid。 + *+ */ + @SerializedName("appid") + private String appId; + /** + *
+ * 点击后进入的小程序页面。 + *+ */ + @SerializedName("pagepath") + private String pagePath; + /** + *
+ * 菜单显示内容。不多于1024字节 + *+ */ + private String content; + } +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfMiniProgramMsg.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfMiniProgramMsg.java new file mode 100644 index 000000000..4e5ce5f2d --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfMiniProgramMsg.java @@ -0,0 +1,46 @@ +package me.chanjar.weixin.cp.bean.kf.msg; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author leiin + * @date 2022/1/26 6:22 下午 + */ +@NoArgsConstructor +@Data +public class WxCpKfMiniProgramMsg { + /** + * 参数:appid + * 是否必须:是 + * 类型:string + * 说明:小程序appid + */ + @SerializedName("appid") + private String appId; + /** + * 参数:title + * 是否必须:否 + * 类型:string + * 说明:小程序消息标题,最多64个字节,超过会自动截断 + */ + @SerializedName("title") + private String title; + /** + * 参数:thumb_media_id + * 是否必须:是 + * 类型:string + * 说明:小程序消息封面的mediaid,封面图建议尺寸为520*416 + */ + @SerializedName("thumb_media_id") + private String thumbMediaId; + /** + * 参数:pagepath + * 是否必须:是 + * 类型:string + * 说明:点击消息卡片后进入的小程序页面路径。注意路径要以.html为后缀,否则在微信中打开会提示找不到页面 + */ + @SerializedName("pagepath") + private String pagePath; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfResourceMsg.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfResourceMsg.java new file mode 100644 index 000000000..43cba65b6 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfResourceMsg.java @@ -0,0 +1,16 @@ +package me.chanjar.weixin.cp.bean.kf.msg; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author leiin + * @date 2022/1/26 5:31 下午 + */ +@NoArgsConstructor +@Data +public class WxCpKfResourceMsg { + @SerializedName("media_id") + private String mediaId; +} diff --git a/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfTextMsg.java b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfTextMsg.java new file mode 100644 index 000000000..1e0ccf076 --- /dev/null +++ b/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/bean/kf/msg/WxCpKfTextMsg.java @@ -0,0 +1,26 @@ +package me.chanjar.weixin.cp.bean.kf.msg; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author leiin + * @date 2022/1/26 5:30 下午 + */ +@NoArgsConstructor +@Data +public class WxCpKfTextMsg { + + /** + *
+ * 参数:content + * 是否必须:是 + * 类型:string + * 说明:消息内容,最长不超过2048个字节 + *+ */ + private String content; + @SerializedName("menu_id") + private String menuId; +} 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 374c7947c..1b803cfdd 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 @@ -249,6 +249,8 @@ public interface WxCpApiPathConsts { String GROUP_WELCOME_TEMPLATE_GET = "/cgi-bin/externalcontact/group_welcome_template/get"; String GROUP_WELCOME_TEMPLATE_DEL = "/cgi-bin/externalcontact/group_welcome_template/del"; + String UPLOAD_ATTACHMENT = "/cgi-bin/media/upload_attachment"; + } interface Kf { @@ -258,5 +260,18 @@ public interface WxCpApiPathConsts { String ACCOUNT_LIST = "/cgi-bin/kf/account/list"; String ADD_CONTACT_WAY = "/cgi-bin/kf/add_contact_way"; + String SERVICER_ADD = "/cgi-bin/kf/servicer/add"; + String SERVICER_DEL = "/cgi-bin/kf/servicer/del"; + String SERVICER_LIST = "/cgi-bin/kf/servicer/list?open_kfid="; + + String SERVICE_STATE_GET = "/cgi-bin/kf/service_state/get"; + String SERVICE_STATE_TRANS = "/cgi-bin/kf/service_state/trans"; + + String SYNC_MSG = "/cgi-bin/kf/sync_msg"; + String SEND_MSG = "/cgi-bin/kf/send_msg"; + + String SEND_MSG_ON_EVENT = "/cgi-bin/kf/send_msg_on_event"; + String CUSTOMER_BATCH_GET = "/cgi-bin/kf/customer/batchget"; + } }