企业微信回调推送消息互动模板

前置条件

# 企业微信后台中设置了url

按以上设置

# 回调url: http://www.baidu.com# token: xxxxx# EncodingAESKey:  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

此处填写的URL需要有两个接口, 一个为Get一个为Post Get作为验证使用

Post作为验证后的调用接口

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Map;@RestController
@RequestMapping("/wxCallback")
public class WxCallbackController {private Environment environment;public static final String token = "xxxxxx";public static final String encodingAesKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";/*** 企业微信回调审批* @return*/@ResponseBody@PostMapping(value = "/callbackCheck")public String callback(final HttpServletRequest request,@RequestParam(name = "msg_signature") final String sMsgSignature,@RequestParam(name = "timestamp") final String sTimestamp,@RequestParam(name = "nonce") final String sNonce) {try {String corpid = environment.getProperty("wx.corpid");InputStream inputStream = request.getInputStream();String sPostData = IOUtils.toString(inputStream, "UTF-8");WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey);//解密String sMsg = wxcpt.DecryptMsg(sMsgSignature, sTimestamp, sNonce, sPostData);//将post数据转换为mapMap<String, String> dataMap = MessageUtil.parseXml(sMsg);//然后去操作你的业务逻辑} catch (Exception e) {e.printStackTrace();}return "success";}/*** get 请求  验签.** @param msgSignature 加密* @param timestamp    时间戳* @param nonce        随机* @param echostr      .* @param response     .* @throws Exception .*/@GetMapping(value = "/callbackCheck")public void callbackCheck(@RequestParam(name = "msg_signature") final String msgSignature,@RequestParam(name = "timestamp") final String timestamp,@RequestParam(name = "nonce") final String nonce,@RequestParam(name = "echostr") final String echostr,final HttpServletResponse response) throws Exception {//企业回调的url-----该url不做任何的业务逻辑,仅仅微信查看是否可以调通.String corpid = environment.getProperty("wx.corpid");WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey);// 随机字符串String sEchoStr = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);PrintWriter out = response.getWriter();try {//必须要返回解密之后的明文if (StringUtils.isBlank(sEchoStr)) {System.out.println("URL验证失败");} else {System.out.println("验证成功!");}} catch (Exception e) {e.printStackTrace();}out.write(sEchoStr);out.flush();}
}

其中所用到的加密解密方法都是由企业微信官方提供

https://open.work.weixin.qq.com/wwopen/downloadfile/java.zip

下载地址目前我只使用解密方式是xml的,估计是腾讯的开发大部分是c++

模板卡片事件推送

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[template_card_event]]></Event>
<EventKey><![CDATA[key111]]></EventKey>
<TaskId><![CDATA[taskid111]]></TaskId>
<CardType><![CDATA[text_notice]]></CardType>
<ResponseCode><![CDATA[ResponseCode]]></ResponseCode>
<AgentID>1</AgentID>
<SelectedItems><SelectedItem><QuestionKey><![CDATA[QuestionKey1]]></QuestionKey><OpitonIds><OpitonId><![CDATA[OpitonId1]]></OpitonId><OpitonId><![CDATA[OpitonId2]]></OpitonId></OpitonIds></SelectedItem><SelectedItem><QuestionKey><![CDATA[QuestionKey2]]></QuestionKey><OpitonIds><OpitonId><![CDATA[OpitonId3]]></OpitonId><OpitonId><![CDATA[OpitonId4]]></OpitonId></OpitonIds></SelectedItem>
</SelectedItems>
</xml>
参数 说明
ToUserName 企业微信CorpID
FromUserName 成员UserID
CreateTime 消息创建时间(整型)
MsgType 消息类型,此时固定为:event
Event 事件类型:template_card_event,点击任务卡片按钮
EventKey 与发送任务卡片消息时指定的按钮btn:key值相同
TaskId 与发送任务卡片消息时指定的task_id相同
CardType 通用模板卡片的类型,类型有”text_notice”, “news_notice”, “button_interaction”, “vote_interaction”, “multiple_interaction”五种
ResponseCode 用于调用更新卡片接口的ResponseCode,24小时内有效,且只能使用一次
AgentID 企业应用的id,整型。可在应用的设置页面查看
QuestionKey 问题的key值
OpitonIds 对应问题的选项列表

根据腾讯官方的文档,我这次调用需要的就是模板卡板的按钮交互事件
那么格式如下

