微信公眾平臺 傳送訊息-群發介面
前言:最近做微信開發,弄了一個群發介面,本著不記錄肯定會忘記的本事,在這裡整理一下。多學習多進步。本文比較囉嗦,可以檢視參考文章,我就是從那位大神那裡學習到的。本片文章基於Spring開發,Spring提供的用於訪問Rest服務的客戶端。
這篇文章解決的問題:
1.上傳圖文訊息素材
2.根據openid列表群發
一、檢視相關技術文件,確定自己業務需求
我想說明一下這裡,因為本人是技術菜鳥,學習的時候檢視文件,發現會多都是直接把程式碼一貼上一複製就算OK,以前我也是這樣,後來自己再去用的時候發現根本看不懂了,所以以後整理每一篇部落格我都會很上心,把一些自己注意到的細節問題寫出了方便自己以後的使用。
1:檢視微信公眾平臺的技術文件
(1)傳送訊息-群發介面
群發訊息,我們首先要上傳訊息,再群發。按照目錄的第一點是上傳圖文訊息內的圖片獲取URL,但是第二點上傳圖文訊息素材。我們檢視上傳圖文訊息素材介面會發現,我們上傳資源的引數是thumb_media_id。如圖:
而上傳圖文訊息內的圖片獲取URL返回的是url,如圖:
所以我們這裡要使用素材管理介面
這裡有兩種素材,一種是臨時素材,一種是永久素材,區別自己檢視介面就能知道,這裡講解上傳臨時素材,畢竟永久素材上傳是有個數的。
呼叫臨時素材介面就可以返回media_id,就是我們上傳圖文訊息素材需要的thumb_media_id
現在開始正式java介面開發。
二、獲取access_token
三、新增臨時素材
1:介面呼叫請求說明
(1)請參引數
(2)java介面開發
public final class MediaType {
public static final String APPLICATION_XML = "application/xml;charset=UTF-8";
public static final String APPLICATION_JSON = "application/json;charset=UTF-8";
public static final String APPLICATION_X_WWW_F_U = "application/x-www-form-urlencoded;charset=UTF-8";
}
GroupSendMessageApi介面
package com.weixin.message.api;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.basic.protocol.MediaType;
import com.weixin.message.model.Articles;
import com.weixin.message.model.FilePathData;
import com.weixin.message.model.GroupSendResponse;
import com.weixin.message.model.MessageData;
import com.weixin.message.model.UploadResponse;
/**
* 介面名:群發訊息介面
* 建立時間:2017-05-26
* 開發者: wangql
*/
@Path("/groupSendMessage")
public interface GroupSendMessageApi {
/**
* 上傳臨時素材
* @param filePath
* @return
*/
@POST
@Path("/uploadMatter")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON })
public UploadResponse fileUpload(FilePathData filePath);
}
FilePathData請求資料
package com.weixin.message.model;
public class FilePathData {
private String filePath;//檔案路徑
private String type;//檔案型別 預設image
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
GroupSendMessageApiImpl實現類
package com.weixin.message.api.impl;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.client.RestTemplate;
import com.basic.factory.RestTemplateFactory;
import com.basic.utils.JsonUtil;
import com.basic.utils.TokenUtil;
import com.weixin.message.api.GroupSendMessageApi;
import com.weixin.message.model.Articles;
import com.weixin.message.model.FilePathData;
import com.weixin.message.model.GroupSendResponse;
import com.weixin.message.model.MessageData;
import com.weixin.message.model.UploadResponse;
/**
* 介面名:群發訊息實現類
* 建立時間:2017-05-26
* 開發者: wangqiulin
*/
public class GroupSendMessageApiImpl implements GroupSendMessageApi {
private static Log logger = LogFactory.getLog(GroupSendMessageApiImpl.class);
private RestTemplate restTemplate;
public GroupSendMessageApiImpl() {
restTemplate = RestTemplateFactory.makeRestTemplate();
}
@Override
public UploadResponse fileUpload(FilePathData filePath) {
UploadResponse response = new UploadResponse();
if(filePath != null){
String type = filePath.getType()==null?"image":filePath.getType();//檔案型別
String url = new StringBuffer("http://file.api.weixin.qq.com/cgi-bin/media/upload?access_token=")
.append(AccessToken).append("&type="+type).toString();
logger.info("檔案路徑:"+filePath.getFilePath());
GroupSendMessageApiImpl groupSendMessageApiImpl = new GroupSendMessageApiImpl();
try {
String result = groupSendMessageApiImpl.send(url, filePath.getFilePath());
logger.info(result);
if(result != null){
response = JsonUtil.jsonToObject(result, response.getClass());
}
} catch (IOException e) {
e.printStackTrace();
}
}else {
response.setErrcode(1);
response.setErrmsg("上傳圖片路徑為空");
}
return response;
}
/**
* 上傳檔案
* @param url
* @param filePath
* @return
* @throws IOException
*/
public String send(String url, String filePath) throws IOException {
String result = null;
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"); // 以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);
// 請求正文資訊
// 第一部分:
StringBuilder sb = new StringBuilder();
sb.append("--"); // 必須多兩道線
sb.append(BOUNDARY);
sb.append("\r\n");
sb.append("Content-Disposition: form-data;name=\"media\";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);
// 檔案正文部分
// 把檔案已流檔案的方式 推入到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();
StringBuffer buffer = new StringBuffer();
BufferedReader reader = null;
try {
// 定義BufferedReader輸入流來讀取URL的響應
reader = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
if (result == null) {
result = buffer.toString();
}
} catch (IOException e) {
System.out.println("傳送POST請求出現異常!" + e);
e.printStackTrace();
throw new IOException("資料讀取異常");
} finally {
if (reader != null) {
reader.close();
}
}
return result;
}
}
UploadResponse響應資料
/**
* 上傳圖文或者素材響應
* @author wangqiulin
*/
public class UploadResponse {
private int errcode;
private String errmsg;
private String type;
private String media_id;
private Long created_at;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMedia_id() {
return media_id;
}
public void setMedia_id(String media_id) {
this.media_id = media_id;
}
public Long getCreated_at() {
return created_at;
}
public void setCreated_at(Long created_at) {
this.created_at = created_at;
}
public int getErrcode() {
return errcode;
}
public void setErrcode(int errcode) {
this.errcode = errcode;
}
public String getErrmsg() {
return errmsg;
}
public void setErrmsg(String errmsg) {
this.errmsg = errmsg;
}
}
如果自己測試的話直接寫一個main方法就可以解決,使用介面主要是讓功能更加清晰。主要的核心程式碼是實現類,其他的請求和響應都是輔助存在。
(3)請求介面引數
返回引數:
請求介面:
這樣我們就生成了media_id。這個media_id就是上傳圖文訊息素材的thumb_media_id。
四、上傳圖文訊息素材
1:介面呼叫請求說明
http請求方式: POST
https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=ACCESS_TOKEN
2:引數說明
3:java介面開發
(1)Articles請求引數
package com.weixin.message.model;
public class Articles {
private Article[] articles;
public Article[] getArticles() {
return articles;
}
public void setArticles(Article[] articles) {
this.articles = articles;
}
}
package com.plateno.weixin.message.model;
public class Article {
private String title;
private String description;
private String url;
private String picurl;
private String thumb_media_id;
private String author;
private String content_source_url;
private String content;
private String digest;
private Integer show_cover_pic;
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;
}
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 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 Integer getShow_cover_pic() {
return show_cover_pic;
}
public void setShow_cover_pic(Integer show_cover_pic) {
this.show_cover_pic = show_cover_pic;
}
}
(2)uploadFile介面
package com.weixin.message.api;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.basic.protocol.MediaType;
import com.weixin.message.model.Articles;
import com.weixin.message.model.FilePathData;
import com.weixin.message.model.GroupSendResponse;
import com.weixin.message.model.MessageData;
import com.weixin.message.model.UploadResponse;
/**
* 介面名:群發訊息介面
* 建立時間:2017-05-26
* 開發者: wangqiulin
*/
@Path("/groupSendMessage")
public interface GroupSendMessageApi {
/**
* 上傳臨時素材
* @param filePath
* @return
*/
@POST
@Path("/uploadMatter")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON })
public UploadResponse fileUpload(FilePathData filePath);
/**
* 上傳圖文訊息
* @param articles
* @return
*/
@POST
@Path("/uploadFile")
@Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON })
public UploadResponse uploadFile(Articles articles);
}
(3)uploadFile實現方法
@Override
public UploadResponse uploadFile(Articles articles) {
UploadResponse response = null;
if(articles != null){
String url = new StringBuffer("https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=").append(TokenUtil.getAccessToken()).toString();
response = restTemplate.postForObject(url, articles, UploadResponse.class);
logger.info("Errcode:"+response.getErrcode());
logger.info("Errmsg:"+response.getErrmsg());
logger.info("Type:"+response.getType());
logger.info("Created_at"+response.getCreated_at());
}else {
response.setErrcode(1);
response.setErrmsg("上傳圖文訊息素材為空");
}
return response;
}
4:請求引數
引數示例:
{"articles": [{"thumb_media_id":"DphGJnvnYMeU3QGVmr8rXdb4wLn0dz96Uin4GpwFrAdjTkVmoIgs8zhKdjKGS2ML","author":"wql","title":"Happy Day","content_source_url":"www.platone.com","content":"content","digest":"digest"}]}
5:返回引數
引數示例:
{
"type":"news",
"media_id":"CsEf3ldqkAYJAU6EJeIkStVDSvffUJ54vqbThMgplD-VJXXof6ctX5fI6-aYyUiQ",
"created_at":1391857799
}
引數說明:
五、根據OpenID列表群發
1:介面呼叫請求說明
http請求方式: POST
https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN
2:POST資料說明
圖文訊息(注意圖文訊息的media_id需要通過上述方法來得到):
{
"touser":[
"OPENID1",
"OPENID2"
],
"mpnews":{
"media_id":"123dsdajkasd231jhksad"
},
"msgtype":"mpnews",
"send_ignore_reprint":0
}
3:java介面開發
(1)請求引數
package com.weixin.message.model;
public class MessageData {
private String[] touser;
private String msgtype;
private MediaContent mpnews;
private Integer send_ignore_reprint;
public String[] getTouser() {
return touser;
}
public void setTouser(String[] touser) {
this.touser = touser;
}
public String getMsgtype() {
return msgtype;
}
public void setMsgtype(String msgtype) {
this.msgtype = msgtype;
}
public MediaContent getMpnews() {
return mpnews;
}
public void setMpnews(MediaContent mpnews) {
this.mpnews = mpnews;
}
public Integer getSend_ignore_reprint() {
return send_ignore_reprint;
}
public void setSend_ignore_reprint(Integer send_ignore_reprint) {
this.send_ignore_reprint = send_ignore_reprint;
}
}
(2)sendMsg介面
/**
* 根據openid群發訊息介面
* @param message
* @return
*/
@POST
@Path("/sendMsg")
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public GroupSendResponse sendMsg(MessageData message);
(3)sendMsg實現方法
@Override
public GroupSendResponse sendMsg(MessageData message) {
GroupSendResponse response = null;
if(message != null){
String url = new StringBuffer("https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=").append(TokenUtil.getAccessToken()).toString();
response = restTemplate.postForObject(url, message, GroupSendResponse.class);
logger.info("Errcode:"+response.getErrcode());
logger.info("Errmsg:"+response.getErrmsg());
logger.info("Msg_id:"+response.getMsg_id());
logger.info("Msg_data_id:"+response.getMsg_data_id());
}else {
response.setErrcode(1);
response.setErrmsg("圖文訊息為空");
}
return response;
}
4:返回說明
(1)引數示例:
{
"errcode":0,
"errmsg":"send job submission success",
"msg_id":34182,
"msg_data_id": 206227730
}