企业微信推送工具
一. 背景
将外部事件消息发送至企业微信,所在成员可以根据消息进行事件处理。
二. 计划流程
管理员在企业微信中自建小程序,将小程序的 ID 和微信的 access_token 作为接入连接的凭证,实现外部消息内容与企业微信自建应用聊天框的对接,最终将外部事件消息通过应用发送给企业微信所在成员。
三. 实现流程
1. 在项目 pom 文件引入依赖如下
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
</dependencies>
2. 创建常量声明类 WeChatConstantUtil,设定重要参数
/**
* 企业微信推送常量声明
* @author hzh
*/
public interface WeChatConstantUtil {
/** 发送消息的类型 */
public final static String MSGTYPE = "text";
/** 将消息发送给所有成员 */
public final static String TOPARTY = "@all";
/** 企业应用Id */
public final static String AGENTID = "1000002";
/** 获取企业微信的企业号,根据不同企业更改 */
public final static String CORPID = "ww1b37f06c59f6a7b4";
/** 获取企业应用的密钥,根据不同应用更改 */
public final static String CORPSECRET = "EiXSk_uysP5SJVF1KD9QcUfJRG-R04l86cIDSVRJC3s";
/** 获取访问权限码URL */
public final static String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
/** 获取用户ID */
public final static String GET_USER_ID = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserid?access_token=";
/** 创建会话请求URL */
public final static String CREATE_SESSION_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=";
}
3. 创建接口凭证 WeChatAccessToken 类对象,其中包括 ACCESS_TOKEN 码和有效时间(主要用于微信接口凭证)
/**
* 微信通用接口凭证
* @author hzh
*
*/
public class WeChatAccessToken {
private String accessToken; // 获取到的access_token字符串(凭证)
private int validTime; // 凭证有效时间(2h,7200s)
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getValidTime() {
return validTime;
}
public void setValidTime(int validTime) {
this.validTime = validTime;
}
}
4. 创建 WeChatMessage 类对象,工具重要类(token 获取、访问微信服务器、消息发送),其中使用 http 中的 post 协议
package com.epichust.wechat.web;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.epichust.mestar.utils.exception.MestarException;
import com.epichust.mestar.utils.lang.StringUtils;
import com.epichust.wechat.unimax.IWeChatSendExecute;
import com.epichust.wechat.unimax.WeChatMessage;
import com.epichust.wechat.utils.WeChatAccessToken;
import com.epichust.wechat.utils.WeChatConstantUtils;
/**
* 企业微信推送工具
*
* @author hzh
*/
@Component("weChatSendExecute")
public class WeChatSendExecute implements IWeChatSendExecute{
/**
* 企业接口向用户发送给微信消息
*
* @param toUser
* 成员ID列表
* @param toPhone
* 手机号列表
* @param toParty
* 部门ID列表
* @param toTag
* 标签ID列表
* @param content
* 消息内容
* @param safe
* 是否保密
*
* @return
*/
public String sendWeChatMessage(WeChatMessage weChatMessage) {
// 从对象中提取凭证
WeChatAccessToken accessToken = getAccessToken();
// 获取access_token字符串
String ACCESS_TOKEN = accessToken.getAccessToken();
// 请求串
String url = WeChatConstantUtils.CREATE_SESSION_URL + ACCESS_TOKEN;
String users = "";
//touser、toparty、totag不能同时为空
if (StringUtils.isNotBlank(weChatMessage.getToPhone())) {
// 通过手机号获取账号ID
String users = getUserId(accessToken, weChatMessage.getToPhone());
weChatMessage.setToUser(users);
}
// 获取消息
String json = getSendMessage(weChatMessage);
//获取执行结果
String result = execute(url, json);
return result;
}
/**
* 获取access_token
*
* @return
*/
public static WeChatAccessToken getAccessToken() {
WeChatAccessToken token = new WeChatAccessToken();
// 访问微信服务器
String url = WeChatConstantUtils.ACCESS_TOKEN_URL + "?corpid=" + WeChatConstantUtils.CORPID + "&corpsecret="
+ WeChatConstantUtils.CORPSECRET;
try {
URL getUrl = new URL(url);
// 开启连接,并返回一个URLConnection对象
HttpURLConnection http = (HttpURLConnection) getUrl.openConnection();
http.setRequestMethod("GET");
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
// 将URL连接用于输入和输出,一般输入默认为true,输出默认为false
http.setDoOutput(true);
http.setDoInput(true);
// 进行连接,不返回对象
http.connect();
// 获得输入内容,并将其存储在缓存区
InputStream inputStream = http.getInputStream();
int size = inputStream.available();
byte[] buffer = new byte[size];
inputStream.read(buffer);
// 将内容转化为JSON代码
String message = new String(buffer, "UTF-8");
JSONObject json = JSONObject.parseObject(message);
// 提取内容,放入对象
token.setAccessToken(json.getString("access_token"));
token.setValidTime(new Integer(json.getString("expires_in")));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 返回access_token码
return token;
}
/**
* 封装发送消息请求JSON
*
* @return
*/
public String getSendMessage(WeChatMessage weChatMessage) {
// 封装发送消息请求JSON
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("{");
stringBuffer.append("\"touser\":" + "\"" + weChatMessage.getToUser() + "\",");
stringBuffer.append("\"toparty\":" + "\"" + weChatMessage.getToParty() + "\",");
stringBuffer.append("\"totag\":" + "\"" + weChatMessage.getToTag() + "\",");
stringBuffer.append("\"msgtype\":" + "\"" + WeChatConstantUtils.MSGTYPE + "\",");
stringBuffer.append("\"text\":" + "{");
stringBuffer.append("\"content\":" + "\"" + weChatMessage.getContent() + "\"");
stringBuffer.append("}");
stringBuffer.append(",\"safe\":" + "\"" + weChatMessage.getSafe() + "\",");
stringBuffer.append("\"agentid\":" + "\"" + WeChatConstantUtils.AGENTID + "\",");
stringBuffer.append("\"debug\":" + "\"" + "1" + "\"");
stringBuffer.append("}");
return stringBuffer.toString();
}
/**
* 根据电话号码得到userId
*
* @param token
* @param employeePhone
* @return
*/
public String getUserId(String token, String employeePhone) {
String json = getPhoneUrl(employeePhone);
String url = WeChatConstantUtils.GET_USER_ID + token;
//返回执行结果
String result = execute(url, json);
JSONObject jsonObject = JSONObject.parseObject(result);
return jsonObject.getString("userid");
}
/**
* io处理流
* @param url
* @param json
* @return
*/
public String execute(String url, String json) {
// 返回结果
String result = "";
try {
// 写入内容
HttpURLConnection http = getHttp(url);
OutputStream outputStream = http.getOutputStream();
outputStream.write(json.getBytes("UTF-8"));
InputStream inputStream = http.getInputStream();
int size = inputStream.available();
byte[] jsonBytes = new byte[size];
inputStream.read(jsonBytes);
result = new String(jsonBytes, "UTF-8");
// 清空输出流
outputStream.flush();
// 关闭输出通道
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 获取拼接手机号消息JSON
*
* @return
*/
public String getPhoneUrl(String employeePhone) {
StringBuffer userURL = new StringBuffer();
userURL.append("{");
userURL.append("\"mobile\":" + "\"" + employeePhone + "\",");
userURL.append("}");
return userURL.toString();
}
/**
* 访问微信服务器
*
* @param action
* @return
* @throws Exception
*/
public HttpsURLConnection getHttp(String action) throws Exception {
URL url = null;
HttpsURLConnection http = null;
try {
url = new URL(action);
// 开启连接,并返回一个URLConnection对象
http = (HttpsURLConnection) url.openConnection();
http.setRequestMethod("POST");
http.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
// 将URL连接用于输入和输出,一般输入默认为true,输出默认为false
http.setDoOutput(true);
http.setDoInput(true);
// 连接超时30秒
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");
// 读取超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000");
// 进行连接,不返回对象
http.connect();
} catch (Exception e) {
e.printStackTrace();
}
return http;
}
}
5. 创建 IWeChatSendExecute 接口提供调用
package com.epichust.wechat.web;
/**
* 企业微信推送外部接口
* @author hzh
*
*/
public interface IWeChatSendExecute {
/**
* 企业接口向用户发送给微信消息(目前仅限于发送消息)
* /
public String sendWeChatMessage(WeChatMessage weChatMessage);
}
6. 创建 WeChatMessage 推送消息类
package com.epichust.wechat.unimax;
/**
* 企业微信推送消息类
*
* @author hzh
*
*/
public class WeChatMessage {
private String toUser; // 成员ID列表 (指定接收消息的成员,成员ID列表(多个接收者用‘|’分隔,最多支持1000个)
private String toPhone; // 手机号列表 (在获取不到成员ID的情况下,可以通过手机号获取发送)
private String toParty; // 部门ID列表 (指定接收消息的部门,部门ID列表,多个接收者用‘|’分隔,最多支持100个)
private String toTag; // 标签ID列表 (指定接收消息的标签,标签ID列表,多个接收者用‘|’分隔,最多支持100个)
private String content; // 消息内容 (消息内容,最长不超过2048个字节,超过将截断)
private int safe = 0; // 是否保密 (表示是否是保密消息,0表示可对外分享,1表示不能分享且内容显示水印,默认为0)
public String getToUser() {
return toUser;
}
public void setToUser(String toUser) {
this.toUser = toUser;
}
public String getToPhone() {
return toPhone;
}
public void setToPhone(String toPhone) {
this.toPhone = toPhone;
}
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 getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getSafe() {
return safe;
}
public void setSafe(int safe) {
this.safe = safe;
}
}
7. 在实际场景中可调用
@Autowired
public IWeChatSendExecute iWeChatSendExecute;
//接口(消息类)
//可分两种情况 1.只传输成员ID 2.只传出手机号
//工具会通过成员ID发送消息 or 根据手机号查询出成员ID发送消息
// 判断规则集中企业微信推送功能是否开启
if (ruleImpl.getParamValBoolean("USM_WECHAT")) {
WeChatMessage weChatMessage = new WeChatMessage();
weChatMessage.setToUser("test");
weChatMessage.setToPhone("18888888888");
weChatMessage.setToParty("1");
weChatMessage.setToTag("MES");
weChatMessage.setContent("您已在MES中签到成功!");
String messageTO = iWeChatSendExecute.sendWeChatMessage(weChatMessage);
}
8. 实际效果图如下