java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)

java微信开发API解析(六)

全局说明

* 详细说明请参考前两篇文章。

本文说明

* 本文主要是对前面学习的知识进行综合整合。
* 我们对需要的bean、工具类、xml、file进行必要的包装。
* 我们构建一个可以直接使用的Java微信应用。
* 文后包含该部分效果的测试微信公众号
* 文后包含构建好的源码供下载

bean的构建

  • public class Access_token,获取Access_token对应的bean。

    private String access_token;
    private String expires_in;
    
  • public class BaseMsg,所有消息共有成员变量bean。
    private String ToUserName;
    private String FromUserName;
    private long CreateTime;
    private String MsgType;
    
  • public class TextMsg extends BaseMsg,文本消息bean。
    private String Content;
    
  • public class Group,分组所需要的成员变量bean。
    private int id;
    private String name;
    private int count;
    private String openid;
    private String to_groupid;
    private String groupid;
    

工具类的构建

  • public class AccessTokenUtils,该工具类前文已经详细说明过了,在此处没有改动。
  • public class GlobalParamsUtils,该工具类存储了全局常量,包括APPID、SECERT、token等;以及微信服务器响应的消息类型(类型较多,可以直接查看源码,不再此处列出)。
  • public class GroupUtils ,包括对分组的各种操作。除了上一篇文章所说的对用户分组,还有一个保存用户信息的两个工具方法,如下
    public class GroupUtils {
        private static final String TAG = "GroupUtils";
    
        /*
         * 该方法测试将用户移动到指定分组
         */
        public static String updateGroup(String openid, String to_groupid) {
            ...
        }
    
        public static boolean existUser(String openid) {
            try {
                BufferedReader dr = new BufferedReader(new InputStreamReader(
                        new FileInputStream(new File("user.txt"))));
                String line = dr.readLine();
                while (line != null) {
                    if (openid.equals(line))
                        return true;
                    line = dr.readLine();
                }
                dr.close();
                return false;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
        }
    
        public static boolean AddGroup(String openid) {
            try {
                File file = new File("user.txt");
                if (!file.exists())
                    file.createNewFile();
                BufferedWriter dw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(file, true)));
                dw.write(openid);
                dw.newLine();
                dw.flush();
                dw.close();
                return true;
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                return false;
            }
        }
    
        @Test
        public void Test1() {
            AddGroup("asdas");
        }
    }
    
  • public class MyHttpUtils,关于http的请求的简单封装。
  • public class SHAUtils,对sha加密的抽取。
  • public class XmlUtils ,对xml处理的工具抽取,如下
        package com.gist.utils;
    
        import java.io.InputStream;
        import java.util.HashMap;
        import java.util.List;
        import java.util.Map;
    
        import org.dom4j.Document;
        import org.dom4j.DocumentException;
        import org.dom4j.Element;
        import org.dom4j.io.SAXReader;
        import org.junit.Test;
    
        import com.gist.bean.TextMsg;
        import com.thoughtworks.xstream.XStream;
    
        /**
         * @author 高远</n>
         * 编写日期   2016-4-24下午2:28:07</n>
         * 邮箱  [email protected]</n>
         * 博客  http://blog.csdn.net/wgyscsf</n>
         * TODO</n>
         */
        public class XmlUtils {
            private static final String TAG = "XmlUtils";
    
            /*
             * 解析用户发送过来的请求。将请求的xml全部封装到map里面
             */
            public static Map<String, String> handleXmlMsg(InputStream is) {
                Map<String, String> map = new HashMap<String, String>();
                try {
                    SAXReader saxReader=new SAXReader();
                    Document document = saxReader.read(is);
                    Element root = document.getRootElement();
                    List<Element> elements = root.elements();
                    for (Element e : elements) {
                        map.put(e.getName(), e.getText());
                    }
                    elements = null;
                    root = null;
                    document = null;
                    return map;
                } catch (DocumentException e) {
                    e.printStackTrace();
                }
                return null;
            }
    
            /**
             * TODO
             */
            public static String str2Xml(TextMsg textMsg) {
                XStream xStream=new XStream();
                xStream.alias("xml", TextMsg.class);
                String xmlStr = xStream.toXML(textMsg);
                return xmlStr;
            }
            @Test
            public void Test() {
                // 我们封装一个回复文本的信息.
                TextMsg textMsg = new TextMsg();
                textMsg.setFromUserName("from");
                textMsg.setToUserName("to");
                textMsg.setMsgType(GlobalParamsUtils.MSGTYPE_TEXT);
                String content = "默认回复消息.";
                textMsg.setContent(content);
                textMsg.setCreateTime(System.currentTimeMillis());
                System.out.println(str2Xml(textMsg));
            }
        }
    

