微信公众平台 发送消息-群发接口

前言:最近做微信开发,弄了一个群发接口,本着不记录肯定会忘记的本事,在这里整理一下。多学习多进步。本文比较啰嗦,可以查看参考文章,我就是从那位大神那里学习到的。本片文章基于Spring开发,Spring提供的用于访问Rest服务的客户端。
这篇文章解决的问题:
1.上传图文消息素材
2.根据openid列表群发

官方技术文档:微信公众平台技术文档

一、查看相关技术文档,确定自己业务需求

我想说明一下这里,因为本人是技术菜鸟,学习的时候查看文档,发现会多都是直接把代码一粘贴一复制就算OK,以前我也是这样,后来自己再去用的时候发现根本看不懂了,所以以后整理每一篇博客我都会很上心,把一些自己注意到的细节问题写出了方便自己以后的使用。

1:查看微信公众平台的技术文档

微信公众平台 发送消息-群发接口_第1张图片
(1)发送消息-群发接口
群发消息,我们首先要上传消息,再群发。按照目录的第一点是上传图文消息内的图片获取URL,但是第二点上传图文消息素材。我们查看上传图文消息素材接口会发现,我们上传资源的参数是thumb_media_id。如图:
微信公众平台 发送消息-群发接口_第2张图片
上传图文消息内的图片获取URL返回的是url,如图:
微信公众平台 发送消息-群发接口_第3张图片
所以我们这里要使用素材管理接口
微信公众平台 发送消息-群发接口_第4张图片
这里有两种素材,一种是临时素材,一种是永久素材,区别自己查看接口就能知道,这里讲解上传临时素材,毕竟永久素材上传是有个数的。

调用临时素材接口就可以返回media_id,就是我们上传图文消息素材需要的thumb_media_id参数数据了。

现在开始正式java接口开发。

二、获取access_token

参考柳峰文章:
微信公众平台开发教程第22篇-如何保证access_token长期有效

三、新增临时素材

1:接口调用请求说明

(1)请参参数
微信公众平台 发送消息-群发接口_第5张图片
(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)请求接口参数
返回参数:
微信公众平台 发送消息-群发接口_第6张图片
请求接口:
微信公众平台 发送消息-群发接口_第7张图片
这样我们就生成了media_id。这个media_id就是上传图文消息素材的thumb_media_id

四、上传图文消息素材

1:接口调用请求说明

http请求方式: POST
https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=ACCESS_TOKEN

2:参数说明

微信公众平台 发送消息-群发接口_第8张图片

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:请求参数

微信公众平台 发送消息-群发接口_第9张图片

参数示例:

{"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
}

参数说明:
微信公众平台 发送消息-群发接口_第10张图片

五、根据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
}

微信公众平台 发送消息-群发接口_第11张图片

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
}

微信公众平台 发送消息-群发接口_第12张图片

参考文章

java微信开发高级接口—-群发功能

你可能感兴趣的:(微信开发,微信)