java微信开发-消息接收和自动回复

0、前提条件

1、需要一个公众平台帐号(测试帐号也可以)
2、平台需要被人关注

1、导入jar

commons-beanutils-1.8.0.jar
commons-collections-3.1.jar
commons-lang-2.5.jar
commons-logging-1.2.jar
date4j.jar
dom4j-1.6.1.jar
dom4j-full.jar
ezmorph-1.0.6.jar
json-lib-2.3-jdk15.jar
jstl.jar
spring-aop-4.1.0.RELEASE.jar
spring-aspects-4.1.0.RELEASE.jar
spring-beans-4.1.0.RELEASE.jar
spring-context-4.1.0.RELEASE.jar
spring-context-support-4.1.0.RELEASE.jar
spring-core-4.1.0.RELEASE.jar
spring-expression-4.1.0.RELEASE.jar
spring-jdbc-4.1.0.RELEASE.jar
spring-tx-4.1.0.RELEASE.jar
spring-web-4.1.0.RELEASE.jar
spring-webmvc-4.1.0.RELEASE.jar
standard.jar
xmlbeans-2.3.0.jar
xmlpull-1.1.3.1.jar
xstream-1.4.7.jar

2、配置springMVC环境

这里不贴代码,具体代码请参考“java微信开发-springMVC配置”。

3、接收消息

处理请求

@Controller
public class HelloWorldController {

    /**
     * 微信消息接收和token验证
     * @param model
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/hello")
    public void hello(Model model, HttpServletRequest request,HttpServletResponse response) throws IOException {
        boolean isGet = request.getMethod().toLowerCase().equals("get");
        PrintWriter print;
        if (isGet) {
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 随机字符串
            String echostr = request.getParameter("echostr");
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
            if (signature != null && CheckoutUtil.checkSignature(signature, timestamp, nonce)) {
                try {
                    print = response.getWriter();
                    print.write(echostr);
                    print.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            // 进入post聊天处理
            System.out.println("enter post");
            print = response.getWriter();
            // 接收消息并返回消息
            // 调用核心服务类接收处理请求
            String respXml = CoreService.processRequest(request);
            print.print(respXml);
            print.flush();
            print.close();
        }

    }
}   

核心服务类

package com.SpringMVC.web.controller;

import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import OAuth2.OAuth;
/**
 * 核心服务类
 * 
 * @author 32950745
 *
 */
public class CoreService {
    public static String processRequest(HttpServletRequest request) {
        // xml格式的消息数据
        String respXml = null;
        // 默认返回的文本消息内容
        String respContent = "未知的消息类型";
        try {
            // 调用parseXml方法解析请求消息
            Map requestMap = MessageUtil.parseXml(request);
            // 发送方帐号
            String fromUserName = (String) requestMap.get("FromUserName");
            // 开发者微信号
            String toUserName = (String) requestMap.get("ToUserName");
            // 消息类型
            String msgType = (String) 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)) {
                respContent = "您发送的是文本消息!";
            }
            // 图片消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
                respContent = "您发送的是图片消息!";
            }
            // 语音消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
                respContent = "您发送的是语音消息!";
            }
            // 视频消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
                respContent = "您发送的是视频消息!";
            }
            // 地理位置消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
                respContent = "您发送的是地理位置消息!";
            }
            // 链接消息
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
                respContent = "您发送的是链接消息!";
            }
            // 事件推送
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件类型
                String eventType = (String) requestMap.get("Event");
                // 关注
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                    respContent = "谢谢您的关注!";
                }
                // 取消关注
                else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                    // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
                }
                // 扫描带参数二维码
                else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
                    // TODO 处理扫描带参数二维码事件
                }
                // 上报地理位置
                else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
                    // TODO 处理上报地理位置事件
                }
                // 自定义菜单
                else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
                    // TODO 处理菜单点击事件
                }
            }
            // 设置文本消息的内容
            textMessage.setContent(respContent);

            // 将文本消息对象转换成xml
            respXml = MessageUtil.textMessageToXml(textMessage);
            return respXml;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }
}

消息工具类

package com.SpringMVC.web.controller;

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;
public class MessageUtil {

    //APPID
    public static final String appID = "微信公众平台的appid";
    //appsecret
    public static final String appsecret = "微信公众平台的apsecred";

    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 String PREFIX_CDATA = "<![CDATA[";
    public static String SUFFIX_CDATA = "]]>";
    /** 
     * 扩展xstream,使其支持CDATA块 
     * 由于xstream框架本身并不支持CDATA块的生成,下面代码是对xtream做了扩展,
     * 使其支持在生成xml各元素值时添加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(PREFIX_CDATA);
                        writer.write(text);
                        writer.write(SUFFIX_CDATA);
                    } else {  
                       super.writeText(writer, text);
                    }  
                }  
            };  
        }  
    });

    /**
     * 解析微信发来的请求(xml)
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    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<Element> 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());
        //xstream.processAnnotations(textMessage.getClass());
        System.out.println(xstream.toXML(textMessage));
        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);
    }
}

所有消息基类

package com.SpringMVC.web.controller;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 消息基类(公众帐号 -> 普通用户)
 * @author 32950745
 *
 */
public class BaseMessage {
    // 接收方帐号(收到的OpenID)  
    @XStreamAlias("ToUserName")
    private String ToUserName;  
    // 开发者微信号  
    @XStreamAlias("FromUserName")
    private String FromUserName;  
    // 消息创建时间 (整型)  
    @XStreamAlias("CreateTime")
    private long CreateTime;  
    // 消息类型(text/music/news)  
    @XStreamAlias("MsgType")
    private String MsgType;  
    // 位0x0001被标志时,星标刚收到的消息  
    @XStreamAlias("FuncFlag")
    private int FuncFlag;  

    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 int getFuncFlag() {  
        return FuncFlag;  
    }  

    public void setFuncFlag(int funcFlag) {  
        FuncFlag = funcFlag;  
    }

    @Override
    public String toString() {
        return "BaseMessage [ToUserName=" + ToUserName + ", FromUserName=" + FromUserName + ", CreateTime=" + CreateTime
                + ", MsgType=" + MsgType + ", FuncFlag=" + FuncFlag + "]";
    }   
}

文本消息

package com.SpringMVC.web.controller;

import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * 消息响应之文本消息:
 * @author 32950745
 *
 */
@XStreamAlias("TextMessage")
//@XStreamAlias("xml")
public class TextMessage extends BaseMessage{
    // 回复的消息内容  
    @XStreamAlias("Content")
    private String Content;  

    public String getContent() {  
        return Content;  
    }  

    public void setContent(String content) {  
        Content = content;  
    }

    @Override
    public String toString() {
        return super.toString()+"\nTextMessage [Content=" + Content + "]";
    } 

}

音乐消息

package com.SpringMVC.web.controller;

/**
 * 回复消息之音乐消息
 * @author 32950745
 *
 */
 @XStreamAlias("MusicMessage ")
public class MusicMessage extends BaseMessage{
    // 回复的消息内容  
    private String Content;  

   @XStreamAlias("Content")
    public String getContent() {  
        return Content;  
    }  

    public void setContent(String content) {  
        Content = content;  
    }  
}

图文消息

package com.SpringMVC.web.controller;

/**
 * 回复消息之图文消息
 * @author 32950745
 *
 */
@XStreamAlias("NewsMessage ")
public class NewsMessage extends BaseMessage{
    // 回复的消息内容  
    @XStreamAlias("Content")
    private String Content;  

    public String getContent() {  
        return Content;  
    }  

    public void setContent(String content) {  
        Content = content;  
    }  
}
/**
 * 回复消息之图文消息
 * @author 32950745
 *
 */
@XStreamAlias("Article") 
public class Article extends BaseMessage{
    @XStreamAlias("Title")
    private String title = "";

    @XStreamAlias("Description")
    private String description = "";

    @XStreamAlias("PicUrl")
    private String picUrl = "";

    @XStreamAlias("Url")
    private String url = "";

    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 getPicUrl() {
        return picUrl;
    }

    public void setPicUrl(String picUrl) {
        this.picUrl = picUrl;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

token验证

package com.SpringMVC.web.controller;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 请求校验工具类
 * @author 32950745
 *
 */
public class CheckoutUtil {

    // 与接口配置信息中的Token要一致
    private static String token = "Javen";

    /**
     * 验证签名
     * 
     * @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);
        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;
    }
    public 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;
                }
            }
        }
    }
}
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值