微信公众号开发消息推送以及图文推送

今天给大家分享的关注公众号自动推送图文消息,以及做一个超牛逼的机器人。

先看看效果。

发错图了。。。这是我昨天开发的一款机器人chu了会骂人啥都不会了。

我今天将它词库进行了更新和升级,接入了http://www.itpk.cn/   机器人第三词库
先给你截图:

机器人的配置:

微信公众号开发消息推送以及图文推送_第1张图片

词库信息。可以自定义词库信息

微信公众号开发消息推送以及图文推送_第2张图片

来看看进一步效果

是不是乖巧多了哈哈哈。

想不想把这个乖巧机器人带走。。。。

来吧 给你们秀一波操作。看好了xiongder们别眨眼我要开始变形了。。。
不好意思忘了一件灰常重要的事情,忘了给你们看官方API文档了

点我快速进入官方API文档,反正我最讨厌看这玩意。。。。

第一步登录微信公众平台 现在开发-基本配置然后服务器配置。如下图

微信公众号开发消息推送以及图文推送_第3张图片

解释含义:
服务器地址(URL):服务器接收消息的的地址也就自己后台处理逻辑的地方
Toke:需要配置到代码中。可以理解为密码 
消息加解密密钥(EncodingAESKey) 就是防止别人截取你的消息,可以选择加密 我用的明文模式

来吧走个流程图吧。哈哈哈哈。。

微信公众号开发消息推送以及图文推送_第4张图片

直接上代码。我代码上的注释很清晰。我就不多解释了。有什么不明白随时联系我。。

/**
     * 微信消息推送的验证。
     * 
     * @param request
     * @param response
     */
    @RequestMapping(value = "sendMsg", method = RequestMethod.GET, produces = "text/html;charset=UTF-8")
    public void sendMsgget(HttpServletRequest request, HttpServletResponse response) { // 微信加密签名
        String signature = request.getParameter("signature");
        // 时间戳
        String timestamp = request.getParameter("timestamp");
        // 随机数
        String nonce = request.getParameter("nonce");
        // 随机字符串
        String echostr = request.getParameter("echostr");

        PrintWriter out = null;
        try {
            out = response.getWriter();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            out.print(echostr);
        }
        out.close();
        out = null;
    }

    package cn.cnbuilder.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;


public class SignUtil {
    // 与接口配置信息中的Token要一致 需要登录微信公众号

    private static String token = "xxxxxxxxxxx";

    /**
     * 验证签名
     * 
     * @param signature
     * @param timestamp
     * @param nonce
     * @return
     */
    public static boolean checkSignature(String signature, String timestamp, String nonce) {
        String[] arr = new String[] { token, timestamp, nonce };
        // 将token、timestamp、nonce三个参数进行字典序排序
        Arrays.sort(arr);
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

    /**
     * 将字节数组转换为十六进制字符串
     * 
     * @param byteArray
     * @return
     */
    static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将字节转换为十六进制字符串
     * 
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];

        String s = new String(tempArr);
        return s;
    }
}

验签验完了之后,我们开始接受消息然后处理逻辑。
微信公众号开发消息推送以及图文推送_第5张图片


