微信生态中关注、点击等各种微信消息处理的后端服务实现WxMpMessageRouter

微信生态中关于消息处理的后端服务实现

业务场景
  • 在微信公众号中,用户点击菜单、给公众号发消息、关注公众号等事件,微信都会将消息通过接口传给后台服务器,后台服务经过处理返回给微信,微信对应展示。
  • 用户关注微信公众号,公众号自动回复用户“欢迎关注”此类的话术。还有用户对话框中输入消息,公众号自动回复对应话术这种场景
技术实现
  • 使用binarywang的微信SDK,开源SDK,公司连不上GitHub,放个gitee的地址吧 https://gitee.com/binary

  • 定义一个管理类,实现ApplicationRunner,项目启动后执行run方法,将微信的相关配置进行初始化。这时候会将微信消息处理的handler初始化到消息处理路由中。SDK中关于微信消息路由器的描述如下:

    微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理

    说明:

      1. 配置路由规则时要按照从细到粗的原则,否则消息可能会被提前处理
      2. 默认情况下消息只会被处理一次,除非使用 WxMpMessageRouterRule.next()
      3. 规则的结束必须用WxMpMessageRouterRule.end()或者WxMpMessageRouterRule.next(),否则不会生效
    

    路由器中可以放置对应的handler和拦截器进行消息的处理,拦截器在项目中没有实际应用,这里不再赘述。

    微信消息拦截器,可以用来做验证

    public interface WxMpMessageInterceptor {
    
      /**
       * 拦截微信消息
       *
       * @param wxMessage
       * @param context        上下文,如果handler或interceptor之间有信息要传递,可以用这个
       * @param wxMpService
       * @param sessionManager
       * @return true代表OK,false代表不OK
       */
      boolean intercept(WxMpXmlMessage wxMessage,
                        Map<String, Object> context,
                        WxMpService wxMpService,
                        WxSessionManager sessionManager) throws WxErrorException;
    
    }
    
  • WxMpMessageHandler,SDK中定义的处理微信推送消息的处理器接口。项目中定义一个抽象类,实现WxMpMessageHandler接口,在实现handle的方法逻辑中再定义一个抽象方法。再分别定义各个实际处理的handler继承这个抽象类,重写抽象类中定义的抽象方法,这个抽象方法,是实际业务逻辑中处理消息的方法。

    public interface WxMpMessageHandler {
    
      /**
       * 处理微信推送消息.
       *
       * @param wxMessage      微信推送消息
       * @param context        上下文,如果handler或interceptor之间有信息要传递,可以用这个
       * @param wxMpService    服务类
       * @param sessionManager session管理器
       * @return xml格式的消息,如果在异步规则里处理的话,可以返回null
       * @throws WxErrorException 异常
       */
      WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
                               Map<String, Object> context,
                               WxMpService wxMpService,
                               WxSessionManager sessionManager) throws WxErrorException;
    
    }
    
    
    
    
  • 在微信管理类执行run方法时,定义一个微信消息路由器WxMpMessageRouter,将自定义的handler和拦截器放进路由器中进行初始化。类似如下写法:

    final WxMpMessageRouter wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
    wxMpMessageRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE).handler(wxmpSubscribeHandler).interceptor(wxmpMessageInterceptorImpl).end();
    
实际执行逻辑
微信调用服务器接口

类似的请求报文体如下,还有签名、nonce、时间戳等参数

<xml>
<ToUserName><![CDATA[gh_28ba13224381]]></ToUserName
<FromUserName><![CDATA[微信公众号的openid]]></FromUserName> 	<CreateTime>1657779555</CreateTime>
<MsgType><![CDATA[text]]></MsgTyp
<Content><![CDATA[你好]]></Content
<MsgId>23733694539373153</MsgId
 </xml>
验签并初始化消息

使用开源SDK中的方法,WxMpService.checkSignature()进行验签。

接着用WxMpXmlMessage 将xml报文转换成消息实体进行处理

WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);

消息处理
  • 初始化的微信消息,放进微信消息路由器中进行处理。WxmpManager.getWxmpMessageRouter(appId).route(wxMessage);
  • 遍历获取到的router,与传进去的微信消息实体进行匹配,比如msgtype、event等,详见WxMpMessageRouterRule中的test方法。
  • 匹配到WxMpMessageRouterRule之后,执行rule.service方法并返回,这里也可以设置成异步的处理,异步处理只是开启一个新线程,new runnable,里面执行rule.service,外面executorService.submit,同时一个list接收返回。
  • 在service方法中,先执行拦截器的逻辑,而后交给handler处理,返回执行结果。对应的每个handler在初始化路由器的时候已经放进去了,所以可以找到对应具体的handler执行逻辑。具体handler类似WxmpMenuHandler(微信公众号菜单事件handler)中只重写了具体的逻辑,所以handler中的hand方法还是要在父类WxmpAbstractMessageHandler中执行。
  • 这里应该是用到了策略模式吧,大体是每个类型的消息通过条件匹配出来一个对应的执行路由,执行路由再通过初始化时的intercepter和handler,进行实际的逻辑处理,表现在controller中只需要将消息传给微信消息路由器并接收返回值即可。用着确实很方便,且如果需要新增事件类型处理的handler时,只需要写一个对应的handler并且微信消息路由器初始化时放进去即可。
项目中用到的消息路由
  • 客服会话
  • 自定义菜单
  • 点击菜单连接
  • 关注事件
  • 取关事件
  • 上报地理位置事件
  • 接收地理位置事件
  • 扫码事件
  • 默认
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值