参数 是否必须 说明
touser 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向关注该企业应用的全部成员发送
toparty 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
totag 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
msgtype 消息类型,此时固定为:template_card
agentid 企业应用的id,整型。企业内部开发,可在应用的设置页面查看;第三方服务商,可通过接口 获取企业授权信息 获取该参数值
card_type 模板卡片类型,按钮交互型卡片填写”button_interaction”
source 卡片来源样式信息,不需要来源样式可不填写
source.icon_url 来源图片的url
source.desc 来源图片的描述,建议不超过20个字
main_title.title 一级标题,建议不超过36个字
main_title.desc 标题辅助信息,建议不超过44个字
sub_title_text 二级普通文本,建议不超过160个字
horizontal_content_list 二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
horizontal_content_list.type 链接类型,0或不填代表不是链接,1 代表跳转url,2 代表下载附件
horizontal_content_list.keyname 二级标题,建议不超过5个字
horizontal_content_list.value 二级文本,如果horizontal_content_list.type是2,该字段代表文件名称(要包含文件类型),建议不超过30个字
horizontal_content_list.url 链接跳转的url,horizontal_content_list.type是1时必填
horizontal_content_list.media_id 附件的media_id,horizontal_content_list.type是2时必填
card_action 整体卡片的点击跳转事件
card_action.type 跳转事件类型,0或不填代表不是链接,1 代表跳转url,2 代表打开小程序
card_action.url 跳转事件的url,card_action.type是1时必填
card_action.appid 跳转事件的小程序的appid,必须是与当前应用关联的小程序,card_action.type是2时必填
card_action.pagepath 跳转事件的小程序的pagepath,card_action.type是2时选填
task_id 任务id,同一个应用任务id不能重复,只能由数字、字母和“_-@”组成,最长128字节
button_list 按钮列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
button_list.text 按钮文案,建议不超过10个字
button_list.style 按钮样式,目前可填1~4,不填或错填默认1
button_list.key 按钮key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复

