使用openResty搭建微信公众号服务

      首先先丢出来几个须要依赖的开源项目,都是我通过千挑万选甄选出来的精品项目。哈哈mysql

      1 mysql 驱动:https://github.com/hehr/lua-resty-mysqlnginx

      2 http 服务:https://github.com/hehr/lua-resty-httpgit

      3 xml解析:https://github.com/hehr/xmlgithub

       项目中引用的上述大神的项目,在此深表感谢。sql

        分析(哔哔一下)数据库

        这里先说一下微信公众号的特色,由于微信公众号的全部消息都是通过腾讯后台将不一样的事件消息请求到后台设定的一个路径。因此,为了保障项目具备良好的可扩展性,后台总体选择消息分发模式来实现。腾讯推送的路径,设置一个dispatch,按照不一样的事件类型,分发给不一样的模块去处理。  查看腾讯的公众号接口文档,能够看到腾讯的消息接口类型仍是用的XML格式,这点很反人类,我在项目中用到的是https://github.com/hehr/xml 这个xml解析工具,不能说很好用,可是最少终于找到一个相对来讲比较稳定的xml解析和生成工具了,若是各位有更好的开源项目推荐,欢迎留言。我在后文会丢出来实际编写的一个消息工具类,依据上述项目,建立腾讯公众号的消息格式。数据库我这边使用的是mysql去存储用户关系,这个没什么好嘟嘟的,毕竟mysql早就深刻人心了,不过仍是要给贡献像lua-resty-mysql 这样优秀开源项目的大神致敬。项目中全部的联系操做都是依赖 lua-resty-http 这个开源项目,支持https很好用,我的以为这样常规的需求都彻底应该整合进openResty常规组件中去。服务器

      实现微信

      nginx的配置文件工具

     

        location = /xxx/message{
              content_by_lua_file lua/response/dispatch.lua ; ui

      }   //我在腾讯的公众号后台填写的消息推送路径也就是该路径了。

 

     dispatch:

    这里作成一个消息分发的模式,不一样的消息不一样的模块去处理,方便后期业务拓展。我这里只是默认给出来一个简单的留言消息处理,随便回复一段文本。


    local xml = require("xml")
    local leave_message = require("message_handle.leave_message") --留言消息


   if 'GET' == ngx.req.get_method() then --微信服务器验证
       local args = ngx.req.get_uri_args()
       ngx.say(args.echostr)
        return
   end


   ngx.req.read_body()
   local args = ngx.req.get_body_data()

   if not args then
      ngx.log(ngx.ERR, "bad request ,check message_dispach.lua")
      return
   end


   local tb_xml = xml.load(args)
   local open_id =  xml.find(tb_xml,'FromUserName')[1] -- open_id
   local count = xml.find(tb_xml,'ToUserName')[1]-- 公众号平台帐号
   local message_type = xml.find(tb_xml,'MsgType')[1] --推送消息类型

   if message_type == 'text' then  --文本消息,用户留言
        
          leave_message.handle_leaving_message(open_id,count)    

   elseif message_type == 'event' then  --事件推送
        
        --todo 处理事件推送

   else  --未处理消息

      --todo 处理事件推送

   end

 

handle :

    这里负责处理不一样事件的具体逻辑,如,一个简单的自动回复文本功能:

   local message_util =  require("utils.message")

   local _M= {}

   function _M.handle_leaving_message( open_id , count )
    
    local text = { user = open_id , count = count , info = '咱们已经收到了您的留言了哦!' }
    local message_xml = message_util.text_message( text )
    ngx.say(message_xml)

   return _M

看到这里,你们必定很好奇,个人message_util.lua里面究竟是个什么鬼。下面我把这个代码给pull出来,其实这个里面就是按照腾讯要求的文档格式,去建立不一样的消息类型。

message.lua

--[[
   
 腾讯公众号微信消息

 1 普通文本消息
2 图文消息
3 文本连接消息    
]]--
 
 local xml = require ("xml")
 local _M = {}

--[[

 图文消息
 image = {user = 用户openId, count = 公众号帐号, title = 消息标题, description = 消息描述 , pic_url = 图片连接, url = 消息跳转连接 }

 ]]--
 20 function _M.image_message( image )
 
  --用来生成dump解析的table格式
  local function  dump_tb( tb )
  local tb_dump = {}
      for k , v in pairs( tb ) do
        local tb_tmp = {}
        tb_tmp.xml = k
        tb_tmp[1] = v
        table.insert(tb_dump,tb_tmp)
      end
    return tb_dump
 end


  local tb_dump = { ToUserName = image.user ,FromUserName = image.count ,CreateTime = ngx.time() , MsgType = 'news' , ArticleCount = 1 } --没有放入item的table
  local tb_item = { Title = image.title , Description = image.description , PicUrl = image.pic_url , Url = image.url } --item中内容

   tb_dump = dump_tb(tb_dump)
   tb_item = dump_tb(tb_item)

   tb_dump.xml = 'xml'
   tb_item.xml = 'item'
 
  local tb_articles = { xml = 'Articles'}

  table.insert(tb_articles , tb_item)
   table.insert(tb_dump,tb_articles)

  return xml.dump(tb_dump) , 'success'
 
 end

--[[

  音频文件消息
  @param  tb = {user = open_id , count = count ,  title = '星晴' , description = '描述' , music_url = '音乐路径' , HQ_music_url = '高品质音乐路径' , thumb_media_id = '微信id上传的' }

 ]]--
function _M.media_message( tb )

  local function  dump_tb( t )

   local tb_dump = {}
 
     for k , v in pairs( t ) do
      local tb_tmp = {}
       tb_tmp.xml = k
       tb_tmp[1] = v
       table.insert(tb_dump,tb_tmp)
end

    return tb_dump
 end

 

--[[

 文本消息
text = {user = 用户openId , count = 公众帐号 , info = 消息文本}
 ]]--
function _M.text_message( text )

   local tb_message = {ToUserName = text.user, FromUserName =  text.count,CreateTime = ngx.time() , MsgType = 'text', Content = text.info}
   local tb_dumpXML = {xml  = 'xml'}--生成一个用来dump xml的表

    for k ,v in pairs(tb_message) do
       local tb_temp = {}
      tb_temp[1] = v
       tb_temp.xml = k
       table.insert(tb_dumpXML,tb_temp)
     end
 
   return xml.dump( tb_dumpXML ) , 'success'
 
 end

 --[[
 发送连接文本消息,如: text  + title(url)  ,如 我要去北京天安门(连接北京天安门首页) 
 tb= {text = 文本消息 , title = 超文本标题 , url = 连接地址,user = open_id ,count = count}
 ]]--
 function _M.url_text_message( tb )

    local tb_message = { ToUserName = tb.user, FromUserName = tb.count , CreateTime = ngx.time() , MsgType = 'text' , Content = tb.text .. '<a href= \"'  .. tb.url ..' \">' .. tb.title .. '</a>'  }
    local tb_dumpXML = {xml  = 'xml'}--生成一个用来dump xml的表

    for k ,v in pairs(tb_message) do
      local tb_temp = {}
      tb_temp[1] = v
      tb_temp.xml = k
      table.insert(tb_dumpXML,tb_temp)
   end
 
    return xml.dump( tb_dumpXML ) , 'success'
 
 end


 return _M

 

  很很差意思又在网上晒了代码,代码很粗浅,你们凑合看。  

相关文章
相关标签/搜索