servlet的构建以及业务层service的构建

  • public class CoreServlet extends HttpServlet,该方法改动很小,其中的POST请求如下

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 特别注意,req.getInputStream()只能获取一次,并且只能读取一次。如果想要多次读取,需要另外想办法。
        // 设置编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        CoreService coreService = new CoreService();
        /*
         * 获取用户发送过来的消息
         */
        InputStream is = req.getInputStream();
    
        String reqXml = coreService.handleRequest(is);// 接收处理过之后的xml
        /*
         * 给用户回复消息
         */
        PrintWriter writer = resp.getWriter();
        writer.print(reqXml);
        writer.flush();
    }
    
  • public class CoreService,业务核心类,如下
    package com.gist.service;
    
    import java.io.InputStream;
    import java.util.Map;
    
    import com.gist.bean.TextMsg;
    import com.gist.utils.GlobalParamsUtils;
    import com.gist.utils.GroupUtils;
    import com.gist.utils.XmlUtils;
    
    /**
     * @author 高远</n>
     * 编写日期   2016-4-24下午2:10:32</n>
     * 邮箱  [email protected]</n>
     * 博客  http://blog.csdn.net/wgyscsf</n>
     * TODO</n>
     */
    public class CoreService {
        // private static final String TAG = "CoreService";
    
        public String handleRequest(InputStream is) {
            boolean flag = false;// 设置一个标记,供下面分组用
            // 用户发送过来消息是xml格式的。虽然消息类型繁多,但是格式基本固定(参看资料包中的“请求资料.txt”)。我们使用xstram对其进行xml解析。
            Map<String, String> handleXmlMsg = XmlUtils.handleXmlMsg(is);
            /*
             * 我们查看资料包中的“请求资料.txt”可以发现,所有的请求都包括以下字段
             * <ToUserName><![CDATA[toUser]]></ToUserName>
             * <FromUserName><![CDATA[fromUser]]></FromUserName>
             * <CreateTime>1348831860</CreateTime>
             * <MsgType><![CDATA[text]]></MsgType>
             * 特别的,对于关注和取消关注、自定义菜单,还有一个共有的字段“Event
             * ”,并且它们的“MsgType”内容全部都是“event”(需要仔细观察
             * )。请参考GlobalParamsUtils中关于该部分参数的设置。
             */
            /*
             * 第一步,我们先获取所有事件共有的参数
             */
            String ToUserName = handleXmlMsg.get("ToUserName");
            String FromUserName = handleXmlMsg.get("FromUserName");
            String CreateTime = handleXmlMsg.get("CreateTime");
            String MsgType = handleXmlMsg.get("MsgType");
    
            // 我们封装一个回复文本的信息.
            TextMsg textMsg = new TextMsg();
            textMsg.setFromUserName(ToUserName);
            textMsg.setToUserName(FromUserName);
            textMsg.setMsgType(GlobalParamsUtils.MSGTYPE_TEXT);
            String content = "默认回复消息.wgyscsf";
    
            // 我们在这里测试一下用户自动分组(强制选择)
    
            boolean exist = GroupUtils.existUser(FromUserName);
    
            if (!exist) {
    
                String text = handleXmlMsg.get("Content");
                if (text.equals("1")) {
    
                    content = GroupUtils.updateGroup(FromUserName, "101");
                    GroupUtils.AddGroup(FromUserName);
                } else if (text.equals("2")) {
    
                    content = GroupUtils.updateGroup(FromUserName, "102");
                    GroupUtils.AddGroup(FromUserName);
                } else {
    
                    content = "请先选择分组(选择对应数字)<\n>:1、开发人员;2、普通用户";
                }
                textMsg.setContent(content);
                textMsg.setCreateTime(System.currentTimeMillis());
                String xmlStr = XmlUtils.str2Xml(textMsg);
                return xmlStr;
            }
    
            /*
             * 第二步,根据MsgType判断用户的请求类型。两大类:普通消息、事件推送
             */
            // 推送消息
            if (MsgType.equals(GlobalParamsUtils.MSGTYPE_EVENT)) {
                // 这里面在细节判断是何种推送事件
                String EVENT = handleXmlMsg.get("Event");
    
                if (EVENT.equals(GlobalParamsUtils.EVENT_SUBSCRIBE)) {
                    // 用户关注
                    content = "欢迎您的关注。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_UNSUBSCRIBE)) {
                    // 取消关注
                    content = "取消关注。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_SCAN)) {
                    // 扫描二维码
                    content = "扫描二维码。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_LOCATION)) {
                    // 地理位置
                    content = "地理位置。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_CLICK)) {
                    // click事件
                    content = "click事件。";
                } else if (EVENT.equals(GlobalParamsUtils.EVENT_VIEW)) {
                    // view事件
                    content = "view事件。";
                }
    
            } else {
                // 普通消息
                if (MsgType.equals(GlobalParamsUtils.MSGTYPE_TEXT)) {
                    // 普通文本
                    content = "普通文本。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_IMAGE)) {
                    // 图片消息
                    content = "图片消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_VOICE)) {
                    // 语音消息
                    content = "语音消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_VIDEO)) {
                    // 视频消息
                    content = "视频消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_SHORTVIDEO)) {
                    // 小视频消息
                    content = "小视频消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_LOCATION)) {
                    // 地理位置消息
                    content = "地理位置消息。";
                } else if (MsgType.equals(GlobalParamsUtils.MSGTYPE_LINK)) {
                    // 链接消息
                    content = "链接消息。";
                }
            }
            textMsg.setContent(content);
            textMsg.setCreateTime(System.currentTimeMillis());
            String xmlStr = XmlUtils.str2Xml(textMsg);
            return xmlStr;
    
        }
    }
    

