企业微信机器人 后端接入

pull/11/head
3y 3 years ago
parent ec2950b0b3
commit 7ea71af0a4

@ -48,6 +48,12 @@ public class SendAccountConstant {
public static final String DING_DING_ROBOT_ACCOUNT_KEY = "dingDingRobotAccount";
public static final String DING_DING_ROBOT_PREFIX = "ding_ding_robot_";
/**
*
*/
public static final String ENTERPRISE_WECHAT_ROBOT_ACCOUNT_KEY = "enterpriseWechatAccountRobot";
public static final String ENTERPRISE_WECHAT_ROBOT_PREFIX = "enterprise_wechat_robot_";
/**
*
*/

@ -0,0 +1,24 @@
package com.java3y.austin.common.dto.account;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
*
* @author 3y
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EnterpriseWeChatRobotAccount {
/**
* webhook
*/
private String webhook;
}

@ -60,7 +60,7 @@ public class EnterpriseWeChatContentModel extends ContentModel {
/**
* mpnews
* [{"title":"Title","thumb_media_id":"MEDIA_ID","author":"Author","content_source_url":"URL","content":"Content","digest":"Digest description"}]
* [{"title":"Title","thumb_media_id":"MEDIA_ID","author":"Author","content_source_url":"URL","content":"Content","digest":"Digest description"}]
*/
private String mpNewsArticle;
@ -74,12 +74,8 @@ public class EnterpriseWeChatContentModel extends ContentModel {
private String contentItems;
/**
* https://developer.work.weixin.qq.com/document/path/90372#%E6%96%87%E6%9C%AC%E6%B6%88%E6%81%AF
*/
}

@ -0,0 +1,44 @@
package com.java3y.austin.common.dto.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author 3y
*
* <p>
* https://developer.work.weixin.qq.com/document/path/91770#%E6%96%87%E6%9C%AC%E7%B1%BB%E5%9E%8B
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EnterpriseWeChatRobotContentModel extends ContentModel {
/**
*
*/
private String sendType;
/**
*
*/
private String content;
/**
* Id
*/
private String mediaId;
/**
* [{"title":"中秋节礼品领取","description":"今年中秋节公司有豪礼相送","url":"www.qq.com","picurl":"http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png"}]
*/
private String articles;
/**
*
*/
private String imagePath;
}

@ -26,6 +26,7 @@ public enum ChannelType {
ENTERPRISE_WE_CHAT(70, "EnterpriseWeChat(企业微信)", EnterpriseWeChatContentModel.class, "enterprise_we_chat"),
DING_DING_ROBOT(80, "dingDingRobot(钉钉机器人)", DingDingRobotContentModel.class, "ding_ding_robot"),
DING_DING_WORK_NOTICE(90, "dingDingWorkNotice(钉钉工作通知)", DingDingWorkContentModel.class, "ding_ding_work_notice"),
ENTERPRISE_WE_CHAT_ROBOT(100, "EnterpriseWeChat(企业微信机器人)", EnterpriseWeChatRobotContentModel.class, "enterprise_we_chat_robot"),
;
/**

@ -14,20 +14,20 @@ import lombok.ToString;
@AllArgsConstructor
public enum SendMessageType {
TEXT("10", "文本", "text", "text"),
VOICE("20", "语音", null, "voice"),
VIDEO("30", "视频", null, null),
NEWS("40", "图文", "feedCard", null),
TEXT_CARD("50", "文本卡片", null, null),
FILE("60", "文件", null, "file"),
MINI_PROGRAM_NOTICE("70", "小程序通知", null, null),
MARKDOWN("80", "markdown", "markdown", "markdown"),
TEMPLATE_CARD("90", "模板卡片", null, null),
IMAGE("100", "图片", null, "image"),
LINK("110", "链接消息", "link", "link"),
ACTION_CARD("120", "跳转卡片消息", "actionCard", "action_card"),
OA("130", "OA消息", null, "oa"),
MP_NEWS("140", "图文消息(mpnews)", null, null),
TEXT("10", "文本", "text", "text","text"),
VOICE("20", "语音", null, "voice",null),
VIDEO("30", "视频", null, null,null),
NEWS("40", "图文", "feedCard", null,"news"),
TEXT_CARD("50", "文本卡片", null, null,null),
FILE("60", "文件", null, "file","file"),
MINI_PROGRAM_NOTICE("70", "小程序通知", null, null,null),
MARKDOWN("80", "markdown", "markdown", "markdown","markdown"),
TEMPLATE_CARD("90", "模板卡片", null, null,"template_card"),
IMAGE("100", "图片", null, "image","image"),
LINK("110", "链接消息", "link", "link",null),
ACTION_CARD("120", "跳转卡片消息", "actionCard", "action_card",null),
OA("130", "OA消息", null, "oa",null),
MP_NEWS("140", "图文消息(mpnews)", null, null,null),
;
@ -44,6 +44,11 @@ public enum SendMessageType {
*/
private String dingDingWorkType;
/**
*
*/
private String enterpriseWeChatRobotType;
/**
* codeType
@ -75,5 +80,19 @@ public enum SendMessageType {
return null;
}
/**
* codeType
*
* @param code
* @return
*/
public static String getEnterpriseWeChatRobotTypeByCode(String code) {
for (SendMessageType value : SendMessageType.values()) {
if (value.getCode().equals(code)) {
return value.getEnterpriseWeChatRobotType();
}
}
return null;
}
}

@ -0,0 +1,437 @@
package com.java3y.austin.handler.domain.wechat.robot;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
*
*
* https://open.dingtalk.com/document/group/custom-robot-access
*
* @author 3y
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EnterpriseWeChatRobotParam {
/**
* msgtype
*/
@JSONField(name = "msgtype")
private String msgType;
/**
* text
*/
@JSONField(name = "text")
private TextDTO text;
/**
* markdown
*/
@JSONField(name = "markdown")
private MarkdownDTO markdown;
/**
* markdown
*/
@JSONField(name = "image")
private ImageDTO image;
/**
* news
*/
@JSONField(name = "news")
private NewsDTO news;
/**
* file
*/
@JSONField(name = "file")
private FileDTO file;
/**
* templateCard
*/
@JSONField(name = "template_card")
private TemplateCardDTO templateCard;
/**
* TextDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class TextDTO {
/**
* content
*/
@JSONField(name = "content")
private String content;
/**
* mentionedList
*/
@JSONField(name = "mentioned_list")
private List<String> mentionedList;
/**
* mentionedMobileList
*/
@JSONField(name = "mentioned_mobile_list")
private List<String> mentionedMobileList;
}
/**
* MarkdownDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class MarkdownDTO {
/**
* content
*/
@JSONField(name = "content")
private String content;
}
/**
* ImageDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class ImageDTO {
/**
* base64
*/
@JSONField(name = "base64")
private String base64;
@JSONField(name = "md5")
private String md5;
}
/**
* NewsDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class NewsDTO {
/**
* articles
*/
@JSONField(name = "articles")
private List<ArticlesDTO> articles;
/**
* ArticlesDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class ArticlesDTO {
/**
* title
*/
@JSONField(name = "title")
private String title;
/**
* description
*/
@JSONField(name = "description")
private String description;
/**
* url
*/
@JSONField(name = "url")
private String url;
/**
* picurl
*/
@JSONField(name = "picurl")
private String picurl;
}
}
/**
* FileDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class FileDTO {
/**
* mediaId
*/
@JSONField(name = "media_id")
private String mediaId;
}
/**
* TemplateCardDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class TemplateCardDTO {
/**
* cardType
*/
@JSONField(name = "card_type")
private String cardType;
/**
* source
*/
@JSONField(name = "source")
private SourceDTO source;
/**
* mainTitle
*/
@JSONField(name = "main_title")
private MainTitleDTO mainTitle;
/**
* emphasisContent
*/
@JSONField(name = "emphasis_content")
private EmphasisContentDTO emphasisContent;
/**
* quoteArea
*/
@JSONField(name = "quote_area")
private QuoteAreaDTO quoteArea;
/**
* subTitleText
*/
@JSONField(name = "sub_title_text")
private String subTitleText;
/**
* horizontalContentList
*/
@JSONField(name = "horizontal_content_list")
private List<HorizontalContentListDTO> horizontalContentList;
/**
* jumpList
*/
@JSONField(name = "jump_list")
private List<JumpListDTO> jumpList;
/**
* cardAction
*/
@JSONField(name = "card_action")
private CardActionDTO cardAction;
/**
* SourceDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class SourceDTO {
/**
* iconUrl
*/
@JSONField(name = "icon_url")
private String iconUrl;
/**
* desc
*/
@JSONField(name = "desc")
private String desc;
/**
* descColor
*/
@JSONField(name = "desc_color")
private Integer descColor;
}
/**
* MainTitleDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class MainTitleDTO {
/**
* title
*/
@JSONField(name = "title")
private String title;
/**
* desc
*/
@JSONField(name = "desc")
private String desc;
}
/**
* EmphasisContentDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class EmphasisContentDTO {
/**
* title
*/
@JSONField(name = "title")
private String title;
/**
* desc
*/
@JSONField(name = "desc")
private String desc;
}
/**
* QuoteAreaDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class QuoteAreaDTO {
/**
* type
*/
@JSONField(name = "type")
private Integer type;
/**
* url
*/
@JSONField(name = "url")
private String url;
/**
* appid
*/
@JSONField(name = "appid")
private String appid;
/**
* pagepath
*/
@JSONField(name = "pagepath")
private String pagepath;
/**
* title
*/
@JSONField(name = "title")
private String title;
/**
* quoteText
*/
@JSONField(name = "quote_text")
private String quoteText;
}
/**
* CardActionDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class CardActionDTO {
/**
* type
*/
@JSONField(name = "type")
private Integer type;
/**
* url
*/
@JSONField(name = "url")
private String url;
/**
* appid
*/
@JSONField(name = "appid")
private String appid;
/**
* pagepath
*/
@JSONField(name = "pagepath")
private String pagepath;
}
/**
* HorizontalContentListDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class HorizontalContentListDTO {
/**
* keyname
*/
@JSONField(name = "keyname")
private String keyname;
/**
* value
*/
@JSONField(name = "value")
private String value;
/**
* type
*/
@JSONField(name = "type")
private Integer type;
/**
* url
*/
@JSONField(name = "url")
private String url;
/**
* mediaId
*/
@JSONField(name = "media_id")
private String mediaId;
}
/**
* JumpListDTO
*/
@NoArgsConstructor
@Data
@Builder
@AllArgsConstructor
public static class JumpListDTO {
/**
* type
*/
@JSONField(name = "type")
private Integer type;
/**
* url
*/
@JSONField(name = "url")
private String url;
/**
* title
*/
@JSONField(name = "title")
private String title;
/**
* appid
*/
@JSONField(name = "appid")
private String appid;
/**
* pagepath
*/
@JSONField(name = "pagepath")
private String pagepath;
}
}
}

