1. 程式人生 > >微信公眾平臺 傳送訊息-群發介面

微信公眾平臺 傳送訊息-群發介面

前言:最近做微信開發,弄了一個群發介面,本著不記錄肯定會忘記的本事,在這裡整理一下。多學習多進步。本文比較囉嗦,可以檢視參考文章,我就是從那位大神那裡學習到的。本片文章基於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
}

這裡寫圖片描述

參考文章