在SAE上搭建微信公眾平台賬號消息服務器


利用微信公眾平台提供的消息接口,搭建自己的消息處理服務器,消息的處理和回復將更加靈活,以期給訂閱用戶提供更加定制化和個性化的信息。本文將結合SAE,基於Python Flask框架,搭建一個公眾賬號“豆米查書”(微信號doumibook)的消息服務器。該公眾號的基本功能是:輸入書籍標題、作者或者isbn條碼號等關鍵字,查詢書籍的基本信息。書籍數據來源豆瓣網,使用了douban api v2

一、申請微信公眾平台賬號

這里注冊微信公眾平台賬號,登陸,設置必要的名稱、地區和用戶信息等內容。在“高級功能”中開啟“開發模式”。

仔細閱讀微信公眾平台的官方文檔

二、在SAE上創建Python應用

創建Python應用,二級域名和應用名稱為doumibook,那么基本地址為http://doumibook.sinaapp.com。

三、申請消息接口並驗證

1,消息接口配置

到“高級功能”-->“開發模式”-->“成為開發者”中填寫接口配置信息,有URL和Token,URL用於接口驗證和消息推送,本例中填寫步驟二中的接入地址,Token用於接口驗證,任意填寫即可,例如填寫“doumitest”。

2,消息接口驗證(網址接入)

信息填寫完成后,點擊提交,會提示認證“服務器未正確響應的Token驗證”,這是正常的,因為我們雖然創建了SAE應用,但沒有處理接口驗證消息。點擊提交時,微信服務器會發送一條Http GET請求,攜帶signature、timestamp、nouce和echostr四個參數,對URL進行合法性的校驗(參考微信官方的詳細文檔的“網址接入”小節)。如下是flask中處理接口驗證的代碼:

import hashlib
 
 @app.route('/weixin', methods=['GET'])
 def weixin_verify():
     signature = request.args.get('signature')
     timestamp = request.args.get('timestamp')
     nonce = request.args.get('nonce')
     echostr = request.args.get('echostr')
     
     token = 'doumitest' #和申請消息接口時的Token一致
     tmplist = [token, timestamp, nonce]
     tmplist.sort()
     tmpstr = ''.join(tmplist)
     hashstr = hashlib.sha1(tmpstr).hexdigest()
 
     if hashstr == signature:
         return echostr #success
     return 'access verification fail' #fail

 

四、消息推送和消息回復

1,消息推送

URL接口驗證以后,公眾平台賬號收到的消息將由微信服務器使用HTTP POST推送至該URL。消息內容為XML格式,消息類型有文本、圖片和地理位置等,例如文本消息由以下幾個部分組成。

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>1348831860</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[this is a test]]></Content>
</xml>

其中,ToUserName和FromUserName分別為公眾帳號和用戶帳號的表識串。MsgType標識消息類型,“text”表明消息是文本消息,文本內容放置在Content字段。其他類型消息的xml結構請參照官方文檔。

使用下面的代碼片段,解析xml數據,以dict形式保存:

import xml.etree.ElementTree as ET
 
 def parse_msg(rawmsgstr):
     root = ET.fromstring(rawmsgstr)
     msg = {}
     for child in root:
         msg[child.tag] = child.text
     return msg

 

2,用戶訂閱消息

當有新用戶關注公眾號時,微信服務器會發送一條通知消息到消息服務器,消息服務器可以返回初次訂閱的歡迎和幫助信息。目前,微信啟用了新的用戶訂閱通知方法,即使用事件推送。

事件推送的MsgType為“event”,是微信4.5版開始支持的一種消息格式,可以發送用戶訂閱( subscribe)、退訂(unsubscribe)以及自定義菜單點擊(CLICK)等事件消息。消息格式為:

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[EVENT]]></Event>
<EventKey><![CDATA[EVENTKEY]]></EventKey>
</xml>

微信官方已經發布通告,在2013年3月26日起由原來的發送一條內容為“Hello2BizUser”的訂閱消息,切換至事件推送方法。

 

3,書籍信息獲取

簡單起見,目前僅支持微信用戶發送書籍isbn條碼號給doumibook,來查詢作者和書名。使用douban api v2版接口,獲取書籍信息,douban返回的json數據。代碼片段如下:

 import urllib2
 import json
 
 bookurlbase = 'http://api.douban.com/v2/book/isbn/'
 DOUBAN_APIKEY = '' #豆瓣上申請的APIKEY
 
 def query_book_info(isbn):
     url = '%s%s?apikey=%s' % (bookurlbase, isbn, DOUBAN_APIKEY)
     resp = urllib2.urlopen(url)
     book = json.loads(resp.read())
     info = ''.join(book['author']) + ': ' + book['title']
     return info

 

4,消息回復

查詢到書籍信息之后,消息服務器響應微信服務器的消息推送,回復內容結構同樣是XML,假設我們回復文本消息,基本結構如下:

<xml>
  <ToUserName><![CDATA[toUser]]></ToUserName>
  <FromUserName><![CDATA[fromUser]]></FromUserName>
  <CreateTime>12345678</CreateTime>
  <MsgType><![CDATA[text]]></MsgType>
  <Content><![CDATA[content]]></Content>
  <FuncFlag>0</FuncFlag>
 </xml>

其中的ToUserName和FromUserName與消息推送中的相關。

構造回復消息代碼片段如下:

def response_msg(recvmsg, content):
     textTpl = """<xml>
             <ToUserName><![CDATA[%s]]></ToUserName>
             <FromUserName><![CDATA[%s]]></FromUserName>
             <CreateTime>%s</CreateTime>
             <MsgType><![CDATA[%s]]></MsgType>
             <Content><![CDATA[%s]]></Content>
             <FuncFlag>0</FuncFlag>
             </xml>"""
     echostr = textTpl % (recvmsg['FromUserName'], recvmsg['ToUserName'], recvmsg['CreateTime'], recvmsg['MsgType'], content)
     return echostr

 注意到,回復文本消息,內容比較單一,這里可以使用MsgType為“news”的圖文消息格式進行回復,這里不再贅述,請參考官方文檔以及本文末尾給出的源代碼鏈接。

4,綜合

消息推送HTTP POST請求的處理代碼如下:

 @app.route('/weixin', methods=['POST'])
 def weixin_msg():
     data = request.data
     msg = parse_msg(data)
     content = 'not found'
     if msg.has_key('Content'):
         content = query_book_info(msg['Content'])
     return response_msg(msg, content)

 

五、總結

本文以doumibook為例,使用Python Flask框架,介紹了在SAE上搭建微信公眾平台賬號消息服務器的基本步驟。

需要看完整代碼的同學,請移步這里:https://github.com/gzb1985/doumibook_weixin

doumibook目前僅實現了很簡單的功能,還沒有實用的價值,例如輸入“浪潮之巔”,則返回:

僅供參考,拋磚引玉吧。

 

文章更新記錄:

2013.3.31:微信官方公布的新的用戶訂閱消息方法,見四(2)。

(完)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM