要实现企业微信中消息推送的功能,类似如下这种:
企业微信消息实体类
package com.ducetech.jeewx.api.wxsendmsg.model;
import java.io.Serializable;
/**
* @ClassName: WeChatMsg
* @Description: 企业微信消息类
* @author
* @date
*
*/
public class WeChatMsg implements Serializable {
private static final long serialVersionUID = 1L;
private String toUser; // 消息接收人
private String toParty; // 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
private String toTag; // 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数
private String msgType; // 消息类型
private String agentId; // 企业应用的id,整型。可在应用的设置页面查看
private String title; // 标题,不超过128个字节,超过会自动截断
private String description; // 描述,不超过512个字节,超过会自动截断
private String thumbMediaId; // 图文消息缩略图的media_id, 可以通过素材管理接口获得。此处thumb_media_id即上传接口返回的media_id
private String mediaId; // 文件id,可以调用上传临时素材接口获取
private String picUrl; // 图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图640320,小图8080。
private String btnTxt; // 按钮文字,仅在图文数为1条时才生效。 默认为“阅读全文”, 不超过4个文字,超过自动截断。该设置只在企业微信上生效,微工作台(原企业号)上不生效。
private String author; // 图文消息的作者,不超过64个字节
private String contentSourceUrl;//url(news) 点击后跳转的链接。
private String content; // 图文消息的内容,支持html标签,不超过666 K个字节
private String digest; // 图文消息的描述,不超过512个字节,超过会自动截断
private String safe; // 表示是否是保密消息,0表示否,1表示是,默认0
public String getToUser() {
return toUser;
}
public void setToUser(String toUser) {
this.toUser = toUser;
}
public String getToParty() {
return toParty;
}
public void setToParty(String toParty) {
this.toParty = toParty;
}
public String getToTag() {
return toTag;
}
public void setToTag(String toTag) {
this.toTag = toTag;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
public String getAgentId() {
return agentId;
}
public void setAgentId(String agentId) {
this.agentId = agentId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getThumbMediaId() {
return thumbMediaId;
}
public void setThumbMediaId(String thumbMediaId) {
this.thumbMediaId = thumbMediaId;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getContentSourceUrl() {
return contentSourceUrl;
}
public void setContentSourceUrl(String contentSourceUrl) {
this.contentSourceUrl = contentSourceUrl;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDigest() {
return digest;
}
public void setDigest(String digest) {
this.digest = digest;
}
public String getSafe() {
return safe;
}
public void setSafe(String safe) {
this.safe = safe;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPicUrl() {
return picUrl;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public String getBtnTxt() {
return btnTxt;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public void setBtnTxt(String btnTxt) {
this.btnTxt = btnTxt;
}
}
企业微信消息的方法
package com.ducetech.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ducetech.jeewx.api.core.common.MyX509TrustManager;
import com.ducetech.jeewx.api.wxsendmsg.model.WeChatMsg;
import com.ducetech.jeewx.constant.WxConstant;
import com.ducetech.redis.MyRedisTemplate;
@Component
public class WXUtils {
@Autowired
private MyRedisTemplate redisTemplateAutoWired;
private static MyRedisTemplate redisTemplate;
private static Logger logger = LoggerFactory.getLogger(WXUtils.class);
@PostConstruct
public void init() {
redisTemplate = redisTemplateAutoWired;
}
/**
* 获取企业微信API返回的JSONObject
* @return
* @throws IOException
*/
public static JSONObject getURLJSONObject(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
//打开连接
URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod.toUpperCase());
if ("GET".equalsIgnoreCase(requestMethod)){
httpUrlConn.connect();
}
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
logger.error("Weixin server connection timed out.");
} catch (Exception e) {
logger.error("https request error:{}", e);
}
return jsonObject;
}
/*public static JSONObject getURLJSONObject(String url) throws IOException {
URL u = new URL(url);
HttpsURLConnection huconn = (HttpsURLConnection) u.openConnection();
BufferedReader in = null;
StringBuilder result = new StringBuilder();
huconn.connect();
in = new BufferedReader(new InputStreamReader(huconn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result.append(line);
}
if (in != null) {
in.close();
}
JSONObject jsonObject = JSONObject.parseObject(result.toString());
return jsonObject;
}*/
/**
* 获取AccessToken
* @param request
* @param response
* @return
* @throws IOException
*/
public static String getAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
/*String wxAccessToken = (String) redisTemplate.getItem("wxAccessToken");
if (null != wxAccessToken) {
return wxAccessToken;
// response.getWriter().write(wxAccessToken);
} else {
String url = WxConstant.GET_ACCESS_TOKEN_URL;
JSONObject jsonObject = getURLJSONObject(url, "GET", null);
wxAccessToken = jsonObject.getString("access_token");
redisTemplate.setItem("examAccessToken", wxAccessToken);
redisTemplate.expire("examAccessToken", 7000);
return wxAccessToken;
// response.getWriter().write(wxAccessToken);
}*/
return getAccessToken();
}
/**
* 获取AccessToken
* @return
* @throws IOException
*/
public static String getAccessToken() throws IOException {
String wxAccessToken = (String) redisTemplate.getItem("examAccessToken");
if (null != wxAccessToken) {
return wxAccessToken;
// response.getWriter().write(wxAccessToken);
} else {
String url = WxConstant.GET_ACCESS_TOKEN_URL;
JSONObject jsonObject = getURLJSONObject(url, "GET", null);
wxAccessToken = jsonObject.getString("access_token");
redisTemplate.setItem("examAccessToken", wxAccessToken);
redisTemplate.expire("examAccessToken", 7000);
return wxAccessToken;
// response.getWriter().write(wxAccessToken);
}
}
/**
* 获取企业微信消息模板
* @param msg
* @return
*/
public static String getMsgTemplate(WeChatMsg msg) {
String msgType = msg.getMsgType();
if("mpnews".equalsIgnoreCase(msgType)) { // 图文消息(mpnews)
JSONObject msgObj = new JSONObject();
msgObj.put("touser", msg.getToUser());//"touser" : "UserID1|UserID2|UserID3"
msgObj.put("toparty", msg.getToParty());
msgObj.put("totag", msg.getToTag());
msgObj.put("msgtype", msgType);
msgObj.put("agentid", msg.getAgentId());//(String, Long)
JSONObject articles = new JSONObject();
articles.put("title", msg.getTitle());
articles.put("thumb_media_id",msg.getThumbMediaId());//TODO:需要调用素材管理的接口
articles.put("author", msg.getAuthor());
articles.put("content_source_url", msg.getContentSourceUrl());
articles.put("content", msg.getContent());
articles.put("digest", msg.getDigest());
msgObj.put("articles", JSON.toJSONString(articles));
msgObj.put("safe", msg.getSafe());
return JSON.toJSONString(msgObj);
}
if("news".equalsIgnoreCase(msgType)) { // 图文消息(news)
JSONObject msgObj = new JSONObject();
msgObj.put("touser", msg.getToUser());//"touser" : "UserID1|UserID2|UserID3"
msgObj.put("toparty", msg.getToParty());
msgObj.put("totag", msg.getToTag());
msgObj.put("msgtype", msgType);
msgObj.put("agentid", msg.getAgentId());//(String, Long)
Map<String, List<JSONObject>> articles = new HashMap<>();
List<JSONObject> articleList = new ArrayList<>();
JSONObject article = new JSONObject();
article.put("title", msg.getTitle());
article.put("description",msg.getDescription());
article.put("url", msg.getContentSourceUrl());
article.put("picurl", msg.getPicUrl());
article.put("btntxt", msg.getBtnTxt());
articleList.add(article);
/*JSONObject article1 = new JSONObject();
article1.put("title", msg.getTitle());
article1.put("description",msg.getDescription());
article1.put("url", msg.getContentSourceUrl());
article1.put("picurl", msg.getPicUrl());
article1.put("btntxt", msg.getBtnTxt());
articleList.add(article1);*/
articles.put("articles", articleList);
msgObj.put("news", articles);
return JSON.toJSONString(msgObj);
}
if("textcard".equalsIgnoreCase(msgType)) { // 文本卡片消息(textcard)
JSONObject msgObj = new JSONObject();
msgObj.put("touser", msg.getToUser());//"touser" : "UserID1|UserID2|UserID3"
msgObj.put("toparty", msg.getToParty());
msgObj.put("totag", msg.getToTag());
msgObj.put("msgtype", msgType);
msgObj.put("agentid", msg.getAgentId());//(String, Long)
JSONObject textcard = new JSONObject();
textcard.put("title", msg.getTitle());
textcard.put("description",msg.getDescription());
textcard.put("url", msg.getContentSourceUrl());
textcard.put("btntxt", msg.getBtnTxt());
msgObj.put("textcard", textcard);
return JSON.toJSONString(msgObj);
}if("file".equalsIgnoreCase(msgType)) { // 文件消息(file)
JSONObject msgObj = new JSONObject();
msgObj.put("touser", msg.getToUser());//"touser" : "UserID1|UserID2|UserID3"
msgObj.put("toparty", msg.getToParty());
msgObj.put("totag", msg.getToTag());
msgObj.put("msgtype", msgType);
msgObj.put("agentid", msg.getAgentId());//(String, Long)
JSONObject file = new JSONObject();
file.put("media_id", msg.getMediaId());
msgObj.put("file", file);
msgObj.put("safe", msg.getSafe());
return JSON.toJSONString(msgObj);
}
if("text".equalsIgnoreCase(msgType)) { // 文本消息(text)
JSONObject msgObj = new JSONObject();
msgObj.put("touser", msg.getToUser());//"touser" : "UserID1|UserID2|UserID3"
msgObj.put("totag", msg.getToTag());
msgObj.put("msgtype", msgType);
msgObj.put("agentid", msg.getAgentId());//(String, Long)
JSONObject text = new JSONObject();
text.put("content", msg.getContent());
msgObj.put("text", text);
return JSON.toJSONString(msgObj);
}
return "";
}
public static int sendMpNews(WeChatMsg msg, HttpServletRequest request, HttpServletResponse response) throws IOException {
// https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
/*int result = 0;
String msgTemplate = WXUtils.getMsgTemplate(msg);
String accessToken = WXUtils.getAccessToken(request, response);
String sendMpNewsUrl = WxConstant.POST_MSG + accessToken;
JSONObject mpNews = WXUtils.getURLJSONObject(sendMpNewsUrl, "POST", msgTemplate);
if (null != mpNews) {
result = mpNews.getIntValue("errcode");
}*/
return sendMpNews(msg);
}
public static int sendMpNews(WeChatMsg msg) throws IOException {
// https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN
int result = 0;
String msgTemplate = WXUtils.getMsgTemplate(msg);
String accessToken = WXUtils.getAccessToken();
String sendMpNewsUrl = WxConstant.POST_MSG + accessToken;
JSONObject mpNews = WXUtils.getURLJSONObject(sendMpNewsUrl, "POST", msgTemplate);
if (null != mpNews) {
result = mpNews.getIntValue("errcode");
}
return result;
}
}
用到的常量
//获取AccessToken的url
public static final String GET_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpID + "&corpsecret=" + corpSecret;
//发送应用消息
public static final String POST_MSG = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=";
//发送消息
public static final String MSG_URL = "http://********.com:8883/examApp";//合法域名
发送消息通知
try {
WeChatMsg msg = new WeChatMsg();
msg.setAgentId(WxConstant.agentId); //企业应用的id
msg.setMsgType("textcard"); //消息类型 文本
msg.setToUser(wxIds); //消息接收人
msg.setTitle("线上评估"); //标题
msg.setDescription("您有一条新的评估测试待完成,结束时间为:"+ DateUtil.formatDate(questionBank.getEndDate(),0,10)); //描述
msg.setContentSourceUrl(WxConstant.MSG_URL+"/questions?levelId = "+questionBank.getLevelId()+"&classifyId = "+questionBank.getClassifyId()); //url(news) 点击后跳转的链接
msg.setBtnTxt("查看详情");
WXUtils.sendMpNews(msg);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
以上,搞定了