测试的微信号二维码(包含上述所说的效果)

这是平时写的一些技术文章的微信公众号,欢迎关注:

源码下载

http://download.csdn.net/detail/wgyscsf/9501213

时间: 2024-07-30 20:39:37

java微信开发API解析(六)-综合运用(消息处理、自定义菜单响应处理、用户自动分组处理;包含源码)的相关文章

java微信开发API解析(五)-用户管理

java微信开发API解析(五)-用户管理 全局说明 * 详细说明请参考前两篇文章. 本文说明 *本文分为五部分: * 工具类MyHttpUtils的封装 * 用户分组管理文档的简单阅读解析 * 分组bean的构建以及各种分组管理的实现源码 * 用户管理的应用场景 * 测试的微信号二维码 * 本文只分析用户管理的用户分组管理部分,其它都大同小异,不再分析处理.如需要,请留言. * 以后原理分析会越来越简洁,具体原理分析请查看以前文章. * 下一篇文章会对于用户普通消息.自定义菜单消息.自动完成用

java微信开发API解析(七)-网页开发-微信网页授权

java微信开发API解析(七)-网页开发-微信网页授权 全局说明 * 详细说明请参考前两篇文章. 本文说明 本文主要完成获取用户基本信息的工作,包括(昵称.头像.地址.国家等基本信息) 对于snsapi_base和snsapi_userinfo我们只演示关于snsapi_userinfo.因为snsapi_userinfo更难,如果能够理解snsapi_userinfo,那么snsapi_base不在话下. 对于该部分(微信网页开发)我们只介绍如何获取用户基本信息,对于开发样式库,js-SDK

