2.4)接收微信服务器发来的消息


当你验证服务器有消息成功后,微信服务器就会把你的公众号任何事件和消息,以post请求推送到你验证的那个url地址上。

所以,把DemoServlet.java的doPost方法完善一下,并创建一个简单的WxMessageHandler。

  • 创建类DemoHandler.java 实现 WxMessageHandler接口
/**
 * 示例:DemoHandler
 * 目的:返回用户 “恭喜你猜对了”
 * @author antgan
 * @date 2016/12/15
 *
 */
public class DemoHandler implements WxMessageHandler{

    @Override
    public WxXmlOutMessage handle(WxXmlMessage wxMessage, Map<String, Object> context, IService iService)
            throws WxErrorException {
        //必须以build()作为结尾,否则不生效。
        WxXmlOutMessage xmlOutMsg = WxXmlOutMessage.TEXT().content("恭喜你猜对了").toUser(wxMessage.getFromUserName()).fromUser(wxMessage.getToUserName()).build();
        return xmlOutMsg;
    }

}
  • 完善doPost方法,这里示例是判断了消息的加密模式,如果是明文模式,可以不用加解密消息。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        // 返回消息给微信服务器
        PrintWriter out = response.getWriter();
        // 获取encrypt_type 消息加解密方式标识
        String encrypt_type = request.getParameter("encrypt_type");
        // 创建一个路由器
        WxMessageRouter router = new WxMessageRouter(iService);
        try {
            // 判断消息加解密方式,如果是加密模式。encrypt_type==aes
            if (encrypt_type != null && "aes".equals(encrypt_type)) {
//                String signature = request.getParameter("signature");
                String timestamp = request.getParameter("timestamp");
                String nonce = request.getParameter("nonce");
                String msg_signature = request.getParameter("msg_signature");

                // 微信服务器推送过来的加密消息是XML格式。使用WxXmlMessage中的decryptMsg()解密得到明文。
                WxXmlMessage wx = WxXmlMessage.decryptMsg(request.getInputStream(), WxConfig.getInstance(), timestamp,
                        nonce, msg_signature);
                System.out.println("消息:\n " + wx.toString());
                // 添加规则;这里的规则是指所有消息都交给交给DemoHandler处理
                // 注意!!每一个规则,必须由end()或者next()结束。不然不会生效。
                // end()是指消息进入该规则后不再进入其他规则。 而next()是指消息进入了一个规则后,如果满足其他规则也能进入,处理。
                router.rule().handler(new DemoHandler()).end();
                // 把消息传递给路由器进行处理,得到最后一个handler处理的结果
                WxXmlOutMessage xmlOutMsg = router.route(wx);
                if (xmlOutMsg != null) {
                    // 将要返回的消息加密,返回
                    out.print(WxXmlOutMessage.encryptMsg(WxConfig.getInstance(), xmlOutMsg.toXml(), timestamp, nonce));// 返回给用户。
                }
            //如果是明文模式,执行以下语句
            } else {
                // 微信服务器推送过来的是XML格式。
                WxXmlMessage wx = XStreamTransformer.fromXml(WxXmlMessage.class, request.getInputStream());
                System.out.println("消息:\n " + wx.toString());
                // 添加规则;这里的规则是指所有消息都交给DemoHandler处理
                // 注意!!每一个规则,必须由end()或者next()结束。不然不会生效。
                // end()是指消息进入该规则后不再进入其他规则。 而next()是指消息进入了一个规则后,如果满足其他规则也能进入,处理。
                router.rule().handler(new DemoHandler()).end();
                // 把消息传递给路由器进行处理
                WxXmlOutMessage xmlOutMsg = router.route(wx);
                if (xmlOutMsg != null)
                    out.print(xmlOutMsg.toXml());// 因为是明文,所以不用加密,直接返回给用户。
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            out.close();
        }

这样子写的效果就是:公众号后台接收所有类型的消息,都交给DemoHandler处理器处理,最后返回了一句“恭喜你猜对了”给用户。

是不是很简单?

看到这里你已经入门了。

接下来加入匹配器Matcher和Interceptor拦截器来处理更加复杂的业务。

results matching ""

    No results matching ""