所以修改为以下代码作为测试展示信息

    /*** 企业微信回调审批* @return*/@ResponseBody@PostMapping(value = "/callbackCheck")public String callback(final HttpServletRequest request,@RequestParam(name = "msg_signature") final String sMsgSignature,@RequestParam(name = "timestamp") final String sTimestamp,@RequestParam(name = "nonce") final String sNonce) {try {String corpid = environment.getProperty("wx.corpid");InputStream inputStream = request.getInputStream();String sPostData = IOUtils.toString(inputStream, "UTF-8");WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey);//解密String sMsg = wxcpt.DecryptMsg(sMsgSignature, sTimestamp, sNonce, sPostData);//将post数据转换为mapMap<String, String> dataMap = MessageUtil.parseXml(sMsg);//企业内成员idString fromUserName = dataMap.get("FromUserName");// 事件需要 template_card_eventString event = dataMap.get("Event");// EventKey id需要对应上  button_key_1  button_key_2 目前设置两个按钮一个为通过 一个为不通过String eventKey = dataMap.get("EventKey");// TODO 在此提供扩展函数log.info("操作人ID:{} , 发起事件:{} , 触发按钮:{} ",fromUserName,event,eventKey);//            log.info(JSONObject.toJSONString(dataMap));//然后去操作你的业务逻辑} catch (Exception e) {e.printStackTrace();}return "success";}

发送消息模板代码

 /*** 推送交互按钮卡片模板* @param userId* @param visitorName* @param startTime* @param teacherName* @param appointId*/public void sendMessageNotify(String userId,String visitorName,String startTime,String teacherName,String appointId){String status = environment.getProperty("csadi.msg.status");WxTempLateBtnVo wxTempLateBtnVo = new WxTempLateBtnVo();wxTempLateBtnVo.setCard_type("button_interaction");WxTempLateBtnVo.SourceBean sourceBean = new WxTempLateBtnVo.SourceBean();//消息推送图片url 没有不填//        sourceBean.setIcon_url();//消息展示信息 在title条上的主题字段sourceBean.setDesc("审核通知");wxTempLateBtnVo.setSource(sourceBean);WxTempLateBtnVo.MainTitleBean mainTitleBean = new WxTempLateBtnVo.MainTitleBean();mainTitleBean.setTitle("待审核");//一级标题 不需要wxTempLateBtnVo.setMain_title(mainTitleBean);// 二级标题wxTempLateBtnVo.setSub_title_text("审核人: "+teacherName);// 整体跳转的行为 不需要wxTempLateBtnVo.setCard_action(null);String uuid = IdUtil.randomUUID();// 任务编号,随机生成wxTempLateBtnVo.setTask_id(uuid);LinkedList<WxTempLateBtnVo.HorizontalContentListBean> horizontalContentListBeans = new LinkedList<>();// 第一条信息  链接跳转的url,horizontal_content_list.type是1时必填 2为文件WxTempLateBtnVo.HorizontalContentListBean horizontalContentListBean = new WxTempLateBtnVo.HorizontalContentListBean();horizontalContentListBean.setKeyname("申请人");horizontalContentListBean.setValue(visitorName);horizontalContentListBeans.add(horizontalContentListBean);//第二条信息WxTempLateBtnVo.HorizontalContentListBean horizontalContentListBean1 = new WxTempLateBtnVo.HorizontalContentListBean();horizontalContentListBean1.setKeyname("申请时间");horizontalContentListBean1.setValue(startTime);horizontalContentListBeans.add(horizontalContentListBean1);//第三条信息WxTempLateBtnVo.HorizontalContentListBean horizontalContentListBean2 = new WxTempLateBtnVo.HorizontalContentListBean();horizontalContentListBean2.setType(1);horizontalContentListBean2.setKeyname("审核页面");horizontalContentListBean2.setValue("点击访问");horizontalContentListBean2.setUrl("http://fk.csadi.cn:6060/csadi-visitor-web/mgecheck.html?userId="+userId);horizontalContentListBeans.add(horizontalContentListBean2);wxTempLateBtnVo.setHorizontal_content_list(horizontalContentListBeans);//设置按钮LinkedList<WxTempLateBtnVo.ButtonListBean> buttonListBeans = new LinkedList<>();WxTempLateBtnVo.ButtonListBean buttonListBean = new WxTempLateBtnVo.ButtonListBean();buttonListBean.setText("审核通过");buttonListBean.setStyle(1);buttonListBean.setKey("button_key_1");buttonListBeans.add(buttonListBean);WxTempLateBtnVo.ButtonListBean buttonListBean1 = new WxTempLateBtnVo.ButtonListBean();buttonListBean1.setText("审核不通过");buttonListBean1.setStyle(3);buttonListBean1.setKey("button_key_2");buttonListBeans.add(buttonListBean1);wxTempLateBtnVo.setButton_list(buttonListBeans);if("1".equals(status)){wxTempLateBtnVo.setAppointId(appointId);//存储 模板按钮提供24小时访问时限,redis同样设置为24小时String rJson = JSONObject.toJSONString(wxTempLateBtnVo);System.out.printf("redisKey=%s \t\n",userId+uuid,rJson);//这里存着是为了回调用的redisTemplate.opsForValue().set(userId+uuid,rJson,24, TimeUnit.HOURS);sendNotifyBtn(userId,wxTempLateBtnVo);}}

WxSendTeacherVo是我封装的前端请求参数

public class WxSendTeacherVo {private String openId;private String visitorName;private String reason;private String date;private String phone;private String linkUrl;private String reviewDate;private String teacherName;public String getOpenId() {return openId;}public void setOpenId(String openId) {this.openId = openId;}public String getVisitorName() {return visitorName;}public void setVisitorName(String visitorName) {this.visitorName = visitorName;}public String getReason() {return reason;}public void setReason(String reason) {this.reason = reason;}public String getDate() {return date;}public void setDate(String date) {this.date = date;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public String getLinkUrl() {return linkUrl;}public void setLinkUrl(String linkUrl) {this.linkUrl = linkUrl;}public String getReviewDate() {return reviewDate;}public void setReviewDate(String reviewDate) {this.reviewDate = reviewDate;}public String getTeacherName() {return teacherName;}public void setTeacherName(String teacherName) {this.teacherName = teacherName;}
}

WxTempLateBtnVo是 消息事件模板按钮互动卡片的发送参数实体类

/*** @author fudon* @version 1.0* @date 2021-08-25 16:09*/public class WxTempLateBtnVo {/*** card_type : button_interaction* source : {"icon_url":"图片的url","desc":"企业微信"}* main_title : {"title":"欢迎使用企业微信","desc":"您的好友正在邀请您加入企业微信"}* sub_title_text : 下载企业微信还能抢红包!* horizontal_content_list : [{"keyname":"邀请人","value":"张三"},{"type":1,"keyname":"企业微信官网","value":"点击访问","url":"https://work.weixin.qq.com"},{"type":2,"keyname":"企业微信下载","value":"企业微信.apk","media_id":"文件的media_id"}]* card_action : {"type":2,"url":"https://work.weixin.qq.com","appid":"小程序的appid","pagepath":"/index.html"}* task_id : task_id* button_list : [{"text":"按钮1","style":1,"key":"button_key_1"},{"text":"按钮2","style":2,"key":"button_key_2"}]*/private String card_type;private SourceBean source;private MainTitleBean main_title;private String sub_title_text;private CardActionBean card_action;private String task_id;private List<HorizontalContentListBean> horizontal_content_list;private List<ButtonListBean> button_list;public static void main(String[] args) {WxTempLateBtnVo wxTempLateBtnVo = new WxTempLateBtnVo();wxTempLateBtnVo.setCard_type("");wxTempLateBtnVo.setSource(new SourceBean());wxTempLateBtnVo.setMain_title(new MainTitleBean());wxTempLateBtnVo.setSub_title_text("");wxTempLateBtnVo.setCard_action(new CardActionBean());wxTempLateBtnVo.setTask_id("");wxTempLateBtnVo.setHorizontal_content_list(Lists.newArrayList());wxTempLateBtnVo.setButton_list(Lists.newArrayList());String s = JSONObject.toJSONString(wxTempLateBtnVo);System.out.println(s );}public String getCard_type() {return card_type;}public void setCard_type(String card_type) {this.card_type = card_type;}public SourceBean getSource() {return source;}public void setSource(SourceBean source) {this.source = source;}public MainTitleBean getMain_title() {return main_title;}public void setMain_title(MainTitleBean main_title) {this.main_title = main_title;}public String getSub_title_text() {return sub_title_text;}public void setSub_title_text(String sub_title_text) {this.sub_title_text = sub_title_text;}public CardActionBean getCard_action() {return card_action;}public void setCard_action(CardActionBean card_action) {this.card_action = card_action;}public String getTask_id() {return task_id;}public void setTask_id(String task_id) {this.task_id = task_id;}public List<HorizontalContentListBean> getHorizontal_content_list() {return horizontal_content_list;}public void setHorizontal_content_list(List<HorizontalContentListBean> horizontal_content_list) {this.horizontal_content_list = horizontal_content_list;}public List<ButtonListBean> getButton_list() {return button_list;}public void setButton_list(List<ButtonListBean> button_list) {this.button_list = button_list;}public static class SourceBean {/*** icon_url : 图片的url* desc : 企业微信*/private String icon_url;private String desc;public String getIcon_url() {return icon_url;}public void setIcon_url(String icon_url) {this.icon_url = icon_url;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}}public static class MainTitleBean {/*** title : 欢迎使用企业微信* desc : 您的好友正在邀请您加入企业微信*/private String title;private String desc;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}}public static class CardActionBean {/*** type : 2* url : https://work.weixin.qq.com* appid : 小程序的appid* pagepath : /index.html*/private int type;private String url;private String appid;private String pagepath;public int getType() {return type;}public void setType(int type) {this.type = type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getAppid() {return appid;}public void setAppid(String appid) {this.appid = appid;}public String getPagepath() {return pagepath;}public void setPagepath(String pagepath) {this.pagepath = pagepath;}}public static class HorizontalContentListBean {/*** keyname : 邀请人* value : 张三* type : 1* url : https://work.weixin.qq.com* media_id : 文件的media_id*/private String keyname;private String value;private int type;private String url;private String media_id;public String getKeyname() {return keyname;}public void setKeyname(String keyname) {this.keyname = keyname;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public int getType() {return type;}public void setType(int type) {this.type = type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMedia_id() {return media_id;}public void setMedia_id(String media_id) {this.media_id = media_id;}}public static class ButtonListBean {/*** text : 按钮1* style : 1* key : button_key_1*/private String text;private int style;private String key;public String getText() {return text;}public void setText(String text) {this.text = text;}public int getStyle() {return style;}public void setStyle(int style) {this.style = style;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}}//按钮模板消息}

最终发送方法

    // 发送消息通知 带交互按钮public void sendNotifyBtn(String userId, WxTempLateBtnVo wxMessageVo){String token = queryAccessToken();HttpRequest post = HttpRequest.post(" https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="+token);Map<String,Object> map = new LinkedHashMap<>();map.put("touser",userId);//群组信息 不需要//        map.put("toparty",null);//标签信息 不需要//        map.put("totag",null);//enable_id_trans  enable_duplicate_check  duplicate_check_interval 均有默认值,不填map.put("msgtype","template_card");map.put("agentid",environment.getProperty("wx.agentId"));//设置模板信息map.put("template_card",wxMessageVo);String param = JSON.toJSONString(map);post.body(param);HttpResponse execute = post.execute();String body = execute.body();logger.info("企业微信消息通知入参:"+param);logger.info("企业微信消息通知返参:"+body);}

更新消息模板

按钮展示了有触发了,现在有个问题,处理完了原先的页面怎么搞,毕竟没有页面的改变事件,找了一下在消息推送的文档下面一栏还有个更新消息模板

参数说明:

参数 是否必须 说明
userids 企业的成员ID列表(最多支持1000个)
partyids 企业的部门ID列表(最多支持100个)
tagids 企业的标签ID列表(最多支持100个)
atall 更新整个任务接收人员
agentid 应用的agentid
response_code 更新卡片所需要消费的code,可通过发消息接口和回调接口返回值获取,一个code只能调用一次该接口,且只能在24小时内调用
card_type 模板卡片类型,按钮交互型卡片填写”button_interaction”
source 卡片来源样式信息,不需要来源样式可不填写
source.icon_url 来源图片的url
source.desc 来源图片的描述,建议不超过20个字
main_title.title 一级标题,建议不超过36个字
main_title.desc 标题辅助信息,建议不超过44个字
sub_title_text 二级普通文本,建议不超过160个字
horizontal_content_list 二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
horizontal_content_list.type 链接类型,0或不填代表不是链接,1 代表跳转url,2 代表下载附件
horizontal_content_list.keyname 二级标题,建议不超过5个字
horizontal_content_list.value 二级文本,如果horizontal_content_list.type是2,该字段代表文件名称(要包含文件类型),建议不超过30个字
horizontal_content_list.url 链接跳转的url,horizontal_content_list.type是1时必填
horizontal_content_list.media_id 附件的media_id,horizontal_content_list.type是2时必填
card_action 整体卡片的点击跳转事件
card_action.type 跳转事件类型,0或不填代表不是链接,1 代表跳转url,2 代表打开小程序
card_action.url 跳转事件的url,card_action.type是1时必填
card_action.appid 跳转事件的小程序的appid,card_action.type是2时必填
card_action.pagepath 跳转事件的小程序的pagepath,card_action.type是2时选填
button_list 按钮列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
button_list.text 按钮文案,建议不超过10个字
button_list.style 按钮样式,目前可填1~4,不填或错填默认1
button_list.key 按钮key值,用户点击后,会产生回调事件将本参数作为EventKey返回,最长支持1024字节,不可重复
replace_text 按钮替换文案,填写本字段后会展现灰色不可点击按钮
    /*** 更新交互模板* 该函数与sendNotifyBtn只有一处url不同* @param userId* @param wxMessageVo*/public void updateTemplateBtnMsg(String userId,String response_code, WxTempLateBtnVo wxMessageVo){String token = queryAccessToken();HttpRequest post = HttpRequest.post("https://qyapi.weixin.qq.com/cgi-bin/message/update_template_card?access_token="+token);Map<String,Object> map = new LinkedHashMap<>();ArrayList<String> list = new ArrayList<>();// 修改对象的userId,这里是传递的一个数组,可以做批量修改list.add(userId);map.put("userids",list);map.put("response_code",response_code);//群组信息 不需要//标签信息 不需要//enable_id_trans  enable_duplicate_check  duplicate_check_interval 均有默认值,不填
//        map.put("msgtype","template_card");map.put("agentid",environment.getProperty("wx.agentId"));//设置模板信息map.put("template_card",wxMessageVo);//设置第二个按钮为空 为了展示消息String param = JSON.toJSONString(map);post.body(param);HttpResponse execute = post.execute();String body = execute.body();logger.info("更新模板交互:"+param);logger.info("模板交互信息返回:"+body);}

这里为为了业务方便塞了几个id进去方便后续操作

queryAccessToken();是封装的拿企业微信操作token的方法,这个看官方文档吧,第一步应该就是

这个参数实体类进行了修改

import java.util.List;/*** @author fudon* @version 1.0* @date 2021-08-25 16:09*/public class WxTempLateBtnVo {/*** card_type : button_interaction* source : {"icon_url":"图片的url","desc":"企业微信"}* main_title : {"title":"欢迎使用企业微信","desc":"您的好友正在邀请您加入企业微信"}* sub_title_text : 下载企业微信还能抢红包!* horizontal_content_list : [{"keyname":"邀请人","value":"张三"},{"type":1,"keyname":"企业微信官网","value":"点击访问","url":"https://work.weixin.qq.com"},{"type":2,"keyname":"企业微信下载","value":"企业微信.apk","media_id":"文件的media_id"}]* card_action : {"type":2,"url":"https://work.weixin.qq.com","appid":"小程序的appid","pagepath":"/index.html"}* task_id : task_id* button_list : [{"text":"按钮1","style":1,"key":"button_key_1"},{"text":"按钮2","style":2,"key":"button_key_2"}]*/private String card_type;private SourceBean source;private MainTitleBean main_title;private String sub_title_text;private CardActionBean card_action;private  String appointId;public String getAppointId() {return appointId;}public void setAppointId(String appointId) {this.appointId = appointId;}public String getReplace_text() {return replace_text;}public void setReplace_text(String replace_text) {this.replace_text = replace_text;}private String task_id;private List<HorizontalContentListBean> horizontal_content_list;private List<ButtonListBean> button_list;private String replace_text;public static void main(String[] args) {WxTempLateBtnVo wxTempLateBtnVo = new WxTempLateBtnVo();wxTempLateBtnVo.setCard_type("");wxTempLateBtnVo.setSource(new SourceBean());wxTempLateBtnVo.setMain_title(new MainTitleBean());wxTempLateBtnVo.setSub_title_text("");wxTempLateBtnVo.setCard_action(new CardActionBean());wxTempLateBtnVo.setTask_id("");wxTempLateBtnVo.setHorizontal_content_list(Lists.newArrayList());wxTempLateBtnVo.setButton_list(Lists.newArrayList());String s = JSONObject.toJSONString(wxTempLateBtnVo);System.out.println(s);}public String getCard_type() {return card_type;}public void setCard_type(String card_type) {this.card_type = card_type;}public SourceBean getSource() {return source;}public void setSource(SourceBean source) {this.source = source;}public MainTitleBean getMain_title() {return main_title;}public void setMain_title(MainTitleBean main_title) {this.main_title = main_title;}public String getSub_title_text() {return sub_title_text;}public void setSub_title_text(String sub_title_text) {this.sub_title_text = sub_title_text;}public CardActionBean getCard_action() {return card_action;}public void setCard_action(CardActionBean card_action) {this.card_action = card_action;}public String getTask_id() {return task_id;}public void setTask_id(String task_id) {this.task_id = task_id;}public List<HorizontalContentListBean> getHorizontal_content_list() {return horizontal_content_list;}public void setHorizontal_content_list(List<HorizontalContentListBean> horizontal_content_list) {this.horizontal_content_list = horizontal_content_list;}public List<ButtonListBean> getButton_list() {return button_list;}public void setButton_list(List<ButtonListBean> button_list) {this.button_list = button_list;}public static class SourceBean {/*** icon_url : 图片的url* desc : 企业微信*/private String icon_url;private String desc;public String getIcon_url() {return icon_url;}public void setIcon_url(String icon_url) {this.icon_url = icon_url;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}}public static class MainTitleBean {/*** title : 欢迎使用企业微信* desc : 您的好友正在邀请您加入企业微信*/private String title;private String desc;public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}}public static class CardActionBean {/*** type : 2* url : https://work.weixin.qq.com* appid : 小程序的appid* pagepath : /index.html*/private int type;private String url;private String appid;private String pagepath;public int getType() {return type;}public void setType(int type) {this.type = type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getAppid() {return appid;}public void setAppid(String appid) {this.appid = appid;}public String getPagepath() {return pagepath;}public void setPagepath(String pagepath) {this.pagepath = pagepath;}}public static class HorizontalContentListBean {/*** keyname : 邀请人* value : 张三* type : 1* url : https://work.weixin.qq.com* media_id : 文件的media_id*/private String keyname;private String value;private int type;private String url;private String media_id;public String getKeyname() {return keyname;}public void setKeyname(String keyname) {this.keyname = keyname;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public int getType() {return type;}public void setType(int type) {this.type = type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMedia_id() {return media_id;}public void setMedia_id(String media_id) {this.media_id = media_id;}}public static class ButtonListBean {/*** text : 按钮1* style : 1* key : button_key_1*/private String text;private int style;private String key;public String getText() {return text;}public void setText(String text) {this.text = text;}public int getStyle() {return style;}public void setStyle(int style) {this.style = style;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}}//按钮模板消息}

只增加两个字段,公用一个实体,懒得再做新建了

不要问为什么不用lombok,这个是Json工具生成的实体类,加的比较麻烦

回调处理变更如下:
    /*** 企业微信回调审批** @return*/@ResponseBody@PostMapping(value = "/callbackCheck")public String callback(final HttpServletRequest request,@RequestParam(name = "msg_signature") final String sMsgSignature,@RequestParam(name = "timestamp") final String sTimestamp,@RequestParam(name = "nonce") final String sNonce) {try {String corpid = environment.getProperty("wx.corpid");InputStream inputStream = request.getInputStream();String sPostData = IOUtils.toString(inputStream, "UTF-8");WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAesKey, corpid);//解密String sMsg = wxcpt.DecryptMsg(sMsgSignature, sTimestamp, sNonce, sPostData);//将post数据转换为mapMap<String, String> dataMap = MessageUtil.parseXml(sMsg);//企业内成员idString fromUserName = dataMap.get("FromUserName");// 事件需要 template_card_eventString event = dataMap.get("Event");// 获取任务执行号 我将部分参数传递在对应json数据中String taskId = dataMap.get("TaskId");// EventKey id需要对应上  button_key_1  button_key_2 目前设置两个按钮一个为通过 一个为不通过String eventKey = dataMap.get("EventKey");// 过滤该事件if(StrUtil.compare("button_key_3",eventKey,true)!=0){return  "success";}String ResponseCode = dataMap.get("ResponseCode");log.info("操作人ID:{} , 发起事件:{} , 触发按钮:{} ", fromUserName, event, eventKey);// TODO: 2021-08-26String rJson = (String) redisTemplate.opsForValue().get(fromUserName + taskId);log.info("redisKey={}",fromUserName + taskId);//找不到对象也需要修改样式
/*            if (StrUtil.isBlank(rJson)) {log.error("找不到操作对象 UserId={}",fromUserName);return "success";}*/redisTemplate.delete(fromUserName + taskId);WxTempLateBtnVo wxTempLateBtnVo = JSONObject.parseObject(rJson, WxTempLateBtnVo.class);WxTempLateBtnVo.MainTitleBean mainTitleBean = new WxTempLateBtnVo.MainTitleBean();mainTitleBean.setTitle("已处理");wxTempLateBtnVo.setMain_title(mainTitleBean);//设置按钮LinkedList<WxTempLateBtnVo.ButtonListBean> buttonListBeans = new LinkedList<>();WxTempLateBtnVo.ButtonListBean buttonListBean = new WxTempLateBtnVo.ButtonListBean();// 设置为没有字仅仅是因为我没放按钮他报错了,所以设置为空buttonListBean.setText("");// 白色样式看起来融入一体了,加上上面为空的显示buttonListBean.setStyle(4);// 用于过滤请求的keyeventbuttonListBean.setKey("button_key_3");buttonListBeans.add(buttonListBean);//改为一个按钮wxTempLateBtnVo.setButton_list(buttonListBeans);
//            wxTempLateBtnVo.setButton_list(new LinkedList<>());//替换按钮为文字wxTempLateBtnVo.setReplace_text("已处理");//更新模板weixinUtils.updateTemplateBtnMsg(fromUserName,ResponseCode, wxTempLateBtnVo);String appointId = wxTempLateBtnVo.getAppointId();Appoint byId = appointService.getById(appointId);// 此处填写事件处理 以下都是业务代码,和实现无关switch (eventKey){// 审核通过case "button_key_1":byId.setStatus(2);teacherController.updateAppointStatus(byId);break;//审核不通过case "button_key_2":byId.setStatus(0);teacherController.updateAppointStatus(byId);break;default:break;}} catch (Exception e) {e.printStackTrace();}return "success";}


这里这个处理完成按钮不知道为什么截图出来是灰色的,但是在app上显示是白色的,可能是有色差吧

企业微信消息推送卡片按钮互动的使用相关推荐

  1. Node-Red 实践:企业微信消息推送

    一个偶然的机会,认识了node-red.这种拖拽控件编写代码的方式给了我很深刻的印象.能够通过简单的拖拽实现mqtt,http,websocket,tcp的服务,作为基于网络的业务流程demon非常方 ...

  2. Spring Boot 实现企业微信消息推送

    1 Maven依赖 <!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba</groupId><ar ...

  3. 企业微信消息推送接口大全

    该类存放接口所用到的企业微信的接口地址 package com.common;public final class QyapiUrl {/*** 请求nginx转发服务器地址*/public stat ...

  4. 【corpwechat-bot】一个好用的企业微信消息推送python接口库

    文章目录 前言 Requirements Result Features Usage 前言 本文同步发表在blog.gentlecp.com corpwechat-bot是一个python封装的企业机 ...

  5. (二)企业微信消息推送

    1.所需信息 CorpID:企业ID AgentID:应用ID Secret:应用密钥 2.功能实现 参考内容:企业微信-发送应用消息 public static class QYWXHelper{/ ...

  6. C# 企业微信消息推送对接,实现天气预报推送

    准备工作 需要获取的东西1. 企业Id,2.应用secret 和 应用ID 获取企业id 注册完成后,在我的企业=>企业信息=>最下面企业id 获取应用secret 和  应用ID 发送微 ...

  7. 微信接收不到企业微信消息推送

    使用微信提供的接口,给公司微信企业号的相关人员推送消息时. 一般是微信端的企业号和企业微信都能接收到推送的消息,但有一次企业微信版本更新后发现微信端的推送消息没有接收到. 原因找了很久,最终发现在企业 ...

  8. 【Java开发】Java实现企业微信消息推送,通过应用发送

    企业微信机器人发送消息 一.可能需要的依赖 二.必须的信息 三.效果展示 四.具体代码 一.可能需要的依赖 之前导依赖的时候没有特别标记,现在分不清哪个是哪个了,应该就在这些里面 <depend ...

  9. 企业微信 消息推送使用(新建应用、发送消息)

    1 新建应用 第一步,登录企业微信管理端. https://work.weixin.qq.com/nl/sem/registe?s=c&from=1014309098&bd_vid=7 ...

最新文章

  1. git---远程仓库版本回滚
  2. 找实习面经----天猫篇
  3. Report_报表中Ref Cursor数据源的概念和用法(案例)
  4. Logistic Regression 之基础知识准备
  5. Oracle12cR2的CDB与PDB简单管理操作
  6. 什么是runtime?
  7. python对象使用
  8. 动态获取某个元素的高度_codeforces 1443D,解法简单,思维缜密的动态规划问题...
  9. 我本人一直以来犯的错误,在看了 Think In Java 后才抓了出来
  10. 【欧洲已死】李开复:欧洲人工智能毫无希望
  11. 台积电已开始试生产3nm芯片 率先为苹果、英特尔供货
  12. linux 报错 bash ‘/bin/sh: Syntax error: “(” unexpected
  13. Linux中telnet命令
  14. SQLServer实现将VARCHAR字符型对象转化为int/float数值型对象后排序、对VARCHAR对象截取指定部分再转化为数值对象进行排序
  15. java中的内存回收机制所采用的算法_JavaGC垃圾回收机制和常见算法
  16. Python使用Reportlab处理PDF数据 - 其他图形
  17. 第7章 区块链开发平台:超级账本
  18. 建立软件工程之动态模型(状态图)步骤
  19. python医院自动化抢号脚本
  20. 云优化,集大成的可扩展平台是硬道理

热门文章

  1. Medicare Fraud Detection using Machine Learning
  2. n维椭球体积公式_2020中考物理知识汇总:公式大全
  3. oracle论坛 南派三叔,南派三叔 不疯魔不成活的金牌网络写手(6)
  4. 装机必备,四款良心软件释放你的电脑潜力,用了就离不开
  5. 上网本不会是一场流星雨
  6. 1号店两年即被资本俘获 创始人离开仅是时间问题
  7. win7 64位下利用u盘重装系统
  8. 每节课都是一个项目 手把手用STM32打造联网气象站-4-STM32基础三件套-TIM定时器和SYSTICK初始化
  9. 电脑系统(U盘安装) win7 win8 win10XP
  10. 考研复试—软件工程(一)