java微信开发API解析(四)-自定义菜单以及个性化菜单实现

全局说明 * 详细说明请参考前两篇文章. 本文说明 *本文分为五部分: * 工具类AccessTokenUtils的封装 * 自定义菜单和个性化菜单文档的阅读解析 * 菜单JSON的分析以及构建对应bean * 自定义菜单的实现 * 个性化菜单的实现 * 微信自定义菜单所有类型菜单都给出演示 * 本文结束会给出包括本文前四篇文章的所有演示源码 工具类AccessTokenUtils的封装 在上文中关于AccessToken的获取和定时保存已经详细介绍过,此处直接给出处理过之后封装的AccessT

Force.com微信开发系列(六)客服接口

当用户主动发消息给微信公众账号的时候(包括发送信息.点击自定义菜单click事件.订阅事件.扫描二维码事件.支付成功事件.用户维权),微信将会把消息数据推送给开发者,开发者在一段时间内(目前为48小时)可以调用客服消息接口,通过POST一个JSON数据包来发送消息给普通用户,在48小时内不限制发送次数.此接口主要用于客服等有人工消息处理环节的功能,方便开发者提供更加优质的服务. 客服接口调用请求说明 客服接口调用的接口说明如下(http请求方式为POST),如果获取Access Token的方式

分享 Java微信开发SDK

分享 Java微信开发SDK •发布于 4周前  •作者 朋也  •432 次浏览  •最后一次编辑是 2周前  •来自 分享 给大家分享两个java开发微信公众号的sdk jfinal-weixin weixin-java-tools fastweixin 第一个是jfinal框架开发的微信开发sdk,貌似没什么文档,大家知道哪地方有文档可以在下方留言 第二个是在github上找的,fork人数也不少,文档写的挺好,基于maven方式搭建,开发起来也很方便 第三个是在osc上看到的,可以整合s

java微信开发

所谓的微信开发就是在微信开发模式之下,对微信进行公众号和企业号的扩展开发. 如果要让你的微信公众号有更多的功能,比如菜单支持,自动的信息服务,查询,消息推送等,就必须开启微信的开发模式.进入微信公众平台的管理界面,打开开发模式,配置好你的服务器即可. 使用java微信开发,就是你配置的服务器中的应用程序是使用java开发. 使用java开发微信的步骤: 1.进入微信公众平台开启开发模式. 2.搭建你自己的服务器,必须是80端口,且必须有域名. 3.寻找一个快速开发的框架,强烈推荐开源的wecha

微信开发 api 需要 https 服务器

微信开发 api 需要 https 服务器 先建一个环境,本地的 https 服务器. 以下这篇不错,很完整. https://zhuanlan.zhihu.com/p/23640321 原文地址:https://www.cnblogs.com/F4NNIU/p/9018040.html

Java微信开发_03_使用测试号进行开发

今天进行自定义菜单的开发时,发现公众号没有自定义菜单的权限.于是想到用测试号,但微信服务器如何区分你要请求的是公众号还是测试号呢. 我们可以发现不同公众号的appID和appsecre是不同的,一对appID和appsecre对应了一个微信公众号或者测试号. 于是,我们将后台代码里的appID和appsecre换成测试号的就好了. 测试号地址

[052] 微信公众平台开发视频公开课第2讲-自定义菜单开发讲解

微信公众平台开发视频公开课第2讲将为大家讲解自定义菜单的相关知识,时间是2014年5月24日20:00-22:00.本次课程的大纲如下: 1.自定义菜单简介 1)如何获得菜单权限 2)菜单按钮分类(click和view) 2.编辑模式下的菜单使用 1)创建菜单 2)预览发布 3)注意事项 3.开发模式下的菜单使用 1)菜单接口介绍 2)如何发起https请求(两种方法,IBM JDK环境) 3)获取access_token 4)如何封装菜单结构 5)创建菜单 6)处理菜单点击事件 7)菜单的查询