/**
     * 处理业务逻辑
     * 
     * @param request
     * @param response
     */
    @RequestMapping(value = "sendMsg", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
    public void sendMsgPost(HttpServletRequest request, HttpServletResponse response) { // 调用核心业务类接收消息、处理消息

        try {
            String respMessage = processRequest(request);
            System.err.println(respMessage);
            // 我们这里处理的是utf-8 微信要的是ios8859-1这是坑啊。。。。。
            byte[] uMessage = respMessage.getBytes("UTF-8");// 编码:字符串变成字节数组 输入 参数(编码表)
            String iMessage = new String(uMessage, "ISO8859-1");// 解码:字节数组变成字符串,String参数(数组,编码表) 输出
            if (respMessage != null) {
                // 响应消息
                PrintWriter out = response.getWriter();
                out.print(iMessage);
                out.close();
            }
        } catch (

        Exception e) {
            // 也许大概不会走到这里除非异常了。。。。。。
        }

    }

    public String processRequest(HttpServletRequest request) {
        String respMessage = null;
        try {
            // xml请求解析
            Map requestMap = MessageUtil.parseXml(request);

            // 发送方帐号(open_id)
            String fromUserName = requestMap.get("FromUserName");

            // 公众帐号
            String toUserName = requestMap.get("ToUserName");
            // 消息类型
            String msgType = requestMap.get("MsgType");

            TextMessage textMessage = new TextMessage();
            textMessage.setToUserName(fromUserName);
            textMessage.setFromUserName(toUserName);
            textMessage.setCreateTime(new Date().getTime());
            textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

            // 文本消息
            if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
                // 接收用户发送的文本消息内容
                String content = requestMap.get("Content");
                System.err.println(content);

                // 创建图文消息
                NewsMessage newsMessage = new NewsMessage();
                newsMessage.setToUserName(fromUserName);
                newsMessage.setFromUserName(toUserName);
                newsMessage.setCreateTime(new Date().getTime());
                newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);

                List
articleList = new ArrayList
(); // 单图文消息 if ("yifan".equals(content)) { Article article = new Article(); article.setTitle("欢迎关注KingYiFan's Blog"); article.setDescription("点击进入详情"); article.setPicUrl( "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1521808337402&di=515fdc032be051f5085c3f9c03af5646&imgtype=0&src=http%3A%2F%2Fwww.vvfeng.com%2Fdata%2Fupload%2Fueditor%2F20170327%2F58d8c88855d9f.jpg"); article.setUrl("http://cnbuilder.cn/"); articleList.add(article); // 设置图文消息个数 newsMessage.setArticleCount(articleList.size()); // 设置图文消息包含的图文集合 newsMessage.setArticles(articleList); // 将图文消息对象转换成xml字符串 respMessage = MessageUtil.newsMessageToXml(newsMessage); } else { // 机器人api String jiqiren = HttpClientUtils.sendGetUtF8("http://i.itpk.cn/api.php", "limit=2&api_key=xxxxx&api_secret=xxxx&type=json&question=" + content); textMessage.setContent(jiqiren); respMessage = MessageUtil.textMessageToXml(textMessage); } // 事件处理开始 } else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) { NewsMessage newsMessage = new NewsMessage(); newsMessage.setToUserName(fromUserName); newsMessage.setFromUserName(toUserName); newsMessage.setCreateTime(new Date().getTime()); newsMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS); // 事件类型 String eventType = requestMap.get("Event"); List
articleList = new ArrayList
(); if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { Article article = new Article(); article.setTitle("欢迎关注KingYiFan's Blog"); article.setDescription("点击进入详情"); article.setPicUrl( "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1521808337402&di=515fdc032be051f5085c3f9c03af5646&imgtype=0&src=http%3A%2F%2Fwww.vvfeng.com%2Fdata%2Fupload%2Fueditor%2F20170327%2F58d8c88855d9f.jpg"); article.setUrl("http://cnbuilder.cn/"); articleList.add(article); // 设置图文消息个数 newsMessage.setArticleCount(articleList.size()); // 设置图文消息包含的图文集合 newsMessage.setArticles(articleList); // 将图文消息对象转换成xml字符串 respMessage = MessageUtil.newsMessageToXml(newsMessage); try { // 保存用户信息 wxMsgService.savaWxInfo(fromUserName); } catch (Exception e) { return respMessage; } } } else if (msgType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { // 取消关注,用户接受不到我们发送的消息了,可以在这里记录用户取消关注的日志信息 } } catch (Exception e) { e.printStackTrace(); } return respMessage; } package cn.cnbuilder.utils; import java.io.InputStream; import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.core.util.QuickWriter; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; import com.thoughtworks.xstream.io.xml.XppDriver; import cn.cnbuilder.entity.wx.sendMsg.Article; import cn.cnbuilder.entity.wx.sendMsg.MusicMessage; import cn.cnbuilder.entity.wx.sendMsg.NewsMessage; import cn.cnbuilder.entity.wx.sendMsg.TextMessage; public class MessageUtil { /** * 返回消息类型:文本 */ public static final String RESP_MESSAGE_TYPE_TEXT = "text"; /** * 返回消息类型:音乐 */ public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; /** * 返回消息类型:图文 */ public static final String RESP_MESSAGE_TYPE_NEWS = "news"; /** * 请求消息类型:文本 */ public static final String REQ_MESSAGE_TYPE_TEXT = "text"; /** * 请求消息类型:图片 */ public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; /** * 请求消息类型:链接 */ public static final String REQ_MESSAGE_TYPE_LINK = "link"; /** * 请求消息类型:地理位置 */ public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; /** * 请求消息类型:音频 */ public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; /** * 请求消息类型:推送 */ public static final String REQ_MESSAGE_TYPE_EVENT = "event"; /** * 事件类型:subscribe(订阅) */ public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; /** * 事件类型:unsubscribe(取消订阅) */ public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; /** * 事件类型:CLICK(自定义菜单点击事件) */ public static final String EVENT_TYPE_CLICK = "CLICK"; /** * 解析微信发来的请求(XML) * * @param request * @return * @throws Exception */ @SuppressWarnings("unchecked") public static Map parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map map = new HashMap(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) map.put(e.getName(), e.getText()); // 释放资源 inputStream.close(); inputStream = null; return map; } /** * 文本消息对象转换成xml * * @param textMessage 文本消息对象 * @return xml */ public static String textMessageToXml(TextMessage textMessage) { xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * 音乐消息对象转换成xml * * @param musicMessage 音乐消息对象 * @return xml */ public static String musicMessageToXml(MusicMessage musicMessage) { xstream.alias("xml", musicMessage.getClass()); return xstream.toXML(musicMessage); } /** * 图文消息对象转换成xml * * @param newsMessage 图文消息对象 * @return xml */ public static String newsMessageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } /** * 扩展xstream,使其支持CDATA块 * * @date 2013-05-19 */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有xml节点的转换都增加CDATA标记 boolean cdata = true; @SuppressWarnings("unchecked") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write(""); } else { writer.write(text); } } }; } }); } package cn.cnbuilder.entity.wx.sendMsg; public class TextMessage extends BaseMessage { // 消息内容 private String Content; public String getContent() { return Content; } public void setContent(String content) { Content = content; } } package cn.cnbuilder.entity.wx.sendMsg; import java.util.List; public class NewsMessage extends BaseMessage{ // 图文消息个数,限制为10条以内 private int ArticleCount; // 多条图文消息信息,默认第一个item为大图 private List
Articles; public int getArticleCount() { return ArticleCount; } public void setArticleCount(int articleCount) { ArticleCount = articleCount; } public List
getArticles() { return Articles; } public void setArticles(List
articles) { Articles = articles; } } package cn.cnbuilder.entity.wx.sendMsg; public class Article { // 图文消息名称 private String Title; // 图文消息描述 private String Description; // 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80,限制图片链接的域名需要与开发者填写的基本资料中的Url一致 private String PicUrl; // 点击图文消息跳转链接 private String Url; public String getTitle() { return Title; } public void setTitle(String title) { Title = title; } public String getDescription() { return null == Description ? "" : Description; } public void setDescription(String description) { Description = description; } public String getPicUrl() { return null == PicUrl ? "" : PicUrl; } public void setPicUrl(String picUrl) { PicUrl = picUrl; } public String getUrl() { return null == Url ? "" : Url; } public void setUrl(String url) { Url = url; } } package cn.cnbuilder.entity.wx.sendMsg; public class BaseMessage { // 开发者微信号 private String ToUserName; // 发送方帐号(一个OpenID) private String FromUserName; // 消息创建时间 (整型) private long CreateTime; // 消息类型(text/image/location/link) private String MsgType; // 消息id,64位整型 private long MsgId; public String getToUserName() { return ToUserName; } public void setToUserName(String toUserName) { ToUserName = toUserName; } public String getFromUserName() { return FromUserName; } public void setFromUserName(String fromUserName) { FromUserName = fromUserName; } public long getCreateTime() { return CreateTime; } public void setCreateTime(long createTime) { CreateTime = createTime; } public String getMsgType() { return MsgType; } public void setMsgType(String msgType) { MsgType = msgType; } public long getMsgId() { return MsgId; } public void setMsgId(long msgId) { MsgId = msgId; } } package cn.cnbuilder.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; import org.apache.http.HttpResponse; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import net.sf.json.JSONObject; public class HttpClientUtils { /** * 向指定URL发送GET方法的请求 * * @param url 发送请求的URL * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "gbk")); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定URL发送GET方法的请求 * * @param url 发送请求的URL * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGetUtF8(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } /** * 向指定 URL 发送POST方法的请求 * * @param url 发送请求的 URL * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(param); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输出流、输入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; } public static String doPostForJson(String url, String jsonParams) { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(180 * 1000) .setConnectionRequestTimeout(180 * 1000).setSocketTimeout(180 * 1000).setRedirectsEnabled(true).build(); httpPost.setConfig(requestConfig); httpPost.setHeader("Content-Type", "application/json"); // try { httpPost.setEntity(new StringEntity(jsonParams, ContentType.create("application/json", "utf-8"))); System.out.println("request parameters" + EntityUtils.toString(httpPost.getEntity())); HttpResponse response = httpClient.execute(httpPost); String str = EntityUtils.toString(response.getEntity()); /** 把json字符串转换成json对象 **/ JSONObject fromObject = JSONObject.fromObject(str); return fromObject.toString(); } catch (Exception e) { e.printStackTrace(); return "KingYiFan温馨提示你:post请求出异常了" + e.getMessage().toString(); } finally { if (null != httpClient) { try { httpClient.close(); } catch (IOException e) { e.printStackTrace(); } } } } } package cn.cnbuilder.entity.wx.sendMsg; public class Music { // 音乐名称 private String Title; // 音乐描述 private String Description; // 音乐链接 private String MusicUrl; // 高质量音乐链接,WIFI环境优先使用该链接播放音乐 private String HQMusicUrl; public String getTitle() { return Title; } public void setTitle(String title) { Title = title; } public String getDescription() { return Description; } public void setDescription(String description) { Description = description; } public String getMusicU package cn.cnbuilder.entity.wx.sendMsg; public class MusicMessage { // 音乐 private Music Music; public Music getMusic() { return Music; } public void setMusic(Music music) { Music = music; } } rl() { return MusicUrl; } public void setMusicUrl(String musicUrl) { MusicUrl = musicUrl; } public String getHQMusicUrl() { return HQMusicUrl; } public void setHQMusicUrl(String musicUrl) { HQMusicUrl = musicUrl; } } package cn.cnbuilder.entity.wx.sendMsg; public class MusicMessage { // 音乐 private Music Music; public Music getMusic() { return Music; } public void setMusic(Music music) { Music = music; } }

这就是微信公众平台消息回复的教程,哪里不懂可以私信我哦!


鼓励作者写出更好的技术文档,就请我喝一瓶哇哈哈哈哈哈哈哈。。
微信:
微信公众号开发消息推送以及图文推送_第6张图片
支付宝:
微信公众号开发消息推送以及图文推送_第7张图片


感谢一路支持我的人。。。。。
Love me and hold me
QQ:69673804(16年老号)
EMAIL:[email protected]
友链交换
如果有兴趣和本博客交换友链的话,请按照下面的格式在评论区进行评论,我会尽快添加上你的链接。


网站名称:KingYiFan’S Blog
网站地址:http://blog.cnbuilder.cn
网站描述:年少是你未醒的梦话,风华是燃烬的彼岸花。
网站Logo/头像:头像地址

你可能感兴趣的:(技术,猿码优创)