Java微信公众号之消息的接收和响应二

本文介绍如何处理微信公众号发送的消息,包括消息格式解析、文本消息处理及响应消息生成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

技术文档

在校验的时候 微信公众平台向我们发送的是Get的请求,而后接收消息的时候,发送的是Post请求,并且消息的发送和接收和发送都是xml格式,现在看看格式:

文本消息格式

<xml>  
    <ToUserName>< ![CDATA[toUser] ]></ToUserName> 
    <FromUserName>< ![CDATA[fromUser] ]></FromUserName>           
    <CreateTime>1348831860</CreateTime> 
    <MsgType>< ![CDATA[text] ]></MsgType> 
    <Content>< ![CDATA[this is a test] ]></Content>    
    <MsgId>1234567890123456</MsgId>  
    </xml>

图片消息格式

<xml> 
       <ToUserName>< ![CDATA[toUser] ]></ToUserName> 
       <FromUserName>< !   [CDATA[fromUser] ]></FromUserName>    
       <CreateTime>1348831860</CreateTime> 
       <MsgType>< ![CDATA[image] ]></MsgType> 
       <MediaId>< ![CDATA[media_id] ]></MediaId> 
       <MsgId>1234567890123456</MsgId> 
</xml>

这里写图片描述

知道了消息的格式,现在我们要做的就是消息的转化

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

借助dom4j的jar包,我们可以编写方法,将XML格式,转化对Map对象格式,方法实现如下:

public class MessgaeUtils {

       /*将xml格式转化为map*/
        public Map<String,String> xmlToMap(HttpServletRequest request) throws Exception{
           Map<String,String> map=new HashMap<>();

            SAXReader reader=new SAXReader();
            InputStream inputStream=request.getInputStream();
            Document doc=reader.read(inputStream);
            Element root=doc.getRootElement();//得到根节点
            List<Element> list=root.elements();//根节点下的所有的节点
            for(Element e:list){
                map.put(e.getName(),e.getText());
            }

            inputStream.close();
            return  map;
        }
}

消息是实体类:

  private String ToUserName;

    private String FromUserName;

    private Long CreateTime;

    private String MsgType;

    private String Content;

    private String MsgId;

还需要xstream jar将我们的消息内容转变为xml

<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4</version>
</dependency>

方法:

/*将我们的消息内容转变为xml*/

        public static String objectToXml(Message message){
            XStream xStream=new XStream();
            xStream.alias("xml", message.getClass());
            return xStream.toXML(message);
        }

post方法逻辑:

 @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        response.setCharacterEncoding("UTF-8");

        PrintWriter out = response.getWriter();

        String str = null;



//将request请求,传到Message工具类的转换方法中,返回接收到的Map对象
           try {
               Map<String, String> map = MessgaeUtils.xmlToMap(request);



//从集合中,获取XML各个节点的内容

            String ToUserName = map.get("ToUserName");

            String FromUserName = map.get("FromUserName");

            String CreateTime = map.get("CreateTime");

            String MsgType = map.get("MsgType");

            String Content = map.get("Content");

            String MsgId = map.get("MsgId");
            //这里只处理文本消息
            if (MsgType.equalsIgnoreCase("text")){

                Message message=new Message();
                message.setFromUserName(ToUserName);
                message.setToUserName(FromUserName);
                message.setContent("您发送的消息是text文本消息"+"很帅");
                message.setMsgId(MsgId);
                message.setMsgType("text");
                message.setCreateTime(new Date().getTime());

                str=MessgaeUtils.objectToXml(message);
            }

             System.out.println(str);

        }catch (Exception e){
               e.printStackTrace();
           }
           out.print(str);
           out.close();
    }

结果:
这里写图片描述

对应的url以及token

这里写图片描述
参考:
http://www.cnblogs.com/jerehedu/p/6534110.html

完整代码

pom.xml

<dependencies>


    <!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6</version>
    </dependency>

    <dependency>
      <groupId>com.thoughtworks.xstream</groupId>
      <artifactId>xstream</artifactId>
      <version>1.4</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>

    </dependency>

    <!--创建Servlet-->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>


    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <!--//<scope>provided</scope>-->
    </dependency>

  </dependencies>

servlet

public class WeiXinServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");

        response.setCharacterEncoding("UTF-8");

        PrintWriter out = response.getWriter();

        String str = null;



//将request请求,传到Message工具类的转换方法中,返回接收到的Map对象
           try {
               Map<String, String> map = MessgaeUtils.xmlToMap(request);



//从集合中,获取XML各个节点的内容

            String ToUserName = map.get("ToUserName");

            String FromUserName = map.get("FromUserName");

            String CreateTime = map.get("CreateTime");

            String MsgType = map.get("MsgType");

            String Content = map.get("Content");

            String MsgId = map.get("MsgId");
            //这里只处理文本消息
            if (MsgType.equalsIgnoreCase("text")){

                Message message=new Message();
                message.setFromUserName(ToUserName);
                message.setToUserName(FromUserName);
                message.setContent("您发送的消息是text文本消息"+"很帅");
                message.setMsgId(MsgId);
                message.setMsgType("text");
                message.setCreateTime(new Date().getTime());

                str=MessgaeUtils.objectToXml(message);
            }

             System.out.println(str);

        }catch (Exception e){
               e.printStackTrace();
           }
           out.print(str);
           out.close();
    }

     @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{

        System.out.println(request.getMethod().toString());
        while (request.getAttributeNames().hasMoreElements()){
            System.out.println("1");
            request.getAttributeNames().nextElement();
        }
        // 微信加密签名
        String signature = request.getParameter("signature");

        // 时间戳
        String timestamp = request.getParameter("timestamp");

        // 随机数
        String nonce = request.getParameter("nonce");


        // 随机字符串  由于我使用的是申请的测试账号,并没有随机字符串随意这里的ech是null
        String ech = request.getParameter("echostr");

        PrintWriter out = response.getWriter();

        if (CheckUtil.checkSignature(signature,timestamp,nonce))
             System.out.println("校验成功");

              out.print(ech);

           }

    }

