转载 https://www.cnblogs.com/snail90/p/10045414.html
Java发送企业微信应用消息
1.发送消息与被动回复消息
(1)流程不同:发送消息是第三方服务器主动通知微信服务器向用户发消息。而被动回复消息是 用户发送消息之后,微信服务器将消息传递给 第三方服务器,第三方服务器接收到消息后,再对消息做出相应的回复消息。
(2)消息是否加密:在发送消息的流程中,对封装好的回复消息(json字符串)是不进行AES加密的。
而在被动回复消息的流程中,第三方服务器接收消息时,需要先解密微信发过来的消息,在最后发送回复消息前,需要先加密(AES)回复消息。
(3)数据交换的格式不同:在发送消息的流程中,第三方服务器将消息(json字符串格式)发送给微信服务器
而在被动回复消息的过程中,第三方服务器接收的消息和被动回复的消息都是以xml字符串格式的。
二、代码实现
1.实体类
1.1 消息基类(企业号 -> 普通用户) ——BaseMessage
复制代码 1 2 /** 3 * 消息基类(企业号 -> 普通用户) 4 * @author hh 5 * 6 */ 7 public class BaseMessage { 8 // 否 成员ID列表(消息接收者,多个接收者用‘|’分隔,最多支持1000个)。特殊情况:指定为@all,则向该企业应用的全部成员发送 9 private String touser; 10 // 否 部门ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数 11 private String toparty; 12 // 否 标签ID列表,多个接收者用‘|’分隔,最多支持100个。当touser为@all时忽略本参数 13 private String totag; 14 // 是 消息类型 15 private String msgtype; 16 // 是 企业应用的id,整型。可在应用的设置页面查看 17 private int agentid; 18 19 20 public String getTouser() { 21 return touser; 22 } 23 public void setTouser(String touser) { 24 this.touser = touser; 25 } 26 public String getToparty() { 27 return toparty; 28 } 29 public void setToparty(String toparty) { 30 this.toparty = toparty; 31 } 32 public String getTotag() { 33 return totag; 34 } 35 public void setTotag(String totag) { 36 this.totag = totag; 37 } 38 public String getMsgtype() { 39 return msgtype; 40 } 41 public void setMsgtype(String msgtype) { 42 this.msgtype = msgtype; 43 } 44 public int getAgentid() { 45 return agentid; 46 } 47 public void setAgentid(int agentid) { 48 this.agentid = agentid; 49 } 50 } 复制代码
1.2 文本消息——Text、TextMessage
企业微信官方文档中关于文本消息请求包的说明
复制代码 1 { 2 "touser" : "UserID1|UserID2|UserID3", 3 "toparty" : " PartyID1|PartyID2 ", 4 "totag" : " TagID1 | TagID2 ", 5 "msgtype" : "text", 6 "agentid" : 1, 7 "text" : { 8 "content" : "你的快递已到,请携带工卡前往邮件中心领取。 出发前可查看<a href="http://work.weixin.qq.com">邮件中心视频实况</a>,聪明避开排队。" 9 }, 10 "safe":0 11 } 复制代码
可把整个json对象看做一个java对象,而在这个json对象中又包含一个text对象。(json中的对象用{ }包裹起来,json中的数组用[ ] 包裹起来)
需注意agentid、safe为int型。于是可以把text看做一个java对象,这样TextMessage类组合了Text类,转json字符串的时候,就可以直接使用 String jsonTextMessage=gson.toJson(textMessage).
于是,我们开始对文本消息进行封装
Text.java
1 /** 2 * 文本 3 * @author hh 4 * 5 */ 6 public class Text { 7 //是 消息内容,最长不超过2048个字节 8 private String content; 9 10 public String getContent() { 11 return content; 12 } 13 14 public void setContent(String content) { 15 this.content = content; 16 } 17 }
TextMessage.java
1 /** 2 * 文本消息 3 * @author hh 4 * 5 */ 6 public class TextMessage extends BaseMessage { 7 //文本 8 private Text text; 9 //否 表示是否是保密消息,0表示否,1表示是,默认0 10 private int safe; 11 12 public Text getText() { 13 return text; 14 } 15 public void setText(Text text) { 16 this.text = text; 17 } 18 public int getSafe() { 19 return safe; 20 } 21 public void setSafe(int safe) { 22 this.safe = safe; 23 } 24 }
1.3 图片类、语音类、文件类——Media
通过对微信官方文档的仔细阅读,可以看到图片消息、语音消息、文件消息中的的json对象都内含同一个Jason对象(media_id),于是我们根据这个对象封装Media.java
复制代码 1 /** 2 * 图片、语音、文件 3 * @author hh 4 * 5 */ 6 public class Media { 7 //是 图片/语音/文件 媒体文件id,可以调用上传临时素材接口获取 8 private String media_id; 9 10 public String getMedia_id() { 11 return media_id; 12 } 13 14 public void setMedia_id(String media_id) { 15 this.media_id = media_id; 16 } 17 }
1.3.1 图片消息——ImgMessage
/** * 图片消息 * @author hh * */ public class ImgMessage extends BaseMessage { //图片 private Media image ; //否 表示是否是保密消息,0表示否,1表示是,默认0 private int safe; public Media getImage() { return image; } public void setImage(Media image) { this.image = image; } public int getSafe() { return safe; } public void setSafe(int safe) { this.safe = safe; } }
1.3.2 语音消息——VoiceMessage
/** * 语音消息 * @author hh * */ public class VoiceMessage extends BaseMessage { //语音 private Media voice ; //否 表示是否是保密消息,0表示否,1表示是,默认0 private int safe; public Media getVoice() { return voice; } public void setVoice(Media voice) { this.voice = voice; } public int getSafe() { return safe; } public void setSafe(int safe) { this.safe = safe; } }
1.3.3 文件消息——FileMessage
/** * 文件消息 * @author hh * */ public class FileMessage extends BaseMessage { //文件 private Media file ; //否 表示是否是保密消息,0表示否,1表示是,默认0 private int safe; public Media getFile() { return file; } public void setFile(Media file) { this.file = file; } public int getSafe() { return safe; } public void setSafe(int safe) { this.safe = safe; } }
1.4 视频消息——Video、VideoMessage
Video.java
/** * 视频 * @author hh * */ public class Video { //是 视频媒体文件id,可以调用上传临时素材接口获取 private String media_id; //否 视频消息的标题,不超过128个字节,超过会自动截断 private String title; //否 视频消息的描述,不超过512个字节,超过会自动截断 private String description; public String getMedia_id() { return media_id; } public void setMedia_id(String media_id) { this.media_id = media_id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
VideoMessage.java
/** * 视频消息 * @author hh * */ public class VideoMessage extends BaseMessage { //视频 private Video video ; //否 表示是否是保密消息,0表示否,1表示是,默认0 private int safe; public Video getVideo() { return video; } public void setVideo(Video video) { this.video = video; } public int getSafe() { return safe; } public void setSafe(int safe) { this.safe = safe; } }
1.5 文本卡片消息——Textcard、TextcardMessage
/** * 文本卡片 * @author hh * */ public class Textcard { //是 标题,不超过128个字节,超过会自动截断 private String title; //是 描述,不超过512个字节,超过会自动截断 private String description; //是 点击后跳转的链接。 private String url; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
TextcardMessage.java
/** * 文本卡片消息 * @author hh * */ public class TextcardMessage extends BaseMessage { //文本 private Textcard textcard; //btntxt 否 按钮文字。 默认为“详情”, 不超过4个文字,超过自动截断。 public Textcard getTextcard() { return textcard; } public void setTextcard(Textcard textcard) { this.textcard = textcard; } }
1.6 图文消息——Article、News、NewsMessage
企业微信官方文档中关于图文消息请求包的说明:
{ "touser" : "UserID1|UserID2|UserID3", "toparty" : " PartyID1 | PartyID2 ", "totag" : " TagID1 | TagID2 ", "msgtype" : "news", "agentid" : 1, "news" : { "articles" : [ { "title" : "中秋节礼品领取", "description" : "今年中秋节公司有豪礼相送", "url" : "URL", "picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png" } ] } }
可以看到NewsMessage类组合了News类,News类组合了List<Aticle> articles(即Article数组),于是得到以下实体类。
Article.java
/** * 文章 * @author hh * */ public class Article { //是 标题,不超过128个字节,超过会自动截断 private String title; //否 描述,不超过512个字节,超过会自动截断 private String description; //是 点击后跳转的链接。 private String url; //否 图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图640320,小图8080。 private String picurl; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getPicurl() { return picurl; } public void setPicurl(String picurl) { this.picurl = picurl; } }
News.java
import java.util.List; /** * 图文 * @author hh * */ public class News { //文章列表 private List<Article> articles; public List<Article> getArticles() { return articles; } public void setArticles(List<Article> articles) { this.articles = articles; } }
NewsMessage.java
/** * 图文消息 * @author hh * */ public class NewsMessage extends BaseMessage { //图文 private News news; public News getNews() { return news; } public void setNews(News news) { this.news = news; } }
2.发送消息业务类——SendMessageService
package com.ray.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sf.json.JSONObject; import com.google.gson.Gson; import com.ray.pojo.message.send.BaseMessage; import com.ray.test.UserTest; import com.ray.util.WeiXinUtil; /**@desc : 发送消息 * * @author: shirayner * @date : 2017-8-18 上午10:06:23 */ public class SendMessageService { private static Logger log = LoggerFactory.getLogger(UserTest.class); private static String sendMessage_url="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN"; /** * @desc :0.公共方法:发送消息 * * @param accessToken * @param message void */ public void sendMessage(String accessToken,BaseMessage message){ //1.获取json字符串:将message对象转换为json字符串 Gson gson = new Gson(); String jsonMessage =gson.toJson(message); //使用gson.toJson(user)即可将user对象顺序转成json System.out.println("jsonTextMessage:"+jsonMessage); //2.获取请求的url sendMessage_url=sendMessage_url.replace("ACCESS_TOKEN", accessToken); //3.调用接口,发送消息 JSONObject jsonObject = WeiXinUtil.httpRequest(sendMessage_url, "POST", jsonMessage); System.out.println("jsonObject:"+jsonObject.toString()); //4.错误消息处理 if (null != jsonObject) { if (0 != jsonObject.getInt("errcode")) { log.error("创建成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } } }
3.工具类
MyX509TrustManager.java
import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /** * 证书信任管理器(用于https请求) * * @author hh * @date 2016-08-08 */ public class MyX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }
AccessToken.java
public class AccessToken { // 获取到的凭证 private String token; // 凭证有效时间,单位:秒 private int expiresIn; public String getToken() { return token; } public void setToken(String token) { this.token = token; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } }
WeiXinUtil.java
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Formatter; import java.util.HashMap; import java.util.Map; import java.util.UUID; 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 net.sf.json.JSONException; import net.sf.json.JSONObject; public class WeiXinUtil { //rivate static Logger log = LoggerFactory.getLogger(WeiXinUtil.class); //微信的请求url //获取access_token的接口地址(GET) 限200(次/天) public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}"; //获取jsapi_ticket的接口地址(GET) 限200(次/天) public final static String jsapi_ticket_url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESSTOKEN"; /** * 1.发起https请求并获取结果 * * @param requestUrl 请求地址 * @param requestMethod 请求方式(GET、POST) * @param outputStr 提交的数据 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) */ public static JSONObject httpRequest(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); 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.fromObject(buffer.toString()); } catch (ConnectException ce) { ce.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return jsonObject; } /** * 2.发送https请求之获取临时素材 * @param requestUrl * @param savePath 文件的保存路径,此时还缺一个扩展名 * @return * @throws Exception */ /*public static File getFile(String requestUrl,String savePath) throws Exception { //String path=System.getProperty("user.dir")+"/img//1.png"; // 创建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("GET"); httpUrlConn.connect(); //获取文件扩展名 String ext=getExt(httpUrlConn.getContentType()); savePath=savePath+ext; System.out.println("savePath"+savePath); //下载文件到f文件 File file = new File(savePath); // 获取微信返回的输入流 InputStream in = httpUrlConn.getInputStream(); //输出流,将微信返回的输入流内容写到文件中 FileOutputStream out = new FileOutputStream(file); int length=100*1024; byte[] byteBuffer = new byte[length]; //存储文件内容 int byteread =0; int bytesum=0; while (( byteread=in.read(byteBuffer)) != -1) { bytesum += byteread; //字节数 文件大小 out.write(byteBuffer,0,byteread); } System.out.println("bytesum: "+bytesum); in.close(); // 释放资源 out.close(); in = null; out=null; httpUrlConn.disconnect(); return file; } */ /** * @desc :2.微信上传素材的请求方法 * * @param requestUrl 微信上传临时素材的接口url * @param file 要上传的文件 * @return String 上传成功后,微信服务器返回的消息 */ public static String httpRequest(String requestUrl, File file) { StringBuffer buffer = new StringBuffer(); try{ //1.建立连接 URL url = new URL(requestUrl); HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); //打开链接 //1.1输入输出设置 httpUrlConn.setDoInput(true); httpUrlConn.setDoOutput(true); httpUrlConn.setUseCaches(false); // post方式不能使用缓存 //1.2设置请求头信息 httpUrlConn.setRequestProperty("Connection", "Keep-Alive"); httpUrlConn.setRequestProperty("Charset", "UTF-8"); //1.3设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY); // 请求正文信息 // 第一部分: //2.将文件头输出到微信服务器 StringBuilder sb = new StringBuilder(); sb.append("--"); // 必须多两道线 sb.append(BOUNDARY); sb.append(" "); sb.append("Content-Disposition: form-data;name="media";filelength="" + file.length() + "";filename=""+ file.getName() + "" "); sb.append("Content-Type:application/octet-stream "); byte[] head = sb.toString().getBytes("utf-8"); // 获得输出流 OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream()); // 将表头写入输出流中:输出表头 outputStream.write(head); //3.将文件正文部分输出到微信服务器 // 把文件以流文件的方式 写入到微信服务器中 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { outputStream.write(bufferOut, 0, bytes); } in.close(); //4.将结尾部分输出到微信服务器 byte[] foot = (" --" + BOUNDARY + "-- ").getBytes("utf-8");// 定义最后数据分隔线 outputStream.write(foot); outputStream.flush(); outputStream.close(); //5.将微信服务器返回的输入流转换成字符串 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(); } catch (IOException e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } return buffer.toString(); } /** * 2.发起http请求获取返回结果 * * @param requestUrl 请求地址 * @return */ public static String httpRequest(String requestUrl) { StringBuffer buffer = new StringBuffer(); try { URL url = new URL(requestUrl); HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); httpUrlConn.setDoOutput(false); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); httpUrlConn.setRequestMethod("GET"); httpUrlConn.connect(); // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); //InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 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(); } catch (Exception e) { } return buffer.toString(); } /** * 3.获取access_token * * @param appid 凭证 * @param appsecret 密钥 * @return */ public static AccessToken getAccessToken(String appid, String appsecret) { AccessToken accessToken = null; String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret); JSONObject jsonObject = httpRequest(requestUrl, "GET", null); // 如果请求成功 if (null != jsonObject) { try { accessToken = new AccessToken(); accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); } catch (JSONException e) { accessToken = null; // 获取token失败 System.out.println("获取token失败 errcode:{} errmsg:{}"+jsonObject.getInt("errcode")+":"+ jsonObject.getString("errmsg")); } } return accessToken; } /** * 4. 获取JsapiTicket * @param accessToken * @return */ public static String getJsapiTicket(String accessToken){ String requestUrl = jsapi_ticket_url.replace("ACCESSTOKEN", accessToken); JSONObject jsonObject = httpRequest(requestUrl, "GET", null); String jsapi_ticket=""; // 如果请求成功 if (null != jsonObject) { try { jsapi_ticket=jsonObject.getString("ticket"); } catch (JSONException e) { e.printStackTrace(); // 获取token失败 // log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return jsapi_ticket; } /** * 3.获取企业微信的JSSDK配置信息 * @param request * @return */ /* public static Map<String, Object> getWxConfig(HttpServletRequest request) { Map<String, Object> ret = new HashMap<String, Object>(); //1.准备好参与签名的字段 String nonceStr = UUID.randomUUID().toString(); // 必填,生成签名的随机串 //System.out.println("nonceStr:"+nonceStr); String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); String jsapi_ticket =getJsapiTicket(accessToken);// 必填,生成签名的H5应用调用企业微信JS接口的临时票据 //System.out.println("jsapi_ticket:"+jsapi_ticket); String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成签名的时间戳 //System.out.println("timestamp:"+timestamp); String url=request.getRequestURL().toString(); //System.out.println("url:"+url); //2.字典序 ,注意这里参数名必须全部小写,且必须有序 String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr+ "×tamp=" + timestamp + "&url=" + url; //3.sha1签名 String signature = ""; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(sign.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); //System.out.println("signature:"+signature); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret.put("appId", WeiXinParamesUtil.corpId); ret.put("timestamp", timestamp); ret.put("nonceStr", nonceStr); ret.put("signature", signature); return ret; }*/ /** * 方法名:byteToHex</br> * 详述:字符串加密辅助方法 </br> * 开发人员:souvc </br> * 创建时间:2016-1-5 </br> * @param hash * @return 说明返回值含义 * @throws 说明发生此异常的条件 */ private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } private static String getExt(String contentType){ if("image/jpeg".equals(contentType)){ return ".jpg"; }else if("image/png".equals(contentType)){ return ".png"; }else if("image/gif".equals(contentType)){ return ".gif"; } return null; } }
WeiXinParamesUtil.java
public class WeiXinParamesUtil { //1.微信参数 //token public final static String token = "ray"; // encodingAESKey public final static String encodingAESKey = "z2W9lyOAR1XjY8mopEmiSqib0TlBZzCFiCLp6IdS2Iv"; //企业ID public final static String corpId = "xxxxxx"; //应用的凭证密钥 public final static String agentSecret = "xxxxx"; //通讯录秘钥 public final static String contactsSecret = "1m_9XP62YrXjSxxxxxiLVWBThukiK5sH7wm1TM"; //打卡的凭证密钥 public final static String checkInSecret = "LLTMcHo5oxxxxxU0F6wX_gRIc"; //审批的凭证密钥 public final static String approveSecret = "6X7Ft0hIZXYxxxxxefWZE0-8"; //企业应用的id,整型。可在应用的设置页面查看 public final static int agentId = 1000014; }
4.发送消息测试类——SendMessageTest
import java.util.ArrayList; import java.util.List; import org.junit.Test; import com.ray.pojo.message.send.Article; import com.ray.pojo.message.send.FileMessage; import com.ray.pojo.message.send.ImgMessage; import com.ray.pojo.message.send.Media; import com.ray.pojo.message.send.News; import com.ray.pojo.message.send.NewsMessage; import com.ray.pojo.message.send.Text; import com.ray.pojo.message.send.TextMessage; import com.ray.pojo.message.send.Textcard; import com.ray.pojo.message.send.TextcardMessage; import com.ray.pojo.message.send.Video; import com.ray.pojo.message.send.VideoMessage; import com.ray.pojo.message.send.VoiceMessage; import com.ray.service.SendMessageService; import com.ray.util.WeiXinParamesUtil; import com.ray.util.WeiXinUtil; /**@desc : 消息推送之发送消息 * * @author: hh * @date : 2017-8-18 上午10:04:55 */ public class SendMessageTest { //1.发送文本消息 @Test public void testSendTextMessage(){ //0.设置消息内容 String content="你的快递已到,请携带工卡前往邮件中心领取。 出发前可查看" + "<a href="http://work.weixin.qq.com">邮件中心视频实况" + "</a>,聪明避开排队。"; //1.创建文本消息对象 TextMessage message=new TextMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("text"); message.setAgentid(WeiXinParamesUtil.agentId); Text text=new Text(); text.setContent(content); message.setText(text); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //2.发送文本卡片消息 @Test public void testSendTextcardMessage(){ //0.设置消息内容 String title="代办事宜"; String description="<div class="gray">2017年8月18日</div> <div class="normal">" + "恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class="highlight">" + "请于2017年10月10日前联系行政同事领取</div>"; String url="http://www.cnblogs.com/shirui/p/7297872.html"; //1.创建文本卡片消息对象 TextcardMessage message=new TextcardMessage(); //1.1非必需 message.setTouser("shirui"); //不区分大小写 //message.setToparty("1"); //message.setTotag(totag); //message.setSafe(0); //1.2必需 message.setMsgtype("textcard"); message.setAgentid(WeiXinParamesUtil.agentId); Textcard textcard=new Textcard(); textcard.setTitle(title); textcard.setDescription(description); textcard.setUrl(url); message.setTextcard(textcard); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //3.发送图片消息---无效的media_id @Test public void testSendImgMessage(){ //0.设置消息内容 String media_; //1.创建图片消息对象 ImgMessage message=new ImgMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("image"); message.setAgentid(WeiXinParamesUtil.agentId); Media image=new Media(); image.setMedia_id(media_id); message.setImage(image); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //4.发送语音消息---无效的media_id @Test public void testSendVoiceMessage(){ //0.设置消息内容 String media_; //1.创建语音消息对象 VoiceMessage message=new VoiceMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("image"); message.setAgentid(WeiXinParamesUtil.agentId); Media voice=new Media(); voice.setMedia_id(media_id); message.setVoice(voice); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //5.发送视频消息 @Test public void testSendVideoMessage(){ //0.设置消息内容 String media_; String title="视频示例"; String description="好看的视频"; //1.创建视频消息对象 VideoMessage message=new VideoMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //message.setToparty("1"); //message.setTotag(totag); //message.setSafe(0); //1.2必需 message.setMsgtype("video"); message.setAgentid(WeiXinParamesUtil.agentId); Video video=new Video(); video.setMedia_id(media_id); video.setTitle(title); video.setDescription(description); message.setVideo(video); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //6.发送文件消息 @Test public void testSendFileMessage(){ //0.设置消息内容 String media_; //1.创建文件对象 FileMessage message=new FileMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("file"); message.setAgentid(WeiXinParamesUtil.agentId); Media file=new Media(); file.setMedia_id(media_id); message.setFile(file); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //7.发送图文消息 @Test public void testSendNewsMessage(){ //1.创建图文消息对象 NewsMessage message=new NewsMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("news"); message.setAgentid(WeiXinParamesUtil.agentId); //设置图文消息 Article article1=new Article(); article1.setTitle("青年文摘"); article1.setDescription("这是一个很特别的描述"); article1.setPicurl("http://mat1.gtimg.com/fashion/images/index/2017/08/18/tpzs2.jpg"); article1.setUrl("http://www.cnblogs.com/shirui/p/7297872.html"); List<Article> articles=new ArrayList<Article>(); articles.add(article1); News news=new News(); news.setArticles(articles); message.setNews(news); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } }
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.cn</groupId> <artifactId>upload</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.0.6.RELEASE</version> </dependency> <!-- <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.2.3</version> </dependency> --> <!--文件上传下载所用的包============ --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- jstl-api --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>jstl-api</artifactId> <version>1.2</version> </dependency> <!-- jstl-impl --> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>jstl-impl</artifactId> <version>1.2</version> </dependency> <!-- 标签standard包 --> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- 数据库配置 --> <!--mybatis mysql--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.29</version> </dependency> <!-- jdbc驱动jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.1.1.RELEASE</version> </dependency> <!-- 生成token需要的jar包 --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version> </dependency> <!-- 企业微信--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.5</version> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> <classifier>jdk15</classifier> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.51</version> </dependency> </dependencies> </project>
1 /** 2 * 图片、语音、文件 3 * @author hh 4 * 5 */ 6 public class Media { 7 //是 图片/语音/文件 媒体文件id,可以调用上传临时素材接口获取 8 private String media_id; 9 10 public String getMedia_id() { 11 return media_id; 12 } 13 14 public void setMedia_id(String media_id) { 15 this.media_id = media_id; 16 } 17 }