zoukankan      html  css  js  c++  java
  • 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 }
    View Code

    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" : "你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看<a href=\"http://work.weixin.qq.com\">邮件中心视频实况</a>,聪明避开排队。"
     9    },
    10    "safe":0
    11 }
    View Code

    可把整个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 }
    View Code

    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 }
    View Code

    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 }
    View Code

    1.3.1 图片消息——ImgMessage

     1 /**
     2  * 图片消息
     3  * @author hh
     4  *
     5  */
     6 public class ImgMessage extends BaseMessage {  
     7     //图片
     8     private Media image ;
     9     //否     表示是否是保密消息,0表示否,1表示是,默认0
    10     private int safe;
    11     
    12     public Media getImage() {
    13         return image;
    14     }
    15     public void setImage(Media image) {
    16         this.image = image;
    17     }
    18     public int getSafe() {
    19         return safe;
    20     }
    21     public void setSafe(int safe) {
    22         this.safe = safe;
    23     }  
    24 }  
    View Code

    1.3.2 语音消息——VoiceMessage

     1 /**
     2  * 语音消息
     3  * @author hh
     4  *
     5  */
     6 public class VoiceMessage extends BaseMessage {  
     7     //语音
     8     private Media voice ;
     9     //否     表示是否是保密消息,0表示否,1表示是,默认0
    10     private int safe;
    11     
    12     public Media getVoice() {
    13         return voice;
    14     }
    15     public void setVoice(Media voice) {
    16         this.voice = voice;
    17     }
    18     public int getSafe() {
    19         return safe;
    20     }
    21     public void setSafe(int safe) {
    22         this.safe = safe;
    23     }
    24 }
    View Code

    1.3.3 文件消息——FileMessage

     1 /**
     2  * 文件消息
     3  * @author hh
     4  *
     5  */
     6 public class FileMessage extends BaseMessage {  
     7     //文件
     8     private Media file ;
     9     //否     表示是否是保密消息,0表示否,1表示是,默认0
    10     private int safe;
    11    
    12     public Media getFile() {
    13         return file;
    14     }
    15     public void setFile(Media file) {
    16         this.file = file;
    17     }
    18     public int getSafe() {
    19         return safe;
    20     }
    21     public void setSafe(int safe) {
    22         this.safe = safe;
    23     }
    24 }  
    View Code

    1.4  视频消息——Video、VideoMessage

    Video.java

     1 /**
     2  * 视频
     3  * @author hh
     4  *
     5  */
     6 public class Video {
     7     //是     视频媒体文件id,可以调用上传临时素材接口获取
     8     private String media_id;    
     9     //否     视频消息的标题,不超过128个字节,超过会自动截断
    10     private String title;
    11     //否     视频消息的描述,不超过512个字节,超过会自动截断
    12     private String description;
    13     
    14     public String getMedia_id() {
    15         return media_id;
    16     }
    17     public void setMedia_id(String media_id) {
    18         this.media_id = media_id;
    19     }
    20     public String getTitle() {
    21         return title;
    22     }
    23     public void setTitle(String title) {
    24         this.title = title;
    25     }
    26     public String getDescription() {
    27         return description;
    28     }
    29     public void setDescription(String description) {
    30         this.description = description;
    31     }    
    32 }
    View Code

    VideoMessage.java

     1 /**
     2  * 视频消息
     3  * @author hh
     4  *
     5  */
     6 public class VideoMessage extends BaseMessage {  
     7     //视频
     8     private Video video ;
     9     //否     表示是否是保密消息,0表示否,1表示是,默认0
    10     private int safe;
    11     
    12     public Video getVideo() {
    13         return video;
    14     }
    15     public void setVideo(Video video) {
    16         this.video = video;
    17     }
    18     public int getSafe() {
    19         return safe;
    20     }
    21     public void setSafe(int safe) {
    22         this.safe = safe;
    23     }
    24 }  
    View Code

    1.5 文本卡片消息——Textcard、TextcardMessage

    Textcard.java

     1 /**
     2  * 文本卡片
     3  * @author hh
     4  *
     5  */
     6 public class Textcard {
     7     //是 标题,不超过128个字节,超过会自动截断
     8     private String title;    
     9     //是    描述,不超过512个字节,超过会自动截断
    10     private String description;    
    11     //是    点击后跳转的链接。
    12     private String url;
    13     public String getTitle() {
    14         return title;
    15     }
    16     public void setTitle(String title) {
    17         this.title = title;
    18     }
    19     public String getDescription() {
    20         return description;
    21     }
    22     public void setDescription(String description) {
    23         this.description = description;
    24     }
    25     public String getUrl() {
    26         return url;
    27     }
    28     public void setUrl(String url) {
    29         this.url = url;
    30     }    
    31 }
    View Code

    TextcardMessage.java

     1 /**
     2  * 文本卡片消息
     3  * @author hh
     4  *
     5  */
     6 public class TextcardMessage extends BaseMessage {  
     7     //文本
     8     private Textcard textcard;
     9     
    10     //btntxt    否    按钮文字。 默认为“详情”, 不超过4个文字,超过自动截断。
    11     
    12     public Textcard getTextcard() {
    13         return textcard;
    14     }
    15 
    16     public void setTextcard(Textcard textcard) {
    17         this.textcard = textcard;
    18     }
    19 }  
    View Code

    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

     1 /**
     2  * 文章
     3  * @author hh
     4  *
     5  */
     6 public class Article {
     7     //是    标题,不超过128个字节,超过会自动截断
     8     private String title;    
     9     //否    描述,不超过512个字节,超过会自动截断
    10     private String description;    
    11     //是    点击后跳转的链接。
    12     private String url;    
    13     //否    图文消息的图片链接,支持JPG、PNG格式,较好的效果为大图640320,小图8080。
    14     private String picurl;
    15     public String getTitle() {
    16         return title;
    17     }
    18     public void setTitle(String title) {
    19         this.title = title;
    20     }
    21     public String getDescription() {
    22         return description;
    23     }
    24     public void setDescription(String description) {
    25         this.description = description;
    26     }
    27     public String getUrl() {
    28         return url;
    29     }
    30     public void setUrl(String url) {
    31         this.url = url;
    32     }
    33     public String getPicurl() {
    34         return picurl;
    35     }
    36     public void setPicurl(String picurl) {
    37         this.picurl = picurl;
    38     }    
    39 }
    View Code

    News.java

     1 import java.util.List;
     2 
     3 /**
     4  * 图文
     5  * @author hh
     6  *
     7  */
     8 public class News {
     9      //文章列表
    10      private List<Article> articles;
    11 
    12     public List<Article> getArticles() {
    13         return articles;
    14     }
    15 
    16     public void setArticles(List<Article> articles) {
    17         this.articles = articles;
    18     }
    19 }

    NewsMessage.java

     1 /**
     2  * 图文消息
     3  * @author hh
     4  *
     5  */
     6 public class NewsMessage extends BaseMessage {  
     7     //图文
     8     private News news;
     9 
    10     public News getNews() {
    11         return news;
    12     }
    13 
    14     public void setNews(News news) {
    15         this.news = news;
    16     }
    17 }  

    2.发送消息业务类——SendMessageService

     1 package com.ray.service;
     2 
     3 import org.slf4j.Logger;
     4 import org.slf4j.LoggerFactory;
     5 
     6 import net.sf.json.JSONObject;
     7 
     8 import com.google.gson.Gson;
     9 import com.ray.pojo.message.send.BaseMessage;
    10 
    11 import com.ray.test.UserTest;
    12 import com.ray.util.WeiXinUtil;
    13 
    14 /**@desc  : 发送消息
    15  * 
    16  * @author: shirayner
    17  * @date  : 2017-8-18 上午10:06:23
    18  */
    19 public class SendMessageService {
    20     private static Logger log = LoggerFactory.getLogger(UserTest.class);  
    21 
    22     private  static  String sendMessage_url="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";  
    23 
    24     /**
    25      * @desc :0.公共方法:发送消息
    26      *  
    27      * @param accessToken
    28      * @param message void
    29      */
    30     public void sendMessage(String accessToken,BaseMessage message){
    31 
    32         //1.获取json字符串:将message对象转换为json字符串    
    33         Gson gson = new Gson(); 
    34         String jsonMessage =gson.toJson(message);      //使用gson.toJson(user)即可将user对象顺序转成json
    35         System.out.println("jsonTextMessage:"+jsonMessage);
    36 
    37 
    38         //2.获取请求的url  
    39         sendMessage_url=sendMessage_url.replace("ACCESS_TOKEN", accessToken);
    40 
    41         //3.调用接口,发送消息
    42         JSONObject jsonObject = WeiXinUtil.httpRequest(sendMessage_url, "POST", jsonMessage);  
    43         System.out.println("jsonObject:"+jsonObject.toString());
    44 
    45         //4.错误消息处理
    46         if (null != jsonObject) {  
    47             if (0 != jsonObject.getInt("errcode")) {  
    48                 log.error("创建成员失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
    49             }  
    50         }  
    51     }
    52 }
    View Code

    3.工具类

    MyX509TrustManager.java

     1 import java.security.cert.CertificateException;  
     2 import java.security.cert.X509Certificate;  
     3   
     4 import javax.net.ssl.X509TrustManager;  
     5   
     6 /** 
     7  * 证书信任管理器(用于https请求) 
     8  *  
     9  * @author hh
    10  * @date 2016-08-08 
    11  */  
    12 public class MyX509TrustManager implements X509TrustManager {  
    13   
    14     public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
    15     }  
    16   
    17     public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {  
    18     }  
    19   
    20     public X509Certificate[] getAcceptedIssuers() {  
    21         return null;  
    22     }  
    23 } 
    View Code

    AccessToken.java

     1 public class AccessToken {
     2      // 获取到的凭证  
     3     private String token;  
     4     // 凭证有效时间,单位:秒  
     5     private int expiresIn;  
     6   
     7     public String getToken() {  
     8         return token;  
     9     }  
    10   
    11     public void setToken(String token) {  
    12         this.token = token;  
    13     }  
    14   
    15     public int getExpiresIn() {  
    16         return expiresIn;  
    17     }  
    18   
    19     public void setExpiresIn(int expiresIn) {  
    20         this.expiresIn = expiresIn;  
    21     }  
    22 }

    WeiXinUtil.java

      1 import java.io.BufferedReader;
      2 import java.io.DataInputStream;
      3 import java.io.DataOutputStream;
      4 import java.io.File;
      5 import java.io.FileInputStream;
      6 import java.io.FileOutputStream;
      7 import java.io.IOException;
      8 import java.io.InputStream;
      9 import java.io.InputStreamReader;
     10 import java.io.OutputStream;
     11 import java.io.UnsupportedEncodingException;
     12 import java.net.ConnectException;
     13 import java.net.HttpURLConnection;
     14 import java.net.URL;
     15 import java.security.MessageDigest;
     16 import java.security.NoSuchAlgorithmException;
     17 import java.util.Formatter;
     18 import java.util.HashMap;
     19 import java.util.Map;
     20 import java.util.UUID;
     21 
     22 import javax.net.ssl.HttpsURLConnection;
     23 import javax.net.ssl.SSLContext;
     24 import javax.net.ssl.SSLSocketFactory;
     25 import javax.net.ssl.TrustManager;
     26 import javax.servlet.http.HttpServletRequest;
     27 
     28 import net.sf.json.JSONException;
     29 import net.sf.json.JSONObject;
     30 
     31 public class WeiXinUtil {
     32          //rivate static Logger log = LoggerFactory.getLogger(WeiXinUtil.class);  
     33         //微信的请求url
     34         //获取access_token的接口地址(GET) 限200(次/天)  
     35         public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";  
     36         //获取jsapi_ticket的接口地址(GET) 限200(次/天)  
     37         public final static String jsapi_ticket_url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESSTOKEN";  
     38 
     39 
     40 
     41         /**
     42          * 1.发起https请求并获取结果 
     43          *  
     44          * @param requestUrl 请求地址 
     45          * @param requestMethod 请求方式(GET、POST) 
     46          * @param outputStr 提交的数据 
     47          * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) 
     48          */  
     49         public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
     50             JSONObject jsonObject = null;  
     51             StringBuffer buffer = new StringBuffer();  
     52             try {  
     53                 // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
     54                 TrustManager[] tm = { new MyX509TrustManager() };  
     55                 SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
     56                 sslContext.init(null, tm, new java.security.SecureRandom());  
     57                 // 从上述SSLContext对象中得到SSLSocketFactory对象  
     58                 SSLSocketFactory ssf = sslContext.getSocketFactory();  
     59 
     60                 URL url = new URL(requestUrl);  
     61                 HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
     62                 httpUrlConn.setSSLSocketFactory(ssf);  
     63 
     64                 httpUrlConn.setDoOutput(true);  
     65                 httpUrlConn.setDoInput(true);  
     66                 httpUrlConn.setUseCaches(false);  
     67                 // 设置请求方式(GET/POST)  
     68                 httpUrlConn.setRequestMethod(requestMethod);  
     69 
     70                 if ("GET".equalsIgnoreCase(requestMethod))  
     71                     httpUrlConn.connect();  
     72 
     73                 // 当有数据需要提交时  
     74                 if (null != outputStr) {  
     75                     OutputStream outputStream = httpUrlConn.getOutputStream();  
     76                     // 注意编码格式,防止中文乱码  
     77                     outputStream.write(outputStr.getBytes("UTF-8"));  
     78                     outputStream.close();  
     79                 }  
     80 
     81                 // 将返回的输入流转换成字符串  
     82                 InputStream inputStream = httpUrlConn.getInputStream();  
     83                 InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");  
     84                 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
     85 
     86                 String str = null;  
     87                 while ((str = bufferedReader.readLine()) != null) {  
     88                     buffer.append(str);  
     89                 }  
     90                 bufferedReader.close();  
     91                 inputStreamReader.close();  
     92                 // 释放资源  
     93                 inputStream.close();  
     94                 inputStream = null;  
     95                 httpUrlConn.disconnect();  
     96                 jsonObject = JSONObject.fromObject(buffer.toString());  
     97             } catch (ConnectException ce) {  
     98                 ce.printStackTrace();
     99             } catch (Exception e) {  
    100                 e.printStackTrace();
    101             }  
    102             return jsonObject;  
    103         }  
    104 
    105        /**
    106          * 2.发送https请求之获取临时素材 
    107          * @param requestUrl
    108          * @param savePath  文件的保存路径,此时还缺一个扩展名
    109          * @return
    110          * @throws Exception
    111          */
    112         /*public static File getFile(String requestUrl,String savePath) throws Exception {  
    113             //String path=System.getProperty("user.dir")+"/img//1.png";
    114         
    115             
    116                 // 创建SSLContext对象,并使用我们指定的信任管理器初始化  
    117                 TrustManager[] tm = { new MyX509TrustManager() };  
    118                 SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
    119                 sslContext.init(null, tm, new java.security.SecureRandom());  
    120                 // 从上述SSLContext对象中得到SSLSocketFactory对象  
    121                 SSLSocketFactory ssf = sslContext.getSocketFactory();  
    122 
    123                 URL url = new URL(requestUrl);  
    124                 HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
    125                 httpUrlConn.setSSLSocketFactory(ssf);  
    126 
    127                 httpUrlConn.setDoOutput(true);  
    128                 httpUrlConn.setDoInput(true);  
    129                 httpUrlConn.setUseCaches(false);  
    130                 // 设置请求方式(GET/POST)  
    131                 httpUrlConn.setRequestMethod("GET");  
    132 
    133                 httpUrlConn.connect();  
    134 
    135                 //获取文件扩展名
    136                 String ext=getExt(httpUrlConn.getContentType());
    137                 savePath=savePath+ext;
    138                 System.out.println("savePath"+savePath);
    139                 //下载文件到f文件
    140                 File file = new File(savePath);
    141 
    142                 
    143                 // 获取微信返回的输入流
    144                 InputStream in = httpUrlConn.getInputStream(); 
    145                 
    146                 //输出流,将微信返回的输入流内容写到文件中
    147                 FileOutputStream out = new FileOutputStream(file);
    148                  
    149                 int length=100*1024;
    150                 byte[] byteBuffer = new byte[length]; //存储文件内容
    151                 
    152                 int byteread =0;
    153                 int bytesum=0;
    154                 
    155                 while (( byteread=in.read(byteBuffer)) != -1) {  
    156                     bytesum += byteread; //字节数 文件大小 
    157                     out.write(byteBuffer,0,byteread);  
    158                     
    159                 }  
    160                 System.out.println("bytesum: "+bytesum);
    161                 
    162                 in.close();  
    163                 // 释放资源  
    164                 out.close();  
    165                 in = null;  
    166                 out=null;
    167                 
    168                 httpUrlConn.disconnect();  
    169 
    170                 
    171                 return file;
    172         } */ 
    173         
    174         
    175 
    176         /**
    177          * @desc :2.微信上传素材的请求方法
    178          *  
    179          * @param requestUrl  微信上传临时素材的接口url
    180          * @param file    要上传的文件
    181          * @return String  上传成功后,微信服务器返回的消息
    182          */
    183         public static String httpRequest(String requestUrl, File file) {  
    184             StringBuffer buffer = new StringBuffer();  
    185 
    186             try{
    187                 //1.建立连接
    188                 URL url = new URL(requestUrl);
    189                 HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  //打开链接
    190 
    191                 //1.1输入输出设置
    192                 httpUrlConn.setDoInput(true);
    193                 httpUrlConn.setDoOutput(true);
    194                 httpUrlConn.setUseCaches(false); // post方式不能使用缓存
    195                 //1.2设置请求头信息
    196                 httpUrlConn.setRequestProperty("Connection", "Keep-Alive");
    197                 httpUrlConn.setRequestProperty("Charset", "UTF-8");
    198                 //1.3设置边界
    199                 String BOUNDARY = "----------" + System.currentTimeMillis();
    200                 httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY);
    201 
    202                 // 请求正文信息
    203                 // 第一部分:
    204                 //2.将文件头输出到微信服务器
    205                 StringBuilder sb = new StringBuilder();
    206                 sb.append("--"); // 必须多两道线
    207                 sb.append(BOUNDARY);
    208                 sb.append("\r\n");
    209                 sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length()
    210                 + "\";filename=\""+ file.getName() + "\"\r\n");
    211                 sb.append("Content-Type:application/octet-stream\r\n\r\n");
    212                 byte[] head = sb.toString().getBytes("utf-8");
    213                 // 获得输出流
    214                 OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream());
    215                 // 将表头写入输出流中:输出表头
    216                 outputStream.write(head);
    217 
    218                 //3.将文件正文部分输出到微信服务器
    219                 // 把文件以流文件的方式 写入到微信服务器中
    220                 DataInputStream in = new DataInputStream(new FileInputStream(file));
    221                 int bytes = 0;
    222                 byte[] bufferOut = new byte[1024];
    223                 while ((bytes = in.read(bufferOut)) != -1) {
    224                     outputStream.write(bufferOut, 0, bytes);
    225                 }
    226                 in.close();
    227                 //4.将结尾部分输出到微信服务器
    228                 byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
    229                 outputStream.write(foot);
    230                 outputStream.flush();
    231                 outputStream.close();
    232 
    233 
    234                 //5.将微信服务器返回的输入流转换成字符串  
    235                 InputStream inputStream = httpUrlConn.getInputStream();  
    236                 InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
    237                 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    238 
    239                 String str = null;  
    240                 while ((str = bufferedReader.readLine()) != null) {  
    241                     buffer.append(str);  
    242                 }  
    243 
    244                 bufferedReader.close();  
    245                 inputStreamReader.close();  
    246                 // 释放资源  
    247                 inputStream.close();  
    248                 inputStream = null;  
    249                 httpUrlConn.disconnect();  
    250 
    251 
    252             } catch (IOException e) {
    253                 System.out.println("发送POST请求出现异常!" + e);
    254                 e.printStackTrace();
    255             } 
    256             return buffer.toString();
    257         }
    258 
    259         /** 
    260          * 2.发起http请求获取返回结果 
    261          *  
    262          * @param requestUrl 请求地址 
    263          * @return 
    264          */  
    265         public static String httpRequest(String requestUrl) {  
    266             StringBuffer buffer = new StringBuffer();  
    267             try {  
    268                 URL url = new URL(requestUrl);  
    269                 HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  
    270 
    271                 httpUrlConn.setDoOutput(false);  
    272                 httpUrlConn.setDoInput(true);  
    273                 httpUrlConn.setUseCaches(false);  
    274 
    275                 httpUrlConn.setRequestMethod("GET");  
    276                 httpUrlConn.connect();  
    277 
    278                 // 将返回的输入流转换成字符串  
    279                 InputStream inputStream = httpUrlConn.getInputStream();  
    280                 //InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
    281                 InputStreamReader inputStreamReader = new InputStreamReader(inputStream);  
    282                 BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    283 
    284                 String str = null;  
    285                 while ((str = bufferedReader.readLine()) != null) {  
    286                     buffer.append(str);  
    287 
    288                 }  
    289                 bufferedReader.close();  
    290                 inputStreamReader.close();  
    291                 // 释放资源  
    292                 inputStream.close();  
    293                 inputStream = null;  
    294                 httpUrlConn.disconnect();  
    295 
    296             } catch (Exception e) {  
    297             }  
    298             return buffer.toString();  
    299         }  
    300 
    301 
    302         /** 
    303          * 3.获取access_token 
    304          *  
    305          * @param appid 凭证 
    306          * @param appsecret 密钥 
    307          * @return 
    308          */  
    309         public static AccessToken getAccessToken(String appid, String appsecret) {  
    310             AccessToken accessToken = null;  
    311 
    312             String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret);  
    313             JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
    314             // 如果请求成功  
    315             if (null != jsonObject) {  
    316                 try {  
    317                     accessToken = new AccessToken();  
    318                     accessToken.setToken(jsonObject.getString("access_token"));  
    319                     accessToken.setExpiresIn(jsonObject.getInt("expires_in"));  
    320                 } catch (JSONException e) {  
    321                     accessToken = null;  
    322                     // 获取token失败  
    323                     System.out.println("获取token失败 errcode:{} errmsg:{}"+jsonObject.getInt("errcode")+":"+ jsonObject.getString("errmsg"));  
    324                 }  
    325             }  
    326             return accessToken;  
    327         }  
    328 
    329         /**
    330          * 4. 获取JsapiTicket
    331          * @param accessToken
    332          * @return
    333          */
    334         public static String getJsapiTicket(String accessToken){
    335 
    336 
    337             String requestUrl = jsapi_ticket_url.replace("ACCESSTOKEN", accessToken);  
    338             JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
    339 
    340             String  jsapi_ticket="";
    341             // 如果请求成功  
    342             if (null != jsonObject) {  
    343                 try {  
    344                     jsapi_ticket=jsonObject.getString("ticket");  
    345 
    346                 } catch (JSONException e) {  
    347                     e.printStackTrace();
    348                     // 获取token失败  
    349                    // log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
    350                 }  
    351             }  
    352             return jsapi_ticket;  
    353         }
    354 
    355         /**
    356          * 3.获取企业微信的JSSDK配置信息
    357          * @param request
    358          * @return
    359          */
    360        /* public static Map<String, Object> getWxConfig(HttpServletRequest request) {
    361             Map<String, Object> ret = new HashMap<String, Object>();
    362             //1.准备好参与签名的字段
    363 
    364             String nonceStr = UUID.randomUUID().toString(); // 必填,生成签名的随机串
    365             //System.out.println("nonceStr:"+nonceStr);
    366             String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    367             String jsapi_ticket =getJsapiTicket(accessToken);// 必填,生成签名的H5应用调用企业微信JS接口的临时票据
    368             //System.out.println("jsapi_ticket:"+jsapi_ticket);
    369             String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成签名的时间戳
    370             //System.out.println("timestamp:"+timestamp);
    371             String url=request.getRequestURL().toString();
    372             //System.out.println("url:"+url);
    373             
    374             //2.字典序           ,注意这里参数名必须全部小写,且必须有序
    375             String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr+ "&timestamp=" + timestamp + "&url=" + url;
    376 
    377             //3.sha1签名
    378             String signature = "";
    379             try {
    380                 MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    381                 crypt.reset();
    382                 crypt.update(sign.getBytes("UTF-8"));
    383                 signature = byteToHex(crypt.digest());
    384                 //System.out.println("signature:"+signature);
    385             } catch (NoSuchAlgorithmException e) {
    386                 e.printStackTrace();
    387             } catch (UnsupportedEncodingException e) {
    388                 e.printStackTrace();
    389             }
    390             ret.put("appId", WeiXinParamesUtil.corpId);
    391             ret.put("timestamp", timestamp);
    392             ret.put("nonceStr", nonceStr);
    393             ret.put("signature", signature);
    394             return ret;
    395         }*/
    396 
    397 
    398         /**
    399          * 方法名:byteToHex</br>
    400          * 详述:字符串加密辅助方法 </br>
    401          * 开发人员:souvc  </br>
    402          * 创建时间:2016-1-5  </br>
    403          * @param hash
    404          * @return 说明返回值含义
    405          * @throws 说明发生此异常的条件
    406          */
    407         private static String byteToHex(final byte[] hash) {
    408             Formatter formatter = new Formatter();
    409             for (byte b : hash) {
    410                 formatter.format("%02x", b);
    411             }
    412             String result = formatter.toString();
    413             formatter.close();
    414             return result;
    415 
    416         }
    417         
    418         
    419         
    420         private static String getExt(String contentType){
    421             if("image/jpeg".equals(contentType)){
    422                 return ".jpg";
    423             }else if("image/png".equals(contentType)){
    424                 return ".png";
    425             }else if("image/gif".equals(contentType)){
    426                 return ".gif";
    427             }
    428             
    429             return null;
    430         }
    431 }
    View Code

    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

      1 import java.util.ArrayList;
      2 import java.util.List;
      3 
      4 import org.junit.Test;
      5 
      6 import com.ray.pojo.message.send.Article;
      7 import com.ray.pojo.message.send.FileMessage;
      8 import com.ray.pojo.message.send.ImgMessage;
      9 import com.ray.pojo.message.send.Media;
     10 import com.ray.pojo.message.send.News;
     11 import com.ray.pojo.message.send.NewsMessage;
     12 import com.ray.pojo.message.send.Text;
     13 import com.ray.pojo.message.send.TextMessage;
     14 import com.ray.pojo.message.send.Textcard;
     15 import com.ray.pojo.message.send.TextcardMessage;
     16 import com.ray.pojo.message.send.Video;
     17 import com.ray.pojo.message.send.VideoMessage;
     18 import com.ray.pojo.message.send.VoiceMessage;
     19 import com.ray.service.SendMessageService;
     20 import com.ray.util.WeiXinParamesUtil;
     21 import com.ray.util.WeiXinUtil;
     22 
     23 /**@desc  : 消息推送之发送消息
     24  * 
     25  * @author: hh
     26  * @date  : 2017-8-18 上午10:04:55
     27  */
     28 public class SendMessageTest {
     29 
     30     //1.发送文本消息
     31     @Test
     32     public void testSendTextMessage(){
     33         //0.设置消息内容
     34         String content="你的快递已到,请携带工卡前往邮件中心领取。\n出发前可查看" +
     35                 "<a href=\"http://work.weixin.qq.com\">邮件中心视频实况" +
     36                 "</a>,聪明避开排队。";
     37 
     38         //1.创建文本消息对象
     39         TextMessage message=new TextMessage();
     40         //1.1非必需
     41         message.setTouser("@all");  //不区分大小写
     42         //textMessage.setToparty("1");
     43         //txtMsg.setTotag(totag);
     44         //txtMsg.setSafe(0);
     45 
     46         //1.2必需
     47         message.setMsgtype("text");
     48         message.setAgentid(WeiXinParamesUtil.agentId);
     49 
     50         Text text=new Text();
     51         text.setContent(content);
     52         message.setText(text);
     53 
     54         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
     55         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
     56         System.out.println("accessToken:"+accessToken);
     57 
     58         //3.发送消息:调用业务类,发送消息
     59         SendMessageService sms=new SendMessageService();
     60         sms.sendMessage(accessToken, message);
     61 
     62     }
     63 
     64     //2.发送文本卡片消息
     65     @Test
     66     public void testSendTextcardMessage(){
     67         //0.设置消息内容
     68         String title="代办事宜";
     69         String description="<div class=\"gray\">2017年8月18日</div> <div class=\"normal\">" +
     70                 "恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\"highlight\">" +
     71                 "请于2017年10月10日前联系行政同事领取</div>";
     72         String url="http://www.cnblogs.com/shirui/p/7297872.html";
     73 
     74         //1.创建文本卡片消息对象
     75         TextcardMessage message=new TextcardMessage();
     76         //1.1非必需
     77         message.setTouser("shirui");  //不区分大小写
     78         //message.setToparty("1");
     79         //message.setTotag(totag);
     80         //message.setSafe(0);
     81 
     82         //1.2必需
     83         message.setMsgtype("textcard");
     84         message.setAgentid(WeiXinParamesUtil.agentId);
     85 
     86         Textcard textcard=new Textcard();
     87         textcard.setTitle(title);
     88         textcard.setDescription(description);
     89         textcard.setUrl(url);
     90         message.setTextcard(textcard);
     91 
     92         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
     93         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
     94         System.out.println("accessToken:"+accessToken);
     95 
     96         //3.发送消息:调用业务类,发送消息
     97         SendMessageService sms=new SendMessageService();
     98         sms.sendMessage(accessToken, message);
     99 
    100     }
    101 
    102     //3.发送图片消息---无效的media_id
    103     @Test
    104     public void testSendImgMessage(){
    105         //0.设置消息内容
    106         String media_;
    107         //1.创建图片消息对象
    108         ImgMessage message=new ImgMessage();
    109         //1.1非必需
    110         message.setTouser("@all");  //不区分大小写
    111         //textMessage.setToparty("1");
    112         //txtMsg.setTotag(totag);
    113         //txtMsg.setSafe(0);
    114 
    115         //1.2必需
    116         message.setMsgtype("image");
    117         message.setAgentid(WeiXinParamesUtil.agentId);
    118 
    119         Media image=new Media();
    120         image.setMedia_id(media_id);
    121         message.setImage(image);
    122 
    123         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
    124         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    125         System.out.println("accessToken:"+accessToken);
    126 
    127         //3.发送消息:调用业务类,发送消息
    128         SendMessageService sms=new SendMessageService();
    129         sms.sendMessage(accessToken, message);
    130 
    131     }
    132 
    133 
    134     //4.发送语音消息---无效的media_id
    135     @Test
    136     public void testSendVoiceMessage(){
    137         //0.设置消息内容
    138         String media_;
    139         //1.创建语音消息对象
    140         VoiceMessage message=new VoiceMessage();
    141         //1.1非必需
    142         message.setTouser("@all");  //不区分大小写
    143         //textMessage.setToparty("1");
    144         //txtMsg.setTotag(totag);
    145         //txtMsg.setSafe(0);
    146 
    147         //1.2必需
    148         message.setMsgtype("image");
    149         message.setAgentid(WeiXinParamesUtil.agentId);
    150 
    151         Media voice=new Media();
    152         voice.setMedia_id(media_id);
    153         message.setVoice(voice);
    154 
    155         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
    156         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    157         System.out.println("accessToken:"+accessToken);
    158 
    159         //3.发送消息:调用业务类,发送消息
    160         SendMessageService sms=new SendMessageService();
    161         sms.sendMessage(accessToken, message);
    162 
    163     }
    164 
    165     //5.发送视频消息
    166     @Test
    167     public void testSendVideoMessage(){
    168         //0.设置消息内容
    169         String media_;
    170         String title="视频示例";
    171         String description="好看的视频";
    172 
    173 
    174         //1.创建视频消息对象
    175         VideoMessage message=new VideoMessage();
    176         //1.1非必需
    177         message.setTouser("@all");  //不区分大小写
    178         //message.setToparty("1");
    179         //message.setTotag(totag);
    180         //message.setSafe(0);
    181 
    182         //1.2必需
    183         message.setMsgtype("video");
    184         message.setAgentid(WeiXinParamesUtil.agentId);
    185 
    186         Video video=new Video();
    187         video.setMedia_id(media_id);
    188         video.setTitle(title);
    189         video.setDescription(description);
    190         message.setVideo(video);
    191 
    192         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
    193         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    194         System.out.println("accessToken:"+accessToken);
    195 
    196         //3.发送消息:调用业务类,发送消息
    197         SendMessageService sms=new SendMessageService();
    198         sms.sendMessage(accessToken, message);
    199 
    200     }
    201 
    202     //6.发送文件消息
    203     @Test
    204     public void testSendFileMessage(){
    205         //0.设置消息内容
    206         String media_;
    207 
    208         //1.创建文件对象
    209         FileMessage message=new FileMessage();
    210         //1.1非必需
    211         message.setTouser("@all");  //不区分大小写
    212         //textMessage.setToparty("1");
    213         //txtMsg.setTotag(totag);
    214         //txtMsg.setSafe(0);
    215 
    216         //1.2必需
    217         message.setMsgtype("file");
    218         message.setAgentid(WeiXinParamesUtil.agentId);
    219 
    220         Media file=new Media();
    221         file.setMedia_id(media_id);
    222         message.setFile(file);
    223 
    224         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
    225         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    226         System.out.println("accessToken:"+accessToken);
    227 
    228         //3.发送消息:调用业务类,发送消息
    229         SendMessageService sms=new SendMessageService();
    230         sms.sendMessage(accessToken, message);
    231 
    232     }
    233 
    234     //7.发送图文消息
    235     @Test
    236     public void testSendNewsMessage(){
    237 
    238         //1.创建图文消息对象
    239         NewsMessage message=new NewsMessage();
    240         //1.1非必需
    241         message.setTouser("@all");  //不区分大小写
    242         //textMessage.setToparty("1");
    243         //txtMsg.setTotag(totag);
    244         //txtMsg.setSafe(0);
    245 
    246         //1.2必需
    247         message.setMsgtype("news");
    248         message.setAgentid(WeiXinParamesUtil.agentId);
    249         //设置图文消息
    250         Article article1=new  Article();
    251         article1.setTitle("青年文摘");
    252         article1.setDescription("这是一个很特别的描述");
    253         article1.setPicurl("http://mat1.gtimg.com/fashion/images/index/2017/08/18/tpzs2.jpg");
    254         article1.setUrl("http://www.cnblogs.com/shirui/p/7297872.html");
    255         
    256         List<Article>  articles=new ArrayList<Article>();
    257         articles.add(article1);
    258         
    259         News news=new News();
    260         news.setArticles(articles);
    261         message.setNews(news);
    262 
    263         //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url
    264         String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
    265         System.out.println("accessToken:"+accessToken);
    266 
    267         //3.发送消息:调用业务类,发送消息
    268         SendMessageService sms=new SendMessageService();
    269         sms.sendMessage(accessToken, message);
    270 
    271     }
    272 }
    
    
    
  • 相关阅读:
    未能加载包“Microsoft SQL Server Data Tools”
    SharePoint 客户端对象模型共用ClientContext的坑
    安装VisualStudio 2015 x64 中文企业版失败
    Could not load file or assembly 'Microsoft.SqlServer.Management.Sdk.Sfc, Version=11.0.0.0 系统找不到指定的文件。
    为Sharepoint 2010 批量创建SharePoint测试用户
    User Profile Service Application 配置同步连接时,报 MOSS MA not found
    SharePoint 2010 系统账户没完全控制权限了
    百度编辑器 UEditor 报错汇总
    更改SharePoint 2007/2010/2013 Web 应用程序端口号
    SharePoint 2013 报:网站在改进过程中处于只读状态,对此给您带来的不便,我们深表歉意
  • 原文地址:https://www.cnblogs.com/snail90/p/10045414.html
Copyright © 2011-2022 走看看