JAVA微信公众号网页开发——将文章群发到微信公众号中(文章使用富文本,包含图片)

 

SendTextToAllUserAct.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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);
    }
}

  

 

posted @   yvioo  阅读(2541)  评论(1编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示