Java企業微信開發_04_消息推送之發送消息(主動)

 源碼請見: Java企業微信開發_00_源碼及資源彙總貼

1、本節要點

1.發送消息與被動回覆消息

(1)流程不一樣:發送消息是第三方服務器主動通知微信服務器向用戶發消息。而被動回覆消息是 用戶發送消息以後,微信服務器將消息傳遞給 第三方服務器,第三方服務器接收到消息後,再對消息作出相應的回覆消息。html

(2)消息是否加密:在發送消息的流程中,對封裝好的回覆消息(json字符串)是不進行AES加密的。java

                                  而在被動回覆消息的流程中,第三方服務器接收消息時,須要先解密微信發過來的消息,在最後發送回覆消息前,須要先加密(AES)回覆消息。node

(3)數據交換的格式不一樣:在發送消息的流程中,第三方服務器將消息(json字符串格式)發送給微信服務器json

                                             而在被動回覆消息的過程當中,第三方服務器接收的消息和被動回覆的消息都是以xml字符串格式的。api

 

 

2、代碼實現

1.實體類

1.1 消息基類(企業號 -> 普通用戶) ——BaseMessage

package com.ray.pojo.message.send;  
  
/**
 * 消息基類(企業號 -> 普通用戶) 
 * @author shirayner
 *
 */
public class BaseMessage {  
    // 否 成員ID列表(消息接收者,多個接收者用‘|’分隔,最多支持1000個)。特殊狀況:指定爲@all,則向該企業應用的所有成員發送
    private String touser;  
    // 否 部門ID列表,多個接收者用‘|’分隔,最多支持100個。當touser爲@all時忽略本參數
    private String toparty;  
    // 否 標籤ID列表,多個接收者用‘|’分隔,最多支持100個。當touser爲@all時忽略本參數
    private String totag;  
    // 是 消息類型 
    private String msgtype; 
    // 是 企業應用的id,整型。可在應用的設置頁面查看
    private int agentid;
    
    
    public String getTouser() {
        return touser;
    }
    public void setTouser(String touser) {
        this.touser = touser;
    }
    public String getToparty() {
        return toparty;
    }
    public void setToparty(String toparty) {
        this.toparty = toparty;
    }
    public String getTotag() {
        return totag;
    }
    public void setTotag(String totag) {
        this.totag = totag;
    }
    public String getMsgtype() {
        return msgtype;
    }
    public void setMsgtype(String msgtype) {
        this.msgtype = msgtype;
    }
    public int getAgentid() {
        return agentid;
    }
    public void setAgentid(int agentid) {
        this.agentid = agentid;
    }

    
 
    
    
}  
View Code

 

1.2 文本消息——Text、TextMessage

企業微信官方文檔中關於文本消息請求包的說明數組

{
   "touser" : "UserID1|UserID2|UserID3",
   "toparty" : " PartyID1|PartyID2 ",
   "totag" : " TagID1 | TagID2 ",
   "msgtype" : "text",
   "agentid" : 1,
   "text" : {
       "content" : "你的快遞已到,請攜帶工卡前往郵件中心領取。\n出發前可查看<a href=\"http://work.weixin.qq.com\">郵件中心視頻實況</a>,聰明避開排隊。"
   },
   "safe":0
}

可把整個json對象看作一個java對象,而在這個json對象中又包含一個text對象。(json中的對象用{ }包裹起來,json中的數組用[  ] 包裹起來緩存

需注意agentid、safe爲int型。因而能夠把text看作一個java對象,這樣TextMessage類組合了Text類,轉json字符串的時候,就能夠直接使用 String jsonTextMessage=gson.toJson(textMessage).服務器

因而,咱們開始對文本消息進行封裝微信

Text.java微信開發

package com.ray.pojo.message.send;

/**
 * 文本
 * @author shirayner
 *
 */
public class Text {
    //是    消息內容,最長不超過2048個字節
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }



}
View Code

 

TextMessage.java

package com.ray.pojo.message.send;  
  
/**
 * 文本消息
 * @author shirayner
 *
 */
public class TextMessage extends BaseMessage {  
    //文本
    private Text text;
    //否     表示是不是保密消息,0表示否,1表示是,默認0
    private int safe;
    
    public Text getText() {
        return text;
    }
    public void setText(Text text) {
        this.text = text;
    }
    public int getSafe() {
        return safe;
    }
    public void setSafe(int safe) {
        this.safe = safe;
    }
    
    
  
   
}  
View Code

 

1.3 圖片類、語音類、文件類——Media

經過對微信官方文檔的仔細閱讀,能夠看到圖片消息、語音消息、文件消息中的的json對象都內含同一個Jason對象(media_id),因而咱們根據這個對象封裝Media.java

package com.ray.pojo.message.send;

/**
 * 圖片、語音、文件
 * @author shirayner
 *
 */
public class Media {
    //是     圖片/語音/文件 媒體文件id,能夠調用上傳臨時素材接口獲取
    private String media_id;

    public String getMedia_id() {
        return media_id;
    }

    public void setMedia_id(String media_id) {
        this.media_id = media_id;
    }    
    
    
}
View Code

 

1.3.1 圖片消息——ImgMessage

package com.ray.pojo.message.send;  
  
/**
 * 圖片消息
 * @author shirayner
 *
 */
public class ImgMessage extends BaseMessage {  
    //圖片
    private Media image ;
    //否     表示是不是保密消息,0表示否,1表示是,默認0
    private int safe;
    
    public Media getImage() {
        return image;
    }
    public void setImage(Media image) {
        this.image = image;
    }
    public int getSafe() {
        return safe;
    }
    public void setSafe(int safe) {
        this.safe = safe;
    }

   
}  
View Code

 

1.3.2 語音消息——VoiceMessage

package com.ray.pojo.message.send;  
  
/**
 * 語音消息
 * @author shirayner
 *
 */
public class VoiceMessage extends BaseMessage {  
    //語音
    private Media voice ;
    //否     表示是不是保密消息,0表示否,1表示是,默認0
    private int safe;
    
    public Media getVoice() {
        return voice;
    }
    public void setVoice(Media voice) {
        this.voice = voice;
    }
    public int getSafe() {
        return safe;
    }
    public void setSafe(int safe) {
        this.safe = safe;
    }
   
    

   
}  
View Code

 

1.3.3 文件消息——FileMessage

package com.ray.pojo.message.send;  
  
/**
 * 文件消息
 * @author shirayner
 *
 */
public class FileMessage extends BaseMessage {  
    //文件
    private Media file ;
    //否     表示是不是保密消息,0表示否,1表示是,默認0
    private int safe;
   
    public Media getFile() {
        return file;
    }
    public void setFile(Media file) {
        this.file = file;
    }
    public int getSafe() {
        return safe;
    }
    public void setSafe(int safe) {
        this.safe = safe;
    }
   
    

   
}  
View Code

 

1.4  視頻消息——Video、VideoMessage

Video.java

package com.ray.pojo.message.send;

/**
 * 視頻
 * @author shirayner
 *
 */
public class Video {
    //是     視頻媒體文件id,能夠調用上傳臨時素材接口獲取
    private String media_id;    
    //否     視頻消息的標題,不超過128個字節,超過會自動截斷
    private String title;
    //否     視頻消息的描述,不超過512個字節,超過會自動截斷
    private String description;
    
    public String getMedia_id() {
        return media_id;
    }
    public void setMedia_id(String media_id) {
        this.media_id = media_id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }    
    
    
}
View Code

 

VideoMessage.java

package com.ray.pojo.message.send;  
  
/**
 * 視頻消息
 * @author shirayner
 *
 */
public class VideoMessage extends BaseMessage {  
    //視頻
    private Video video ;
    //否     表示是不是保密消息,0表示否,1表示是,默認0
    private int safe;
    
    public Video getVideo() {
        return video;
    }
    public void setVideo(Video video) {
        this.video = video;
    }
    public int getSafe() {
        return safe;
    }
    public void setSafe(int safe) {
        this.safe = safe;
    }

}  
View Code

 

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

Textcard.java

package com.ray.pojo.message.send;

/**
 * 文本卡片
 * @author shirayner
 *
 */
public class Textcard {
    //是 標題,不超過128個字節,超過會自動截斷
    private String title;    
    //是    描述,不超過512個字節,超過會自動截斷
    private String description;    
    //是    點擊後跳轉的連接。
    private String url;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }    
    
    
}
View Code

 

