SendTextToAllUserAct.java
package com.weixin.sendmessage; import org.apache.commons.lang.StringUtils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.json.JSONException; import org.json.JSONObject; import org.springframework.web.bind.annotation.RequestMapping; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.net.URI; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 控制器 */ public class SendTextToAllUserAct { /** * 群发文章微信 * * @param ids 内容id * @return */ @RequestMapping("/content/o_sendToWeixin.do") public String sendToWeixin(Integer[] ids) { Content[] beans = new Content[ids.length]; for (int i = 0; i < ids.length; i++) { beans[i] = contentMng.findById(ids[i]); //查询所有要发送的内容 } sendTextToAllUser(beans); return null; } /** * 群发 */ public void sendTextToAllUser(Content[] beans) { String access_token = getToken(); //上传内容到微信 /** * 上传图文消息素材 * 官方接口文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Batch_Sends_and_Originality_Checks.html#%E4%B8%8A%E4%BC%A0%E5%9B%BE%E6%96%87%E6%B6%88%E6%81%AF%E7%B4%A0%E6%9D%90%E3%80%90%E8%AE%A2%E9%98%85%E5%8F%B7%E4%B8%8E%E6%9C%8D%E5%8A%A1%E5%8F%B7%E8%AE%A4%E8%AF%81%E5%90%8E%E5%9D%87%E5%8F%AF%E7%94%A8%E3%80%91 */ String articalUploadUrl = "https://api.weixin.qq.com/cgi-bin/media/uploadnews"; String url = articalUploadUrl + "?access_token=" + access_token; String[] str = articalUpload(access_token, beans); Integer contentCount = 0; contentCount = Integer.parseInt(str[1]); if (contentCount > 0) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); HttpPost post = new HttpPost(url); try { System.out.println("str[0]:" + str[0]); StringEntity s = new StringEntity(str[0], "utf-8"); s.setContentType("application/json"); post.setEntity(s); HttpResponse res = client.execute(post); HttpEntity entity = res.getEntity(); String contentString = EntityUtils.toString(entity, "utf-8"); System.out.println("contentString:" + contentString); JSONObject json = new JSONObject(contentString); //输出返回消息 String media_id = ""; media_id = json.getString("media_id"); if (StringUtils.isNotBlank(media_id)) { /** *图文消息群发 * 官方接口文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Batch_Sends_and_Originality_Checks.html */ String sendAllMessageUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall"; String url_send = sendAllMessageUrl + "?access_token=" + token; String str_send = "{\"filter\":{\"is_to_all\":true},\"mpnews\":{\"media_id\":\"" + media_id + "\"},\"msgtype\":\"mpnews\"}"; post(url_send, str_send, "application/json"); } } catch (Exception e) { e.printStackTrace(); } } } private String post(String url, String json, String contentType) { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); HttpPost post = new HttpPost(url); try { StringEntity s = new StringEntity(json, "utf-8"); if (StringUtils.isBlank(contentType)) { s.setContentType("application/json"); } s.setContentType(contentType); post.setEntity(s); HttpResponse res = client.execute(post); HttpEntity entity = res.getEntity(); String str = EntityUtils.toString(entity, "utf-8"); return str; } catch (Exception e) { e.printStackTrace(); } return null; } /** * @param token * @param beans * @return */ private String[] articalUpload(String token, Content[] beans) { Integer count = 0; String str = "{\"articles\":["; for (int i = 0; i < beans.length; i++) { //将富文本图片先上传到微信服务器上 String txt = contentHtmlProc(token, beans[i].getHtml()); String mediaId = ""; if (!StringUtils.isBlank("文章类型图")) { String typeImg = "文章类型图"; mediaId = uploadFile(token, typeImg, "image"); System.out.println("typeImg:" + typeImg); str = str + "{" + "\"thumb_media_id\":\"" + mediaId + "\"," + "\"author\":\"" + beans[i].getAuthor() + "\"," + "\"title\":\"" + beans[i].getTitle() + "\"," + "\"content_source_url\":\"" + beans[i].getSourceUrl() + "\"," + "\"content\":\"" + txt + "\"," + "\"digest\":\"" + beans[i].getDescription() + "\"," + "\"show_cover_pic\":\"0\"" + "}"; if (i != beans.length - 1) { str = str + ","; } count++; } } str = str + "]}"; String[] result = new String[2]; result[0] = str; result[1] = count.toString(); return result; } /** * 把内容中的图片先上传到微信服务器 * * @param access_token 微信的access_token * @param txt 富文本内容 html代码 * @return */ private String contentHtmlProc(String access_token, String txt) { if (StringUtils.isBlank(txt)) { return ""; } //从富文本的html中提取img图片路径 List<String> imgUrls = getImageSrc(txt); for (String img : imgUrls) { //img路径为图片的绝对路径 //上传图片到微信 String imgRealUrl = uploadImg(access_token, img); if (StringUtils.isNotBlank(imgRealUrl)) { txt = txt.replace(img, imgRealUrl); } } //html标签双引号需要注意 txt = txt.replaceAll("\"", "\'"); return txt; } /** * 文件上传到微信服务器 * 官方接口文档:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html * * @param access_token * @param filePath 文件路径 ,绝对地址 * @param type 文件类型 * @return */ public String uploadFile(String access_token, String filePath, String type) { String sendGetUrl = "https://api.weixin.qq.com/cgi-bin/media/upload"; String url = sendGetUrl + "?access_token=" + access_token; String result = null; String mediaId = ""; FileUpload fileUpload = new FileUpload(); try { result = fileUpload.uploadFile(url, filePath, type); System.out.println("result:" + result); if (result.startsWith("{") && result.contains("media_id")) { JSONObject json = new JSONObject(result); mediaId = json.getString("media_id"); } } catch (Exception e) { e.printStackTrace(); } return mediaId; } /** * 把本地图片先上传到服务器 ,上传图文消息内的图片获取URL * 官网接口地址 :https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html * * @param access_token * @param filePath 图片路径 * @return */ private String uploadImg(String access_token, String filePath) { String sendGetUrl = "https://api.weixin.qq.com/cgi-bin/media/uploadimg"; String url = sendGetUrl + "?access_token=" + access_token; String result = null; String mediaId = ""; FileUpload fileUpload = new FileUpload(); try { result = fileUpload.uploadFile(url, filePath, null); if (result.startsWith("{")) { JSONObject json = new JSONObject(result); mediaId = json.getString("url"); } } catch (Exception e) { e.printStackTrace(); } return mediaId; } /** * 提取img图片路径 * * @param htmlCode html代码 * @return */ public static List<String> getImageSrc(String htmlCode) { List<String> imageSrcList = new ArrayList<String>(); String regular = "<img(.*?)src=\"(.*?)\""; String img_pre = "(?i)<img(.*?)src=\""; String img_sub = "\""; Pattern p = Pattern.compile(regular, Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(htmlCode); String src = null; while (m.find()) { src = m.group(); src = src.replaceAll(img_pre, "").replaceAll(img_sub, "").trim(); imageSrcList.add(src); } return imageSrcList; } /** * 获取access_token * * @return */ public String getToken() { String tokenGetUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";//微信提供获取access_token接口地址 String appid = ""; String secret = ""; System.out.println("~~~~~appid:" + appid); System.out.println("~~~~~secret:" + secret); JSONObject tokenJson = new JSONObject(); if (StringUtils.isNotBlank(appid) && StringUtils.isNotBlank(secret)) { tokenGetUrl += "&appid=" + appid + "&secret=" + secret; tokenJson = getUrlResponse(tokenGetUrl); System.out.println("~~~~~tokenJson:" + tokenJson.toString()); try { return (String) tokenJson.get("access_token"); } catch (JSONException e) { System.out.println("报错了"); return null; } } else { System.out.println("appid和secret为空"); return null; } } private JSONObject getUrlResponse(String url) { CharsetHandler handler = new CharsetHandler("UTF-8"); try { HttpGet httpget = new HttpGet(new URI(url)); HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); //HttpClient CloseableHttpClient client = httpClientBuilder.build(); client = (CloseableHttpClient) wrapClient(client); return new JSONObject(client.execute(httpget, handler)); } catch (Exception e) { e.printStackTrace(); return null; } } private static HttpClient wrapClient(HttpClient base) { try { SSLContext ctx = SSLContext.getInstance("TLSv1"); X509TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; ctx.init(null, new TrustManager[]{tm}, null); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); return httpclient; } catch (Exception ex) { return null; } } private class CharsetHandler implements ResponseHandler<String> { private String charset; public CharsetHandler(String charset) { this.charset = charset; } public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() >= 300) { throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); } HttpEntity entity = response.getEntity(); if (entity != null) { if (!StringUtils.isBlank(charset)) { return EntityUtils.toString(entity, charset); } else { return EntityUtils.toString(entity); } } else { return null; } } } }
Content.java
package com.weixin.sendmessage; /** * 内容实体类 */ public class Content { private Integer id; private String author; private String html; private String title; private String description; private String sourceUrl; public String getSourceUrl() { return sourceUrl; } public void setSourceUrl(String sourceUrl) { this.sourceUrl = sourceUrl; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getHtml() { return html; } public void setHtml(String html) { this.html = html; } 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; } }
FileUpload.java
package com.weixin.sendmessage; import org.apache.commons.lang.StringUtils; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; public class FileUpload { /** * 模拟form表单的形式 ,上传文件 以输出流的形式把文件写入到url中,然后用输入流来获取url的响应 * * @param url 请求地址 form表单url地址 * @param filePath 文件在服务器保存路径 * @return String 正确上传返回media_id * @throws IOException */ /** 微信上传文件接口 */ public String uploadFile(String url, String filePath, String type) throws Exception { File file = new File(filePath); String result = null; if (!file.exists() || !file.isFile()) { return "文件路径错误"; } /** * 第一部分 */ if(StringUtils.isNotBlank(type)){ url = url+"&type="+type; } URL urlObj = new URL(url); HttpURLConnection con = null; //解决HTTPS trustAllHttpsCertificates(); HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String urlHostName, SSLSession session) { System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost()); return true; } }; HttpsURLConnection.setDefaultHostnameVerifier(hv); con=(HttpURLConnection) urlObj.openConnection(); /** * 设置关键值 */ con.setRequestMethod("POST"); // 以Post方式提交表单,默认get方式 con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // post方式不能使用缓存 // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); // 设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); con.setRequestProperty("content-type", "multipart/form-data; boundary=" + BOUNDARY); //con.setRequestProperty("Content-Type", "multipart/mixed; boundary=" + BOUNDARY); //con.setRequestProperty("content-type", "text/html"); // 请求正文信息 // 第一部分: StringBuilder sb = new StringBuilder(); sb.append("--"); // ////////必须多两道线 sb.append(BOUNDARY); sb.append("\r\n"); sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n"); sb.append("Content-Type:application/octet-stream\r\n\r\n"); byte[] head = sb.toString().getBytes("utf-8"); // 获得输出流 OutputStream out = new DataOutputStream(con.getOutputStream()); out.write(head); // 文件正文部分 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); // 结尾部分 byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线 out.write(foot); out.flush(); out.close(); /** * 读取服务器响应,必须读取,否则提交不成功 */ // con.getResponseCode(); /** * 下面的方式读取也是可以的 */ try { // 定义BufferedReader输入流来读取URL的响应 StringBuffer buffer = new StringBuffer(); BufferedReader reader = new BufferedReader(new InputStreamReader( con.getInputStream(),"UTF-8")); String line = null; while ((line = reader.readLine()) != null) { //System.out.println(line); buffer.append(line); } if(result==null){ result = buffer.toString(); } return buffer.toString(); } catch (Exception e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } return result; } private static void trustAllHttpsCertificates() throws Exception { javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; javax.net.ssl.TrustManager tm = new miTM(); trustAllCerts[0] = tm; javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext .getInstance("SSL"); sc.init(null, trustAllCerts, null); HttpsURLConnection.setDefaultSSLSocketFactory(sc .getSocketFactory()); } static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public boolean isServerTrusted( java.security.cert.X509Certificate[] certs) { return true; } public boolean isClientTrusted( java.security.cert.X509Certificate[] certs) { return true; } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException { return; } } public static void main(String[] args) throws Exception { String filePath = "d:/mv1.jpg"; String token="Jdr_B5dQzbWlmmTAlMxbpOZiUfe100laWKeNjRgqfYAJ2GkgCdbQCQO4gAA6e0qd7uYM8fhhzx9ehQBCHlQvKQ"; String result = null; FileUpload fileUpload = new FileUpload(); result = fileUpload.uploadFile(token, filePath, "image"); System.out.println(result); } }