web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app
        version="3.0"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">


     <servlet>
       <servlet-name>bb</servlet-name>
       <servlet-class>yiche.com.servlet.WeiXinServlet</servlet-class>
     </servlet>
    <servlet-mapping>
      <servlet-name>bb</servlet-name>
      <url-pattern>/ok.do</url-pattern>
    </servlet-mapping>
</web-app>

文本消息


public class Message {


    private String ToUserName;

    private String FromUserName;

    private Long CreateTime;

    private String MsgType;

    private String Content;

    private String MsgId;

消息转化工具类

public class MessgaeUtils {


       /*将xml格式转化为map*/
        public static Map<String,String> xmlToMap(HttpServletRequest request) throws Exception{
           Map<String,String> map=new HashMap<>();

            SAXReader reader=new SAXReader();
            InputStream inputStream=request.getInputStream();
            Document doc=reader.read(inputStream);
            Element root=doc.getRootElement();//得到根节点
            List<Element> list=root.elements();//根节点下的所有的节点
            for(Element e:list){
                map.put(e.getName(),e.getText());
            }

            inputStream.close();
            return  map;
        }

        /*将我们的消息内容转变为xml*/

        public static String objectToXml(Message message){
            XStream xStream=new XStream();
            xStream.alias("xml", message.getClass());
            return xStream.toXML(message);
        }
}

doGet方法校验以及加密工具类

public class CheckUtil {

    public static final String tooken = "jkjkjkhk"; //开发者自行定义Tooken


    //signatrue微信公众平台传过来的的经过加密的签名
    public static boolean checkSignature(String signature, String timestamp, String nonce) {

//1.定义数组存放tooken,timestamp,nonce

        String[] arr = {tooken, timestamp, nonce};

//2.对数组进行排序

        Arrays.sort(arr);

//3.生成字符串

        StringBuffer sb = new StringBuffer();

        for (String s : arr) {

            sb.append(s);

        }

//4.sha1加密,网上均有现成代码

        String temp = getSha1(sb.toString());

//5.将加密后的字符串,与微信传来的加密签名比较,返回结果

        return temp.equals(signature);
    }



    public static String getSha1(String str){

        if(str==null||str.length()==0){

            return null;

        }

        char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',

                'a','b','c','d','e','f'};

        try {

            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");

            mdTemp.update(str.getBytes("UTF-8"));



            byte[] md = mdTemp.digest();

            int j = md.length;

            char buf[] = new char[j*2];

            int k = 0;

            for (int i = 0; i < j; i++) {

                byte byte0 = md[i];

                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];

                buf[k++] = hexDigits[byte0 & 0xf];

            }

            return new String(buf);

        } catch (Exception e) {

            // TODO: handle exception

            return null;

        }

    }


}
### 实现Java微信公众号消息提醒功能 #### 接口调用服务端配置教程 为了实现微信公众号消息提醒功能,在服务端需要完成对接收到的信息进行处理并作出响应。由于微信服务器通过HTTPS POST送XML数据给开者填写的URL,因此需设置一个HTTP(S)接口来接收这些POST求。 对于Java项目而言,可以利用Servlet或其他Web框架(如Spring Boot)创建相应的API endpoint用于监听来自微信公众平台的数据推送[^1]。 当接收消息时,应先验证消息签名的安全性以确认其确实来源于微信官方;之后解析传入的XML字符串获取具体字段值,再依据业务逻辑执行相应操作——比如向指定用户回复自动文本或是触某些内部流程通知相关人员注意新消息的到来。 下面是一个简单的例子展示如何构建这样的Servlet: ```java import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; @WebServlet("/wechatCallback") public class WeChatMessageHandler extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { StringBuilder sb = new StringBuilder(); String line; try (BufferedReader reader = request.getReader()) { while ((line = reader.readLine()) != null) { sb.append(line); } } // 这里sb.toString() 就是从微信服务器接收到的原始 XML 数据 // 验证消息合法性... // 解析XML... // 处理业务逻辑... // 返回响应给微信服务器 response.getWriter().write("success"); } } ``` 上述代码片段展示了基本结构,实际应用中还需要加入更多细节处理,例如安全校验、错误捕捉以及更复杂的业务规则等。 另外值得注意的是,如果希望使用更加现代化的方式来进行开,则推荐考虑采用Spring Boot搭建RESTful API的形式替代传统的Servlet编程模式。这不仅能够简化很多配置工作量,而且更容易与其他微服务体系集成在一起。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值