首先先丟出來幾個須要依賴的開源項目,都是我通過千挑萬選甄選出來的精品項目。哈哈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
很很差意思又在網上曬了代碼,代碼很粗淺,你們湊合看。