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 }
    
    
    
  • 相关阅读:
    Building a flexiable renderer
    Indirect Illumination in mental ray
    我的心情
    Cellular Automata
    Subsurface Scattering in mental ray
    Shader Types in mental ray
    BSP Traversal
    我的渲染器终于达到了MR的速度
    How to handle displacement and motion blur
    说明
  • 原文地址:https://www.cnblogs.com/snail90/p/10045414.html
Copyright © 2011-2022 走看看