springboot集成企业微信收发应用消息

2020-07-31 03:22:19  晓掌柜  版权声明:本文为站长原创文章,转载请写明出处


一、背景


    在之前的业务中,我们的消息推送是使用的微信公众号的模板消息。

    但是有几个痛点:

        ① 模板要申请,不能应急处理一些场景。
        ② 模板能支持的自定义操作有限。
        ③ 消息内容及形式相对单一

        所以,在最近的版本中,我们准备把内部消息推送统一集中到企业微信上(在企业微信建立专门的应用用以收发消息)


二、准备工作


    2.1、创建应用

        首先登陆企业微信(注册,认证等工作按需处理),创建应用。


    2.2、获取应用信息

        创建应用后会给到你应用的ID,秘钥,设置可见范围,定义管理员等,大致如下:


         


    2.3、接入开发api

        接入到企业微信开发api后,按照既定规则进行http请求,应用消息的发送api接口文档连接如下:  

       发送应用消息        


       

三、程序规划


    ① 首先这个发送消息的程序定义成一个单独的服务节点,统一接收外部请求
    ② 可配置:满足不同的消息格式及使用场景(卡片消息、文字消息、事件A的消息、事件B的消息)


四、程序设计


    4.1、定义消息类型枚举

        支持不同的消息类型

   
    MSG_TYPE_00(0, "文本消息"),
    MSG_TYPE_01(1, "图片消息"),
MSG_TYPE_02(2, "语音消息"),
MSG_TYPE_03(3, "视频消息"),
MSG_TYPE_04(4, "文件消息"),
MSG_TYPE_05(5, "图文消息"),
MSG_TYPE_06(6, "卡片消息");

    4.2、定义不同的业务场景

        配置业务场景枚举,适配不同场景下的业务需求
    
    EVENT_00(0, "货物XX"),
EVENT_01(1, "增值XX"),
EVENT_02(2, "XX件"),
EVENT_03(3, "退XX"),
EVENT_04(4, "待XXX"),
EVENT_05(5, "已XX"),
EVENT_06(6, "退XX过"),
EVENT_07(7, "未XX"),
EVENT_08(8, "货XXX"),
EVENT_09(9, "增XXX成"),
EVENT_10(10, "问XX成"),
EVENT_11(11, "已XXX"),
EVENT_12(12, "程序预警");


五、整个消息发送的流程


    5.1、主入口接收消息类型和消息相关参数

        作为总的入口进行业务的分发处理。

    5.2、获取token

        根据在企业微信注册的信息获取token,作为后续的操作凭证。

        因为token会自动过期及腾讯方业务需要过期,所以要加入重试机制。

    5.3、格式化消息内容

        根据消息类型枚举类中的配置及对应业务场景来动态创建消息内容。

    5.4、发送应用消息

        调用企业微信api进行消息发送

    5.5、返回结果值

        监听返回结果值,并作出对应处理。


六、核心代码如下


    6.1、获取token

     
    /**
* 功能描述: 获取应用的操作token
* Param: [isOutTime] 是否过期或不合法...
* Return: java.lang.String
*/
public String getToken(boolean isOutTime){
/* 从redis获取token */
Object tokenObj = redisUtil.get("wechatToken");
if(tokenObj == null || isOutTime){
String url = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", groupId, groupSecret);
String rltStr = HttpClientUtil.doGet(url, null);
/* 失败重试3次 */
for(int i=0;i<3;i++){
JSONObject jsonRlt = JSON.parseObject(rltStr);
if(0 != jsonRlt.getIntValue("errcode")){
rltStr = HttpClientUtil.doGet(url, null);
}else{
String tokenStr = jsonRlt.getString("access_token");
/* 保存到redis缓存(token有效期为7200) */
redisUtil.set("wechatToken", tokenStr, 60 * 60 * 2);
return tokenStr;
}
}
}
assert tokenObj != null;
return tokenObj.toString();
}

 

   6.2、token验证及消息重入

    
     /**
* 功能描述:消息发送实现类
* Param: [msgType, msgHandlerVO]
* Return: com.bh.enterprisewechat.commons.utils.R
*/
@Override
public R sendMsgByType(int msgType, MsgHandlerVO msgHandlerVO) {
String token = tokenUtil.getToken(false);
if(token == null){
return R.error("获取token失败!");
}
/* 消息发送失败后重试(3次)*/
String rltStr = formatPost(msgType, token, msgHandlerVO);
for(int i=0;i<3;i++){
JSONObject rltJson = JSON.parseObject(rltStr);
int errCode = rltJson.getIntValue("errcode");
if(0 != errCode){
/* 中间判断是否为token过期,或者不合法 */
if(42001 == errCode || 40014 == errCode){
token = tokenUtil.getToken(true);
}
rltStr = formatPost(msgType, token, msgHandlerVO);
}else{
return R.ok();
}
}
return R.error().put("data", rltStr);
}

 

   6.3、格式化消息格式、内容及发送

    
     /**
* 功能描述: 消息分发 (XXX)
* Param: [type, token, msgVO]
* Return: java.lang.String
*/
private String formatPost(int type,String token, MsgHandlerVO msgHandlerVO){
TextMsgVO textMsgVO;
TextCardMsgVO textCardMsgVO;
String rltStr = null;
String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + token;
Integer eventKey = msgHandlerVO.getEventType().getKey();
switch (type){
case 0: /* 此处省略部分业务处理... */ /* 程序预警 */
if(eventKey == 12){ // 此处省略格式化消息内容处理... textCardMsgVO = buildTextCardMsg("warning", msgHandlerVO);
rltStr = HttpClientUtil.sendJsonStr(url, JSONObject.toJSONString(textCardMsgVO));
}

break;
default:
break;
}
return rltStr;
}

    

七、成品展示(文本消息和卡片消息)

   

        


        

更多精彩请关注guangmuhua.com


最新评论: