github地址:https://github.com/tanghh0410/sendNews.git
另外一篇發送文本消息:https://blog.csdn.net/tangthh123/article/details/100181930
前言:
本篇文章我將圍繞如何實現應用發送圖片消息給用戶,
發送方:一個自建應用 接收方:企業微信用戶。
準備內容:
1.如果沒有自建應用的話,需要在企業微信管理後臺建立一個自建應用。
2.準備企業微信的公司id 和 應用的AgentID 和 AgentSecret,這些都可以在企業微信管理後臺看到。
3.在本地準備一張圖片 供上傳使用。
發送圖片功能邏輯:
點擊圖片上傳功能,將需要發送的圖片通過調用上傳文件素材接口存到企業微信服務器上,然後調用企業微信下載文件素材接口得到該圖片的media_id ,接下來就可以組裝發送圖片消息的代碼,發送請求,圖片發送成功!
準備開始:
1.TestController
package com.test.controller;
import com.test.service.WeiMessageService;
import com.test.wechat.SendApplicationMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Created by tanghh on 2019/9/1
*/
@RestController
public class TestController {
@Autowired
private WeiMessageService weiMessageService;
@GetMapping(value = "/testSendNews")
public void testSendNews(){
//1.發送文本消息
// SendApplicationMessage message = new SendApplicationMessage();
// message.testSendText();
//2.發送圖片消息
weiMessageService.sendImageMessage("D:/project/csdn/有錢.gif","image");
}
}
2.Service
package com.test.service;
/**
* @Author tanghh
* @Date 2020/6/29 15:41
*/
public interface WeiMessageService {
/**
* 發送圖片消息
* @param filePath
* @param type
*/
void sendImageMessage(String filePath,String type);
}
package com.test.service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.test.model.Image;
import com.test.model.ImageMessage;
import com.test.util.QiWeiParametersUtil;
import com.test.util.QiYeWeiUtil;
import com.test.wechat.SendRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.File;
/**
* @Author tanghh
* @Date 2020/6/29 15:41
*/
@Service
public class WeiMessageServiceImpl implements WeiMessageService {
private Logger logger = LoggerFactory.getLogger(WeiMessageServiceImpl.class);
@Override
public void sendImageMessage(String filePath, String type) {
//1.將獲取到的圖片上傳到企業微信服務器
JSONObject resultJsonObject = uploadTempMaterial(filePath,"image");
String mediaId = resultJsonObject.getString("media_id");
//將圖片發給用戶(企業微信或者是微信) 微信用戶如果在24小時之內沒有與微信公衆平臺交互,微信用戶將接收不到微信公衆號的消息
String accessToken = QiWeiParametersUtil.getAccessToken();
//2.組裝圖片消息
//2.1.創建圖片消息對象
ImageMessage sendImgMessage = new ImageMessage();
//2.2非必需 發送用戶id
sendImgMessage.setTouser("TangHuiHong");
//2.3 發送類型
sendImgMessage.setMsgtype(type);
sendImgMessage.setAgentid(QiWeiParametersUtil.agentId);
Image image = new Image();
image.setMedia_id(mediaId);
sendImgMessage.setImage(image);
//2.獲取請求的url
String sendMessage_url = QiWeiParametersUtil.sendAccessTokenUrl.replace("ACCESS_TOKEN", accessToken);
String json = JSON.toJSONString(sendImgMessage);
//3.發送消息:調用業務類,發送消息
JSONObject jsonObject = SendRequest.sendPost(sendMessage_url, json);
//4.錯誤消息處理
if (null != jsonObject) {
if (0 != jsonObject.getIntValue("errcode")) {
logger.error("發送消息失敗 errcode:{} errmsg:{}", jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
}
}
}
/**
* 企業微信上傳臨時素材
* 文件上傳並獲取上傳文件的mediaId
* type 媒體文件類型,分別有圖片(image)、語音(voice)、視頻(video),普通文件(file)
*
* @param
* @return
*/
public JSONObject uploadTempMaterial(String filePath, String type) {
//1.創建本地文件
File file = new File(filePath);
String accessToken = QiWeiParametersUtil.getAccessToken();
//2.拼接請求url
String uploadTempMaterialUrl = QiWeiParametersUtil.uploadMediaUrl.replace("ACCESS_TOKEN", accessToken)
.replace("TYPE", type);
//3.調用接口,發送請求,上傳文件到微信服務器
String result = QiYeWeiUtil.httpRequest(uploadTempMaterialUrl, file);
//4.json字符串轉對象:解析返回值,json反序列化
result = result.replaceAll("[\\\\]", "");
JSONObject resultJSON = JSONObject.parseObject(result);
//5.返回參數判斷
if (resultJSON != null) {
if (resultJSON.get("media_id") != null) {
System.out.println("上傳" + type + "永久素材成功");
return resultJSON;
} else {
System.out.println("上傳" + type + "永久素材失敗");
}
}
return resultJSON;
}
}
3.涉及的實體類
package com.test.model;
import lombok.Data;
/**
* Created by tanghh on 2019/8/30
*/
public @Data
class ImageMessage {
private String touser;
// private String toparty;
// private String totag;
private String msgtype;
private Integer agentid;
private Image image;
private Integer safe;
}
package com.test.model;
import lombok.Data;
/**
* 圖片消息
* @Author: tanghh18
* @Date: 2019/8/30 17:02
*/
public @Data
class Image {
private String media_id;
}
4.參數類
參數類中有些參數必須要替換掉 corpId agentId secret
package com.test.util;
import com.alibaba.fastjson.JSONObject;
import com.test.wechat.SendRequest;
/**
* 企業微信參數配置類
*
* @Author: tanghh18
* @Date: 2019/8/30 16:21
*/
public class QiWeiParametersUtil {
/**
* 1.獲取AccessToken
*/
public static String getAccessTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}";
/**
* 發送企業微信AccessToken
*/
public static String sendAccessTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";
/**
* 上傳臨時文件素材
* @param
* @return
*/
public static String uploadMediaUrl="https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
/**
* 企業ID
*/
public final static String corpId = "*****";
/**
* 企業應用的id,整型。可在應用的設置頁面查看(yes)項目測試(ebo0.2版本)
*/
public final static int agentId = 0;
/**
* 應用secret
*/
public static String secret = "**********riBPcYSDsA64AQ4YmOs";
/**
* 獲得各種access_token
*
* @return
*/
public static String getAccessToken() {
String url = getAccessTokenUrl.replace("{corpid}", corpId).replace("{corpsecret}", secret);
JSONObject departmentJson = SendRequest.sendGet(url);
return departmentJson.getString("access_token");
}
}
5.上傳文件素材的類。
package com.test.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author tanghh
* @Date: 2019/4/17
*/
public class QiYeWeiUtil {
private static Logger logger = LoggerFactory.getLogger(QiYeWeiUtil.class);
// 微信加密簽名
private String msg_signature;
// 時間戳
private String timestamp;
// 隨機數
private String nonce;
/**
* 1.企業微信上傳素材的請求方法
*
* @param
* @return
*/
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);
// post方式不能使用緩存
httpUrlConn.setUseCaches(false);
//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.發送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;
}
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;
}
}
6.發送請求的類
package com.test.wechat;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
/**
* 用來發送請求的類
*
* @Author: tanghh18
* @Date: 2019/8/30 16:21
*/
public class SendRequest {
/**
* 發送GET請求
*
* @param url
* @return
*/
public static JSONObject sendGet(String url) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpSession session = request.getSession();
JSONObject jsonObject = null;
StringBuffer sb = new StringBuffer();
BufferedReader in = null;
try {
String urlName = url;
URL realUrl = new URL(urlName);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 設置通用的請求屬性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
//針對羣暉NAS請求,加一個Cookie
if (session.getAttribute("sid") != null) {
conn.addRequestProperty("Cookie", "id=" + session.getAttribute("sid"));
}
conn.setConnectTimeout(10000);
// 建立實際的連接
conn.connect();
// 定義BufferedReader輸入流來讀取URL的響應
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
jsonObject = JSON.parseObject(sb.toString());
} catch (Exception e) {
System.out.println("發送GET請求出現異常!" + e);
} finally {
// 使用finally塊來關閉輸入流
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
System.out.println("關閉流異常");
}
}
return jsonObject;
}
/**
* 發送post請求(返回json)
*
* @param url
* @param param
* @return
*/
public static JSONObject sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
JSONObject jsonObject = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打開和URL之間的連接
URLConnection conn = realUrl.openConnection();
// 發送POST請求必須設置如下兩行
conn.setDoOutput(true);
conn.setDoInput(true);
// conn.addRequestProperty("Cookie", "stay_login=1 smid=DumpWzWQSaLmKlFY1PgAtURdV_u3W3beoei96zsXkdSABwjVCRrnnNBsnH1wGWI0-VIflgvMaZAfli9H2NGtJg id=EtEWf1XZRLIwk1770NZN047804");//設置獲取的cookie
// 獲取URLConnection對象對應的輸出流(設置請求編碼爲UTF-8)
out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
// 發送請求參數
out.print(param);
// flush輸出流的緩衝
out.flush();
// 獲取請求返回數據(設置返回數據編碼爲UTF-8)
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
jsonObject = JSONObject.parseObject(result);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return jsonObject;
}
}
7.其他類
package com.test.util;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
public class MyX509TrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
文章中涉及的代碼已經貼出,如果覺得小編寫的不錯的話 ,可以給小編點個贊喔 謝謝。
有什麼問題的話歡迎評論區留言。