企业微信推送工具

一. 背景

将外部事件消息发送至企业微信,所在成员可以根据消息进行事件处理。

二. 计划流程

管理员在企业微信中自建小程序,将小程序的 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. 实际效果图如下

QQ截图20220706203007.png