微信開發者模式實現圖文訊息傳送
阿新 • • 發佈:2018-12-12
公眾號型別
測試號
測試號現在僅支援使用預覽介面,並不能實現群發。
實現
基於springboot
前端是自己根據圖文訊息(Article)的格式設計的,Article的內容如下:
【圖片來源:官方文件截圖】
1. 上傳內容圖片獲取URL
【圖片來源:官方文件截圖】
前端使用bootstrap-fileinput上傳圖片,傳到後臺獲取URL,然後將URL作為圖片連結,放入wangEditor編輯器中。
(此處僅提供圖片素材上傳功能,暫未考慮視訊、音訊素材)
【注意:通過獲取的微信伺服器的URL插入編輯器時,可能會出現”未經允許“的圖案,只需在當前html中加入
<meta name="referrer" content="never">
即可】
後臺程式碼如下:
@PostMapping(value = "/wx/upload/img") @ResponseBody public String uploadImg(MultipartFile img) throws IOException { JsonResult res = ResultUtil.success(); String url = wxService.postImg(img); if (null != url) { res.setData(url); } else { res = ResultUtil.error(ResultEnum.UPLOAD_IMG_FAILURE); } return res.toString(); } /** * 上傳圖文資訊圖片 * * @param img 圖片 * @return url */ @Override @Nullable public String postImg(MultipartFile img) throws IOException { // 儲存到本地,獲取本地圖片絕對路徑 String filePath = FileUtil.saveFile("TEMP", img, "TEMP_"+DataUtil.getTimeStringSixBit()+DataUtil.getRandom(6)+".jpg"); JSONObject res = doPostForm(UPLOAD_IMG_URL.replace("ACCESS_TOKEN", wxTokenHelper.getToken().getToken()), filePath); return res.getString("url"); } /** * POST請求 - Form格式資料 * * @param url 請求地址 * @param filePath 檔案本地路徑 * @return */ public JSONObject doPostForm(String url, String filePath) throws IOException { File file = new File(filePath); if (!file.exists() || !file.isFile()) { throw new IOException("檔案不存在"); } URL urlObj = new URL(url); // 連線 HttpURLConnection con = (HttpURLConnection) urlObj.openConnection(); con.setRequestMethod("POST"); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // 設定請求頭資訊 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); // 設定邊界 String BOUNDARY = "----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); String sb = "--" + BOUNDARY + "\r\n" + "Content-Disposition: form-data;name=\"file\";filename=\"" + file.getName() + "\"\r\n" + "Content-Type:application/octet-stream\r\n\r\n"; byte[] head = sb.getBytes("utf-8"); // 獲得輸出流 OutputStream out = new DataOutputStream(con.getOutputStream()); // 輸出表頭 out.write(head); // 檔案正文部分 // 把檔案已流檔案的方式 推入到url中 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(); StringBuilder buffer = new StringBuilder(); BufferedReader reader = null; String result = null; try { // 定義BufferedReader輸入流來讀取URL的響應 reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { buffer.append(line); } result = buffer.toString(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { reader.close(); } } return JSONObject.parseObject(result); }
2. 上傳圖文訊息素材,得到media_id
【圖片來源:官方文件截圖】
/** * 上傳圖文訊息素材 * * @param articles 圖文訊息集合 * @return media_id */ @Override @Nullable public String postNews(Article[] articles) { JSONObject data = new JSONObject(); data.put("articles", articles); JSONObject res = doPostStr(UPLOAD_NEWS_URL.replace("ACCESS_TOKEN", wxTokenHelper.getToken().getToken()), data.toJSONString()); return res.getString("media_id"); } /** * POST請求 - JSON格式資料 * * @param url * @param outStr * @return */ public JSONObject doPostStr(String url, String outStr) { HttpHeaders headers = new HttpHeaders(); headers.set("Content-Type", "application/json;charset=UTF-8");// 解決請求亂碼問題 String response = restTemplate.postForEntity(url, new HttpEntity<String>(outStr, headers), String.class) .getBody(); return JSON.parseObject(response); } /** * @author kingsong * @create 2018/9/26 9:00 * @desc 圖文訊息【推送】實體類 **/ public class Article { private String thumb_media_id; // 圖文訊息縮圖media_id private String author; // 圖文訊息作者 private String title; // 圖文訊息標題 private String content_source_url; // “閱讀原文”連結,受安全限制,如需跳轉Appstore,可以使用itun.es或appsto.re的短鏈服務,並在短鏈後增加 #wechat_redirect 字尾。 private String content; // 訊息內容,支援HTML標籤 private String digest; // 推送描述,如本欄位為空,則預設抓去正文的前64個字 private int show_cover_pic; // 是否顯示封面 public String getThumb_media_id() { return thumb_media_id; } public void setThumb_media_id(String thumb_media_id) { this.thumb_media_id = thumb_media_id; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent_source_url() { return content_source_url; } public void setContent_source_url(String content_source_url) { this.content_source_url = content_source_url; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getDigest() { return digest; } public void setDigest(String digest) { this.digest = digest; } public int getShow_cover_pic() { return show_cover_pic; } public void setShow_cover_pic(int show_cover_pic) { this.show_cover_pic = show_cover_pic; } }
3. 傳送圖文訊息
測試號目前僅支援預覽介面
【圖片來源:官方文件截圖】
後臺程式碼如下:
@PostMapping(value = "/wx/send/new")
@ResponseBody
public String sendNew(String media_id) throws Exception {
JsonResult res = ResultUtil.success();
res.setData(wxService.sendNewsByOpenIds(userService.getAllOpenIds(), media_id));
return res.toString();
}
/**
* 根OpenID群發圖文訊息
*
* @param openIds OpenID集合
* @param media_id 圖文訊息媒體編號
* @return msg_id
* @throws Exception 傳送失敗
*/
@Override
public String sendNewsByOpenIds(List<String> openIds, String media_id) throws Exception {
JSONObject data = new JSONObject();
// 預覽介面僅支援一個openID
data.put("touser", openIds.get(0));
Map<String, String> npnews = new HashMap<>();
npnews.put("media_id", media_id);
data.put("mpnews", npnews);
data.put("msgtype", "mpnews");
data.put("send_ignore_reprint", 0);
JSONObject res = doPostStr(SEND_NEWS_URL.replace("ACCESS_TOKEN", wxTokenHelper.getToken().getToken()), data.toJSONString());
if(0!=res.getIntValue("errcode")) {
// 傳送失敗
throw new CustomException(ResultEnum.SEND_NEWS_FAILURE);
} else {
return res.getString("msg_id");
}
}