美文网首页
使用Vert.x开发微信框架

使用Vert.x开发微信框架

作者: 22790fe4fb44 | 来源:发表于2017-03-06 17:46 被阅读0次

背景

现在用java开发微信公众号等功能,虽然说已经有了一些成熟的框架,但都是Servlet相关的,缺少采用Vert.x框架的。Vert.x的特点是,在消息机制(event bus)的基础上,支持采用多种语言进行开发,包括但不限于java, node.js和scala等。我们希望,开发一个基于Vert.x的框架,可以方便微信平台的开发,同时利用消息机制,让多种语言可以复用这种基础能力,快速接入微信平台。阅读这篇文章,需要你对Vert.x的event bus机制有所了解。

现有的微信通信机制

我们首先对微信现有的通信机制做一个简单的了解。在下面的描述里,WechatServer(W.S.)指的是微信服务器, Server(S.)指的是开发者接入微信的服务器。

W.S.发消息给S.以及S.的回复

W.S.通过接口URL,即开发者填写的URL,通过Post请求,将消息推送到S。这些消息的类型,有用户点击了菜单,用户发送了消息等,消息是用XML定义的。同时S.可以通过在回复中携带消息,作为对此的回复。

W.S. ==(Post 接口URL with XML Body)==> S.
    <========(XML Body)=====

一个文本消息的定义如下:

<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>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[CLICK]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>

回复的消息定义和上面的类似。

S.发送请求给W.S.

S.在对菜单进行操作的时候,以及群发消息的时候,是通过Post/Get请求到W.S.对应的各自业务接口,会携带JSON定义的内容,来完成请求。W.S.以JSON返回结果。

S. ==(Post/Get 业务URL with JSON Body)==> W.S.
    <========(JSON Body)============

自定义菜单创建接口的示例:

http请求方式:POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

 {
    "button":[
    {   
        "type":"click",
        "name":"今日歌曲",
        "key":"V1001_TODAY_MUSIC"
    },
    {
        "name":"菜单",
        "sub_button":[
        {   
            "type":"view",
            "name":"搜索",
            "url":"http://www.soso.com/"
            },
            {
            "type":"view",
            "name":"视频",
            "url":"http://v.qq.com/"
            },
            {
            "type":"click",
            "name":"赞一下我们",
            "key":"V1001_GOOD"
            }]
    }]
}

回复:
{"errcode":0,"errmsg":"ok"}

自定义菜单查询接口的示例:

http请求方式:GET
https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN

回复:
{
    "menu": {
        "button": [
            {
                "type": "click", 
                "name": "今日歌曲", 
                "key": "V1001_TODAY_MUSIC", 
                "sub_button": [ ]
            }
        ], 
        "menuid": 208396938
    }, 
    "conditionalmenu": [
        {
            "button": [
                {
                    "type": "click", 
                    "name": "今日歌曲", 
                    "key": "V1001_TODAY_MUSIC", 
                    "sub_button": [ ]
                }, 
                {
                    "name": "菜单", 
                    "sub_button": [
                        {
                            "type": "view", 
                            "name": "搜索", 
                            "url": "http://www.soso.com/", 
                            "sub_button": [ ]
                        }, 
                        {
                            "type": "view", 
                            "name": "视频", 
                            "url": "http://v.qq.com/", 
                            "sub_button": [ ]
                        }, 
                        {
                            "type": "click", 
                            "name": "赞一下我们", 
                            "key": "V1001_GOOD", 
                            "sub_button": [ ]
                        }
                    ]
                }
            ], 
            "matchrule": {
                "group_id": 2, 
                "sex": 1, 
                "country": "中国", 
                "province": "广东", 
                "city": "广州", 
                "client_platform_type": 2
            }, 
            "menuid": 208396993
        }
]

API的聚合方式: 业务实体 VS 消息通讯

通常来说,针对某个领域的框架,会提供一些业务实体来完成操作。例如自定义菜单,可以提供这样的业务实体:

Menu.Get(handler)
    .Create(menu, handler)
    .Update(menu, handler)
    .delete(menu, handler)

并且,将菜单相关的消息推送以事件的方式封装:

Menu.On("click", handler)

这种业务实体的映射,也可以说是RPC,的风格是相当可以的。但是我们会以消息通讯这种松散的方式来实现框架,例如说:

eventBus.send("fzs.wechat.menu.get", message, handler)

eventBus.send("fzs.wechat.menu.create", handler)

//接收消息推送的地址,address和事件名一一对应。
eventBus.consumer("fzs.wechat.event.click", message, handler)
eventBus.consumer("fzs.wechat.event.view", message, handler)

我们倾向于使用第二种方式来实现,因为这样对于多语言支持是友好的。

工作计划

  1. 将微信的接口分类,聚合到不同的address。

  2. 针对W.S. => S.的请求,路由到一个拦截器,将请求转发到不同的address,同时要将XML Body转为JSON表述的消息。

  3. 针对S. => W.S.的请求,实现一系列Consumer,根据address, 将消息的内容转为相应的请求,调用微信相对应的业务URL。

相关文章

网友评论

      本文标题:使用Vert.x开发微信框架

      本文链接:https://www.haomeiwen.com/subject/wxuugttx.html