zoukankan      html  css  js  c++  java
  • 基于springboot微信公众号开发,几分钟学会微信自动回复

    效果图

    1.准备工作

    申请微信订阅号(个人只能申请订阅号,而且没什么功能,也无法认证),申请完毕,点击 开发=>基本配置,如下图:


    服务器配置需要有 域名 80端口,我猜你没有,这里推荐个实用工具,pagekite,下载链接,

    这个工具需要 python2.7以上环境,还有邮箱一个,一个邮箱一个月,邮箱这东西大家懂得,

    用pagekite申请完域名,就可以用自己的电脑做订阅号服务器了.

    2.服务器代码

    创建个springboot工程

    pom.xml

    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
        </parent>
    
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <!-- 使thymeleaf支持h5标签 -->
            <dependency>
                <groupId>net.sourceforge.nekohtml</groupId>
                <artifactId>nekohtml</artifactId>
                <version>1.9.22</version>
            </dependency>

        <dependency>
          <groupId>dom4j</groupId>
          <artifactId>dom4j</artifactId>
          <version>1.6.1</version>
        </dependency>

        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>

    入口类

    @SpringBootApplication
    public class WeChatApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(WeChatApplication.class, args);
            System.out.println("====启动成功====");
        }
    
    }

    application.properties,配置server.port=80

    Controller,这个是处理微信请求,get方法就是微信公众平台 服务器配置url请求的路径,post是处理用户事件

    @RestController
    public class WeChatController {
        @Autowired
        private WeChatService weChatService;
        /**
         * 处理微信服务器发来的get请求,进行签名的验证
         * 
         * signature 微信端发来的签名
         * timestamp 微信端发来的时间戳
         * nonce     微信端发来的随机字符串
         * echostr   微信端发来的验证字符串
         */
        @GetMapping(value = "wechat")
        public String validate(@RequestParam(value = "signature") String signature,
                @RequestParam(value = "timestamp") String timestamp, 
                @RequestParam(value = "nonce") String nonce,
                @RequestParam(value = "echostr") String echostr) {
            return WeChatUtil.checkSignature(signature, timestamp, nonce) ? echostr : null;
    
        }
        /**
         * 此处是处理微信服务器的消息转发的
         */
        @PostMapping(value = "wechat")
        public String processMsg(HttpServletRequest request) {
            // 调用核心服务类接收处理请求
            return weChatService.processRequest(request);        
        }
    }

    Service,处理post请求

    /**
     * 核心服务类
     */
    @Service
    public class WeChatServiceImpl implements WeChatService{
        @Autowired
        private FeignUtil feignUtil;
        @Autowired
        private RedisUtils redisUtils;
        public String processRequest(HttpServletRequest request) {
            // xml格式的消息数据
            String respXml = null;
            // 默认返回的文本消息内容
            String respContent;
            try {
                // 调用parseXml方法解析请求消息
                Map<String,String> requestMap = WeChatUtil.parseXml(request);
                 // 消息类型
                String msgType = (String) requestMap.get(WeChatContant.MsgType);
                String mes = null;
                // 文本消息
                if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_TEXT)) {
                    mes =requestMap.get(WeChatContant.Content).toString();
                    if(mes!=null&&mes.length()<2){
                        List<ArticleItem> items = new ArrayList<>();
                        ArticleItem item = new ArticleItem();
                        item.setTitle("照片墙");
                        item.setDescription("阿狸照片墙");
                        item.setPicUrl("http://changhaiwx.pagekite.me/photo-wall/a/iali11.jpg");
                        item.setUrl("http://changhaiwx.pagekite.me/page/photowall");
                        items.add(item);
                        
                        item = new ArticleItem();
                        item.setTitle("哈哈");
                        item.setDescription("一张照片");
                        item.setPicUrl("http://changhaiwx.pagekite.me/images/me.jpg");
                        item.setUrl("http://changhaiwx.pagekite.me/page/index");
                        items.add(item);
                        
                        item = new ArticleItem();
                        item.setTitle("小游戏2048");
                        item.setDescription("小游戏2048");
                        item.setPicUrl("http://changhaiwx.pagekite.me/images/2048.jpg");
                        item.setUrl("http://changhaiwx.pagekite.me/page/game2048");
                        items.add(item);
                        
                        item = new ArticleItem();
                        item.setTitle("百度");
                        item.setDescription("百度一下");
                        item.setPicUrl("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1505100912368&di=69c2ba796aa2afd9a4608e213bf695fb&imgtype=0&src=http%3A%2F%2Ftx.haiqq.com%2Fuploads%2Fallimg%2F170510%2F0634355517-9.jpg");
                        item.setUrl("http://www.baidu.com");
                        items.add(item);
                        
                        respXml = WeChatUtil.sendArticleMsg(requestMap, items);
                    }else if("我的信息".equals(mes)){
                        Map<String, String> userInfo = getUserInfo(requestMap.get(WeChatContant.FromUserName));
                        System.out.println(userInfo.toString());
                        String nickname = userInfo.get("nickname");
                        String city = userInfo.get("city");
                        String province = userInfo.get("province");
                        String country = userInfo.get("country");
                        String headimgurl = userInfo.get("headimgurl");
                        List<ArticleItem> items = new ArrayList<>();
                        ArticleItem item = new ArticleItem();
                        item.setTitle("你的信息");
                        item.setDescription("昵称:"+nickname+"  地址:"+country+" "+province+" "+city);
                        item.setPicUrl(headimgurl);
                        item.setUrl("http://www.baidu.com");
                        items.add(item);
                        
                        respXml = WeChatUtil.sendArticleMsg(requestMap, items);
                    }
                }
                // 图片消息
                else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_IMAGE)) {
                    respContent = "您发送的是图片消息!";
                    respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                }
                // 语音消息
                else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_VOICE)) {
                    respContent = "您发送的是语音消息!";
                    respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                }
                // 视频消息
                else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_VIDEO)) {
                    respContent = "您发送的是视频消息!";
                    respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                }
                // 地理位置消息
                else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_LOCATION)) {
                    respContent = "您发送的是地理位置消息!";
                    respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                }
                // 链接消息
                else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_LINK)) {
                    respContent = "您发送的是链接消息!";
                    respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                }
                // 事件推送
                else if (msgType.equals(WeChatContant.REQ_MESSAGE_TYPE_EVENT)) {
                    // 事件类型
                    String eventType = (String) requestMap.get(WeChatContant.Event);
                    // 关注
                    if (eventType.equals(WeChatContant.EVENT_TYPE_SUBSCRIBE)) {
                        respContent = "谢谢您的关注!";
                        respXml = WeChatUtil.sendTextMsg(requestMap, respContent);
                    }
                    // 取消关注
                    else if (eventType.equals(WeChatContant.EVENT_TYPE_UNSUBSCRIBE)) {
                        // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
                    }
                    // 扫描带参数二维码
                    else if (eventType.equals(WeChatContant.EVENT_TYPE_SCAN)) {
                        // TODO 处理扫描带参数二维码事件
                    }
                    // 上报地理位置
                    else if (eventType.equals(WeChatContant.EVENT_TYPE_LOCATION)) {
                        // TODO 处理上报地理位置事件
                    }
                    // 自定义菜单
                    else if (eventType.equals(WeChatContant.EVENT_TYPE_CLICK)) {
                        // TODO 处理菜单点击事件
                    }
                }
                mes = mes == null ? "不知道你在干嘛" : mes;
                if(respXml == null)
                    respXml = WeChatUtil.sendTextMsg(requestMap, mes);
                System.out.println(respXml);
                return respXml;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
            
        }
    @Override
        public String getToken() {
            String token = (String) redisUtils.get("token");
            if(token == null){
                Map<String, String> tokenMap = feignUtil.getToken((String)redisUtils.get(WeChatContant.appID), (String)redisUtils.get(WeChatContant.appsecret));
                System.out.println("token:	"+tokenMap.toString());
                token = tokenMap.get("access_token") ;
                if(token != null){
                    redisUtils.set("token", token, 7000L);
                }
                    
            }
            return token;
        }
    
        @Override
        public Map<String, String> getUserInfo(String openid) {
            // TODO Auto-generated method stub
            return feignUtil.getUserInfo(getToken(), openid);
        }
    
    
    

    }

    微信工具类(只写了回复文本消息,和图文消息,其他的都是大同小异)

    package com.wechat.util;
    
    import java.io.InputStream;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import com.wechat.bean.ArticleItem;
    
    /**
     * 请求校验工具类
     * 
     * @author 32950745
     *
     */
    public class WeChatUtil {    
    
        /**
         * 验证签名
         * 
         * @param signature
         * @param timestamp
         * @param nonce
         * @return
         */
        public static boolean checkSignature(String signature, String timestamp, String nonce) {
            String[] arr = new String[] { WeChatContant.TOKEN, timestamp, nonce };
            // 将token、timestamp、nonce三个参数进行字典序排序
            // Arrays.sort(arr);
            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
         */
        private 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;
        }
    
        private static void sort(String a[]) {
            for (int i = 0; i < a.length - 1; i++) {
                for (int j = i + 1; j < a.length; j++) {
                    if (a[j].compareTo(a[i]) < 0) {
                        String temp = a[i];
                        a[i] = a[j];
                        a[j] = temp;
                    }
                }
            }
        }
    
        /**
         * 解析微信发来的请求(xml)
         * 
         * @param request
         * @return
         * @throws Exception
         */
        @SuppressWarnings({ "unchecked"})
        public static Map<String,String> parseXml(HttpServletRequest request) throws Exception {
            // 将解析结果存储在HashMap中
            Map<String,String> map = new HashMap<String,String>();
    
            // 从request中取得输入流
            InputStream inputStream = request.getInputStream();
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
            // 遍历所有子节点
            for (Element e : elementList)
                map.put(e.getName(), e.getText());
    
            // 释放资源
            inputStream.close();
            inputStream = null;
            return map;
        }
    
        public static String mapToXML(Map map) {
            StringBuffer sb = new StringBuffer();
            sb.append("<xml>");
            mapToXML2(map, sb);
            sb.append("</xml>");
            try {
                return sb.toString();
            } catch (Exception e) {
            }
            return null;
        }
    
        private static void mapToXML2(Map map, StringBuffer sb) {
            Set set = map.keySet();
            for (Iterator it = set.iterator(); it.hasNext();) {
                String key = (String) it.next();
                Object value = map.get(key);
                if (null == value)
                    value = "";
                if (value.getClass().getName().equals("java.util.ArrayList")) {
                    ArrayList list = (ArrayList) map.get(key);
                    sb.append("<" + key + ">");
                    for (int i = 0; i < list.size(); i++) {
                        HashMap hm = (HashMap) list.get(i);
                        mapToXML2(hm, sb);
                    }
                    sb.append("</" + key + ">");
    
                } else {
                    if (value instanceof HashMap) {
                        sb.append("<" + key + ">");
                        mapToXML2((HashMap) value, sb);
                        sb.append("</" + key + ">");
                    } else {
                        sb.append("<" + key + "><![CDATA[" + value + "]]></" + key + ">");
                    }
    
                }
    
            }
        }
        /**
         * 回复文本消息
         * @param requestMap
         * @param content
         * @return
         */
         public static String sendTextMsg(Map<String,String> requestMap,String content){
            
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("ToUserName", requestMap.get(WeChatContant.FromUserName));
            map.put("FromUserName",  requestMap.get(WeChatContant.ToUserName));
            map.put("MsgType", WeChatContant.RESP_MESSAGE_TYPE_TEXT);
            map.put("CreateTime", new Date().getTime());
            map.put("Content", content);
            return  mapToXML(map);
        }
         /**
          * 回复图文消息
          * @param requestMap
          * @param items
          * @return
          */
        public static String sendArticleMsg(Map<String,String> requestMap,List<ArticleItem> items){
            if(items == null || items.size()<1){
                return "";
            }
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("ToUserName", requestMap.get(WeChatContant.FromUserName));
            map.put("FromUserName", requestMap.get(WeChatContant.ToUserName));
            map.put("MsgType", "news");
            map.put("CreateTime", new Date().getTime());
            List<Map<String,Object>> Articles=new ArrayList<Map<String,Object>>();  
            for(ArticleItem itembean : items){
                Map<String,Object> item=new HashMap<String, Object>();
                Map<String,Object> itemContent=new HashMap<String, Object>();
                itemContent.put("Title", itembean.getTitle());
                itemContent.put("Description", itembean.getDescription());
                itemContent.put("PicUrl", itembean.getPicUrl());
                itemContent.put("Url", itembean.getUrl());
                item.put("item",itemContent);
                Articles.add(item);
            }
            map.put("Articles", Articles);
            map.put("ArticleCount", Articles.size());
            return mapToXML(map);
        }
        
    }
    View Code

    微信常量

    public class WeChatContant {
         //APPID
        public static final String appID = "appid";
        //appsecret
        public static final String appsecret = "appsecret";
        // Token
        public static final String TOKEN = "zch";
        public static final String RESP_MESSAGE_TYPE_TEXT = "text";
        public static final Object REQ_MESSAGE_TYPE_TEXT = "text";
        public static final Object REQ_MESSAGE_TYPE_IMAGE = "image";
        public static final Object REQ_MESSAGE_TYPE_VOICE = "voice";
        public static final Object REQ_MESSAGE_TYPE_VIDEO = "video";
        public static final Object REQ_MESSAGE_TYPE_LOCATION = "location";
        public static final Object REQ_MESSAGE_TYPE_LINK = "link";
        public static final Object REQ_MESSAGE_TYPE_EVENT = "event";
        public static final Object EVENT_TYPE_SUBSCRIBE = "SUBSCRIBE";
        public static final Object EVENT_TYPE_UNSUBSCRIBE = "UNSUBSCRIBE";
        public static final Object EVENT_TYPE_SCAN = "SCAN";
        public static final Object EVENT_TYPE_LOCATION = "LOCATION";
        public static final Object EVENT_TYPE_CLICK = "CLICK";
        
        public static final String FromUserName = "FromUserName";
        public static final String ToUserName = "ToUserName";
        public static final String MsgType = "MsgType";
        public static final String Content = "Content";
        public static final String Event = "Event";
        
    }

    图文消息实体bean

    public class ArticleItem {
        private String Title;
        private String Description;
        private String PicUrl;
        private String Url;
        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 getPicUrl() {
            return PicUrl;
        }
        public void setPicUrl(String picUrl) {
            PicUrl = picUrl;
        }
        public String getUrl() {
            return Url;
        }
        public void setUrl(String url) {
            Url = url;
        }
        
    }
    View Code

    好了运行项目,在公众平台配置好url,个人订阅号完成.

     项目github https://github.com/zhangchanghai/wechat.git (本项目属于闲暇时 自学的写的 DEMO, 仅用于参考)

  • 相关阅读:
    ab 性能测试工具的使用(Web并发测试)
    java 读取文件——按照行取出(使用BufferedReader和一次将数据保存到内存两种实现方式)
    java 判断两个时间相差的天数
    java 正则表达式的应用:读取文件,获取其中的电话号码
    mybatis 插入数据时返回主键
    CodeForces 493B Vasya and Wrestling 【模拟】
    图像边缘检測小结
    【JS设计模式】温习简单工厂模式、工厂方法模式、抽象工厂模式概念
    60.自己定义View练习(五)高仿小米时钟
    bzoj4361 isn
  • 原文地址:https://www.cnblogs.com/changhai/p/8289808.html
Copyright © 2011-2022 走看看