@ -0,0 +1,106 @@
package com.java3y.austin.handler.handler.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.ContentType;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Throwables;
import com.java3y.austin.common.constant.SendAccountConstant;
import com.java3y.austin.common.domain.TaskInfo;
import com.java3y.austin.common.dto.account.EnterpriseWeChatRobotAccount;
import com.java3y.austin.common.dto.model.EnterpriseWeChatRobotContentModel;
import com.java3y.austin.common.enums.ChannelType;
import com.java3y.austin.common.enums.SendMessageType;
import com.java3y.austin.handler.domain.wechat.robot.EnterpriseWeChatRobotParam;
import com.java3y.austin.handler.handler.BaseHandler;
import com.java3y.austin.handler.handler.Handler;
import com.java3y.austin.support.domain.MessageTemplate;
import com.java3y.austin.support.utils.AccountUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
/**
*
*
* @author 3y
*/
@Slf4j
@Service
public class EnterpriseWeChatRobotHandler extends BaseHandler implements Handler {
@Autowired
private AccountUtils accountUtils;
public EnterpriseWeChatRobotHandler() {
channelCode = ChannelType.ENTERPRISE_WE_CHAT_ROBOT.getCode();
}
@Override
public boolean handler(TaskInfo taskInfo) {
try {
EnterpriseWeChatRobotAccount account = accountUtils.getAccount(taskInfo.getSendAccount(), SendAccountConstant.ENTERPRISE_WECHAT_ROBOT_ACCOUNT_KEY, SendAccountConstant.ENTERPRISE_WECHAT_ROBOT_PREFIX, EnterpriseWeChatRobotAccount.class);
EnterpriseWeChatRobotParam enterpriseWeChatRobotParam = assembleParam(taskInfo);
String result = HttpRequest.post(account.getWebhook()).header(Header.CONTENT_TYPE.getValue(), ContentType.JSON.getValue())
.body(JSON.toJSONString(enterpriseWeChatRobotParam))
.timeout(2000)
.execute().body();
JSONObject jsonObject = JSON.parseObject(result);
if (jsonObject.getInteger("errcode") != 0) {
return true;
}
log.error("EnterpriseWeChatRobotHandler#handler fail! result:{},params:{}", JSON.toJSONString(jsonObject), JSON.toJSONString(taskInfo));
} catch (Exception e) {
log.error("EnterpriseWeChatRobotHandler#handler fail!e:{},params:{}", Throwables.getStackTraceAsString(e), JSON.toJSONString(taskInfo));
}
return false;
}
private EnterpriseWeChatRobotParam assembleParam(TaskInfo taskInfo) {
EnterpriseWeChatRobotContentModel contentModel = (EnterpriseWeChatRobotContentModel) taskInfo.getContentModel();
EnterpriseWeChatRobotParam param = EnterpriseWeChatRobotParam.builder()
.msgType(SendMessageType.getEnterpriseWeChatRobotTypeByCode(contentModel.getSendType())).build();
if (SendMessageType.TEXT.getCode().equals(contentModel.getSendType())) {
param.setText(EnterpriseWeChatRobotParam.TextDTO.builder().content(contentModel.getContent()).build());
}
if (SendMessageType.MARKDOWN.getCode().equals(contentModel.getSendType())) {
param.setMarkdown(EnterpriseWeChatRobotParam.MarkdownDTO.builder().content(contentModel.getContent()).build());
}
if (SendMessageType.IMAGE.getCode().equals(contentModel.getSendType())) {
FileReader fileReader = new FileReader(contentModel.getImagePath());
byte[] bytes = fileReader.readBytes();
param.setImage(EnterpriseWeChatRobotParam.ImageDTO.builder().base64(Base64.encode(bytes))
.md5(DigestUtil.md5Hex(bytes)).build());
}
if (SendMessageType.FILE.getCode().equals(contentModel.getSendType())) {
param.setFile(EnterpriseWeChatRobotParam.FileDTO.builder().mediaId(contentModel.getMediaId()).build());
}
if (SendMessageType.NEWS.getCode().equals(contentModel.getSendType())) {
List<EnterpriseWeChatRobotParam.NewsDTO.ArticlesDTO> articlesDTOS = JSON.parseArray(contentModel.getArticles(), EnterpriseWeChatRobotParam.NewsDTO.ArticlesDTO.class);
param.setNews(EnterpriseWeChatRobotParam.NewsDTO.builder().articles(articlesDTOS).build());
}
if (SendMessageType.TEMPLATE_CARD.getCode().equals(contentModel.getSendType())) {
//
}
return param;
}
@Override
public void recall(MessageTemplate messageTemplate) {
}
}

@ -68,6 +68,7 @@ public abstract class AbstractLazyPending<T> {
// 判断是否停止当前线程
if (stop && CollUtil.isEmpty(tasks)) {
executorService.shutdown();
break;
}
} catch (Exception e) {
@ -75,7 +76,7 @@ public abstract class AbstractLazyPending<T> {
}
}
});
executorService.shutdown();
}
/**

Loading…
Cancel
Save