TextcardMessage.java

package com.ray.pojo.message.send;  
  
/**
 * 文本卡片消息
 * @author shirayner
 *
 */
public class TextcardMessage extends BaseMessage {  
    //文本
    private Textcard textcard;
    
    //btntxt    否    按鈕文字。 默認爲「詳情」, 不超過4個文字,超過自動截斷。
    
    public Textcard getTextcard() {
        return textcard;
    }

    public void setTextcard(Textcard textcard) {
        this.textcard = textcard;
    }
   

   
}  
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

package com.ray.pojo.message.send;

/**
 * 文章
 * @author shirayner
 *
 */
public class Article {
    //是    標題,不超過128個字節,超過會自動截斷
    private String title;    
    //否    描述,不超過512個字節,超過會自動截斷
    private String description;    
    //是    點擊後跳轉的連接。
    private String url;    
    //否    圖文消息的圖片連接,支持JPG、PNG格式,較好的效果爲大圖640320,小圖8080。
    private String picurl;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getPicurl() {
        return picurl;
    }
    public void setPicurl(String picurl) {
        this.picurl = picurl;
    }    
    
    
}
View Code

News.java

package com.ray.pojo.message.send;

import java.util.List;

/**
 * 圖文
 * @author shirayner
 *
 */
public class News {
     //文章列表
     private List<Article> articles;

    public List<Article> getArticles() {
        return articles;
    }

    public void setArticles(List<Article> articles) {
        this.articles = articles;
    }
     
     
}
View Code

NewsMessage.java

package com.ray.pojo.message.send;  

  
/**
 * 圖文消息
 * @author shirayner
 *
 */
public class NewsMessage extends BaseMessage {  
    //圖文
    private News news;

    public News getNews() {
        return news;
    }

    public void setNews(News news) {
        this.news = news;
    }
    


}  
View Code

 

2.微信工具類—WeiXinUtil.java

package com.ray.util;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ray.pojo.AccessToken;




import net.sf.json.JSONException;
import net.sf.json.JSONObject;

public class WeiXinUtil {

    private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class);  
    //微信的請求url
    //獲取access_token的接口地址(GET) 限200(次/天)  
    public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";  
    //獲取jsapi_ticket的接口地址(GET) 限200(次/天)  
    public final static String jsapi_ticket_url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=ACCESSTOKEN";  



    /**
     * 1.發起https請求並獲取結果 
     *  
     * @param requestUrl 請求地址 
     * @param requestMethod 請求方式(GET、POST) 
     * @param outputStr 提交的數據 
     * @return JSONObject(經過JSONObject.get(key)的方式獲取json對象的屬性值) 
     */  
    public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {  
        JSONObject jsonObject = null;  
        StringBuffer buffer = new StringBuffer();  
        try {  
            // 建立SSLContext對象,並使用咱們指定的信任管理器初始化  
            TrustManager[] tm = { new MyX509TrustManager() };  
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
            sslContext.init(null, tm, new java.security.SecureRandom());  
            // 從上述SSLContext對象中獲得SSLSocketFactory對象  
            SSLSocketFactory ssf = sslContext.getSocketFactory();  

            URL url = new URL(requestUrl);  
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
            httpUrlConn.setSSLSocketFactory(ssf);  

            httpUrlConn.setDoOutput(true);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  
            // 設置請求方式(GET/POST)  
            httpUrlConn.setRequestMethod(requestMethod);  

            if ("GET".equalsIgnoreCase(requestMethod))  
                httpUrlConn.connect();  

            // 當有數據須要提交時  
            if (null != outputStr) {  
                OutputStream outputStream = httpUrlConn.getOutputStream();  
                // 注意編碼格式,防止中文亂碼  
                outputStream.write(outputStr.getBytes("UTF-8"));  
                outputStream.close();  
            }  

            // 將返回的輸入流轉換成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  

            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 釋放資源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  
            jsonObject = JSONObject.fromObject(buffer.toString());  
        } catch (ConnectException ce) {  
            log.error("Weixin server connection timed out.");  
        } catch (Exception e) {  
            log.error("https request error:{}", e);  
        }  
        return jsonObject;  
    }  

   /**
     * 2.發送https請求之獲取臨時素材 
     * @param requestUrl
     * @param savePath  文件的保存路徑,此時還缺一個擴展名
     * @return
     * @throws Exception
     */
    public static File getFile(String requestUrl,String savePath) throws Exception {  
        //String path=System.getProperty("user.dir")+"/img//1.png";
    
        
            // 建立SSLContext對象,並使用咱們指定的信任管理器初始化  
            TrustManager[] tm = { new MyX509TrustManager() };  
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
            sslContext.init(null, tm, new java.security.SecureRandom());  
            // 從上述SSLContext對象中獲得SSLSocketFactory對象  
            SSLSocketFactory ssf = sslContext.getSocketFactory();  

            URL url = new URL(requestUrl);  
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();  
            httpUrlConn.setSSLSocketFactory(ssf);  

            httpUrlConn.setDoOutput(true);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  
            // 設置請求方式(GET/POST)  
            httpUrlConn.setRequestMethod("GET");  

            httpUrlConn.connect();  

            //獲取文件擴展名
            String ext=getExt(httpUrlConn.getContentType());
            savePath=savePath+ext;
            System.out.println("savePath"+savePath);
            //下載文件到f文件
            File file = new File(savePath);

            
            // 獲取微信返回的輸入流
            InputStream in = httpUrlConn.getInputStream(); 
            
            //輸出流,將微信返回的輸入流內容寫到文件中
            FileOutputStream out = new FileOutputStream(file);
             
            int length=100*1024;
            byte[] byteBuffer = new byte[length]; //存儲文件內容
            
            int byteread =0;
            int bytesum=0;
            
            while (( byteread=in.read(byteBuffer)) != -1) {  
                bytesum += byteread; //字節數 文件大小 
                out.write(byteBuffer,0,byteread);  
                
            }  
            System.out.println("bytesum: "+bytesum);
            
            in.close();  
            // 釋放資源  
            out.close();  
            in = null;  
            out=null;
            
            httpUrlConn.disconnect();  

            
            return file;
    }  
    
    

    /**
     * @desc :2.微信上傳素材的請求方法
     *  
     * @param requestUrl  微信上傳臨時素材的接口url
     * @param file    要上傳的文件
     * @return String  上傳成功後,微信服務器返回的消息
     */
    public static String httpRequest(String requestUrl, File file) {  
        StringBuffer buffer = new StringBuffer();  

        try{
            //1.創建鏈接
            URL url = new URL(requestUrl);
            HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  //打開連接

            //1.1輸入輸出設置
            httpUrlConn.setDoInput(true);
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setUseCaches(false); // post方式不能使用緩存
            //1.2設置請求頭信息
            httpUrlConn.setRequestProperty("Connection", "Keep-Alive");
            httpUrlConn.setRequestProperty("Charset", "UTF-8");
            //1.3設置邊界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY);

            // 請求正文信息
            // 第一部分:
            //2.將文件頭輸出到微信服務器
            StringBuilder sb = new StringBuilder();
            sb.append("--"); // 必須多兩道線
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length()
            + "\";filename=\""+ file.getName() + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");
            byte[] head = sb.toString().getBytes("utf-8");
            // 得到輸出流
            OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream());
            // 將表頭寫入輸出流中:輸出表頭
            outputStream.write(head);

            //3.將文件正文部分輸出到微信服務器
            // 把文件以流文件的方式 寫入到微信服務器中
            DataInputStream in = new DataInputStream(new FileInputStream(file));
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, bytes);
            }
            in.close();
            //4.將結尾部分輸出到微信服務器
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定義最後數據分隔線
            outputStream.write(foot);
            outputStream.flush();
            outputStream.close();


            //5.將微信服務器返回的輸入流轉換成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  

            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  
            }  

            bufferedReader.close();  
            inputStreamReader.close();  
            // 釋放資源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  


        } catch (IOException e) {
            System.out.println("發送POST請求出現異常!" + e);
            e.printStackTrace();
        } 
        return buffer.toString();
    }

    /** 
     * 2.發起http請求獲取返回結果 
     *  
     * @param requestUrl 請求地址 
     * @return 
     */  
    public static String httpRequest(String requestUrl) {  
        StringBuffer buffer = new StringBuffer();  
        try {  
            URL url = new URL(requestUrl);  
            HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();  

            httpUrlConn.setDoOutput(false);  
            httpUrlConn.setDoInput(true);  
            httpUrlConn.setUseCaches(false);  

            httpUrlConn.setRequestMethod("GET");  
            httpUrlConn.connect();  

            // 將返回的輸入流轉換成字符串  
            InputStream inputStream = httpUrlConn.getInputStream();  
            //InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");  
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);  
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  

            String str = null;  
            while ((str = bufferedReader.readLine()) != null) {  
                buffer.append(str);  

            }  
            bufferedReader.close();  
            inputStreamReader.close();  
            // 釋放資源  
            inputStream.close();  
            inputStream = null;  
            httpUrlConn.disconnect();  

        } catch (Exception e) {  
        }  
        return buffer.toString();  
    }  


    /** 
     * 3.獲取access_token 
     *  
     * @param appid 憑證 
     * @param appsecret 密鑰 
     * @return 
     */  
    public static AccessToken getAccessToken(String appid, String appsecret) {  
        AccessToken accessToken = null;  

        String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret);  
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  
        // 若是請求成功  
        if (null != jsonObject) {  
            try {  
                accessToken = new AccessToken();  
                accessToken.setToken(jsonObject.getString("access_token"));  
                accessToken.setExpiresIn(jsonObject.getInt("expires_in"));  
            } catch (JSONException e) {  
                accessToken = null;  
                // 獲取token失敗  
                log.error("獲取token失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            }  
        }  
        return accessToken;  
    }  

    /**
     * 4. 獲取JsapiTicket
     * @param accessToken
     * @return
     */
    public static String getJsapiTicket(String accessToken){


        String requestUrl = jsapi_ticket_url.replace("ACCESSTOKEN", accessToken);  
        JSONObject jsonObject = httpRequest(requestUrl, "GET", null);  

        String  jsapi_ticket="";
        // 若是請求成功  
        if (null != jsonObject) {  
            try {  
                jsapi_ticket=jsonObject.getString("ticket");  

            } catch (JSONException e) {  

                // 獲取token失敗  
                log.error("獲取token失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            }  
        }  
        return jsapi_ticket;  
    }

    /**
     * 3.獲取企業微信的JSSDK配置信息
     * @param request
     * @return
     */
    public static Map<String, Object> getWxConfig(HttpServletRequest request) {
        Map<String, Object> ret = new HashMap<String, Object>();
        //1.準備好參與簽名的字段

        String nonceStr = UUID.randomUUID().toString(); // 必填,生成簽名的隨機串
        //System.out.println("nonceStr:"+nonceStr);
        String accessToken=WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        String jsapi_ticket =getJsapiTicket(accessToken);// 必填,生成簽名的H5應用調用企業微信JS接口的臨時票據
        //System.out.println("jsapi_ticket:"+jsapi_ticket);
        String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成簽名的時間戳
        //System.out.println("timestamp:"+timestamp);
        String url=request.getRequestURL().toString();
        //System.out.println("url:"+url);
        
        //2.字典序           ,注意這裏參數名必須所有小寫,且必須有序
        String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr+ "&timestamp=" + timestamp + "&url=" + url;

        //3.sha1簽名
        String signature = "";
        try {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(sign.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
            //System.out.println("signature:"+signature);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ret.put("appId", WeiXinParamesUtil.corpId);
        ret.put("timestamp", timestamp);
        ret.put("nonceStr", nonceStr);
        ret.put("signature", signature);
        return ret;
    }


    /**
     * 方法名:byteToHex</br>
     * 詳述:字符串加密輔助方法 </br>
     * 開發人員:souvc  </br>
     * 建立時間:2016-1-5  </br>
     * @param hash
     * @return 說明返回值含義
     * @throws 說明發生此異常的條件
     */
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;

    }
    
    
    
    private static String getExt(String contentType){
        if("image/jpeg".equals(contentType)){
            return ".jpg";
        }else if("image/png".equals(contentType)){
            return ".png";
        }else if("image/gif".equals(contentType)){
            return ".gif";
        }
        
        return null;
    }
}
View Code

 

3.發送消息業務類——SendMessageService

package com.ray.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.json.JSONObject;

import com.google.gson.Gson;
import com.ray.pojo.message.send.BaseMessage;

import com.ray.test.UserTest;
import com.ray.util.WeiXinUtil;

/**@desc  : 發送消息
 * 
 * @author: shirayner
 * @date  : 2017-8-18 上午10:06:23
 */
public class SendMessageService {
    private static Logger log = LoggerFactory.getLogger(UserTest.class);  

    private  static  String sendMessage_url="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";  

    /**
     * @desc :0.公共方法:發送消息
     *  
     * @param accessToken
     * @param message void
     */
    public void sendMessage(String accessToken,BaseMessage message){

        //1.獲取json字符串:將message對象轉換爲json字符串    
        Gson gson = new Gson(); 
        String jsonMessage =gson.toJson(message);      //使用gson.toJson(user)便可將user對象順序轉成json
        System.out.println("jsonTextMessage:"+jsonMessage);


        //2.獲取請求的url  
        String url=sendMessage_url.replace("ACCESS_TOKEN", accessToken);

        //3.調用接口,發送消息
        JSONObject jsonObject = WeiXinUtil.httpRequest(url, "POST", jsonMessage);  
        System.out.println("jsonObject:"+jsonObject.toString());

        //4.錯誤消息處理
        if (null != jsonObject) {  
            if (0 != jsonObject.getInt("errcode")) {  
                log.error("消息發送失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));  
            }  
        }  
    }
    
    
    
    
}
View Code

 

 

4.發送消息測試類——SendMessageTest

package com.ray.test;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;


import com.ray.pojo.message.send.Article;
import com.ray.pojo.message.send.FileMessage;
import com.ray.pojo.message.send.ImgMessage;
import com.ray.pojo.message.send.Media;
import com.ray.pojo.message.send.News;
import com.ray.pojo.message.send.NewsMessage;
import com.ray.pojo.message.send.Text;
import com.ray.pojo.message.send.TextMessage;
import com.ray.pojo.message.send.Textcard;
import com.ray.pojo.message.send.TextcardMessage;
import com.ray.pojo.message.send.Video;
import com.ray.pojo.message.send.VideoMessage;
import com.ray.pojo.message.send.VoiceMessage;
import com.ray.service.SendMessageService;
import com.ray.util.WeiXinParamesUtil;
import com.ray.util.WeiXinUtil;

/**@desc  : 消息推送之發送消息
 * 
 * @author: shirayner
 * @date  : 2017-8-18 上午10:04:55
 */
public class SendMessageTest {

    //1.發送文本消息
    @Test
    public void testSendTextMessage(){
        //0.設置消息內容
        String content="你的快遞已到,請攜帶工卡前往郵件中心領取。\n出發前可查看" +
                "<a href=\"http://work.weixin.qq.com\">郵件中心視頻實況" +
                "</a>,聰明避開排隊。";

        //1.建立文本消息對象
        TextMessage message=new TextMessage();
        //1.1非必需
        message.setTouser("@all");  //不區分大小寫
        //textMessage.setToparty("1");
        //txtMsg.setTotag(totag);
        //txtMsg.setSafe(0);

        //1.2必需
        message.setMsgtype("text");
        message.setAgentid(WeiXinParamesUtil.agentId);

        Text text=new Text();
        text.setContent(content);
        message.setText(text);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }

    //2.發送文本卡片消息
    @Test
    public void testSendTextcardMessage(){
        //0.設置消息內容
        String title="代辦事宜";
        String description="<div class=\"gray\">2017年8月18日</div> <div class=\"normal\">" +
                "恭喜你抽中iPhone 7一臺,領獎碼:xxxx</div><div class=\"highlight\">" +
                "請於2017年10月10日前聯繫行政同事領取</div>";
        String url="http://www.cnblogs.com/shirui/p/7297872.html";

        //1.建立文本卡片消息對象
        TextcardMessage message=new TextcardMessage();
        //1.1非必需
        message.setTouser("shirui");  //不區分大小寫
        //message.setToparty("1");
        //message.setTotag(totag);
        //message.setSafe(0);

        //1.2必需
        message.setMsgtype("textcard");
        message.setAgentid(WeiXinParamesUtil.agentId);

        Textcard textcard=new Textcard();
        textcard.setTitle(title);
        textcard.setDescription(description);
        textcard.setUrl(url);
        message.setTextcard(textcard);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }

    //3.發送圖片消息---無效的media_id
    @Test
    public void testSendImgMessage(){
        //0.設置消息內容
        String media_id="MEDIA_ID";
        //1.建立圖片消息對象
        ImgMessage message=new ImgMessage();
        //1.1非必需
        message.setTouser("@all");  //不區分大小寫
        //textMessage.setToparty("1");
        //txtMsg.setTotag(totag);
        //txtMsg.setSafe(0);

        //1.2必需
        message.setMsgtype("image");
        message.setAgentid(WeiXinParamesUtil.agentId);

        Media image=new Media();
        image.setMedia_id(media_id);
        message.setImage(image);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }


    //4.發送語音消息---無效的media_id
    @Test
    public void testSendVoiceMessage(){
        //0.設置消息內容
        String media_id="MEDIA_ID";
        //1.建立語音消息對象
        VoiceMessage message=new VoiceMessage();
        //1.1非必需
        message.setTouser("@all");  //不區分大小寫
        //textMessage.setToparty("1");
        //txtMsg.setTotag(totag);
        //txtMsg.setSafe(0);

        //1.2必需
        message.setMsgtype("image");
        message.setAgentid(WeiXinParamesUtil.agentId);

        Media voice=new Media();
        voice.setMedia_id(media_id);
        message.setVoice(voice);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }

    //5.發送視頻消息
    @Test
    public void testSendVideoMessage(){
        //0.設置消息內容
        String media_id="MEDIA_ID";
        String title="視頻示例";
        String description="好看的視頻";


        //1.建立視頻消息對象
        VideoMessage message=new VideoMessage();
        //1.1非必需
        message.setTouser("@all");  //不區分大小寫
        //message.setToparty("1");
        //message.setTotag(totag);
        //message.setSafe(0);

        //1.2必需
        message.setMsgtype("video");
        message.setAgentid(WeiXinParamesUtil.agentId);

        Video video=new Video();
        video.setMedia_id(media_id);
        video.setTitle(title);
        video.setDescription(description);
        message.setVideo(video);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }

    //6.發送文件消息
    @Test
    public void testSendFileMessage(){
        //0.設置消息內容
        String media_id="MEDIA_ID";

        //1.建立文件對象
        FileMessage message=new FileMessage();
        //1.1非必需
        message.setTouser("@all");  //不區分大小寫
        //textMessage.setToparty("1");
        //txtMsg.setTotag(totag);
        //txtMsg.setSafe(0);

        //1.2必需
        message.setMsgtype("file");
        message.setAgentid(WeiXinParamesUtil.agentId);

        Media file=new Media();
        file.setMedia_id(media_id);
        message.setFile(file);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }

    //7.發送圖文消息
    @Test
    public void testSendNewsMessage(){

        //1.建立圖文消息對象
        NewsMessage message=new NewsMessage();
        //1.1非必需
        message.setTouser("@all");  //不區分大小寫
        //textMessage.setToparty("1");
        //txtMsg.setTotag(totag);
        //txtMsg.setSafe(0);

        //1.2必需
        message.setMsgtype("news");
        message.setAgentid(WeiXinParamesUtil.agentId);
        //設置圖文消息
        Article article1=new  Article();
        article1.setTitle("青年文摘");
        article1.setDescription("這是一個很特別的描述");
        article1.setPicurl("http://mat1.gtimg.com/fashion/images/index/2017/08/18/tpzs2.jpg");
        article1.setUrl("http://www.cnblogs.com/shirui/p/7297872.html");
        
        List<Article>  articles=new ArrayList<Article>();
        articles.add(article1);
        
        News news=new News();
        news.setArticles(articles);
        message.setNews(news);

        //2.獲取access_token:根據企業id和通信錄密鑰獲取access_token,並拼接請求url
        String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken();
        System.out.println("accessToken:"+accessToken);

        //3.發送消息:調用業務類,發送消息
        SendMessageService sms=new SendMessageService();
        sms.sendMessage(accessToken, message);

    }




}
View Code
相關文章
相關標籤/搜索