針對(duì)微信公眾平臺(tái),圖形界面操作存在的許多功能限制,在開(kāi)發(fā)者中心設(shè)置回調(diào)URL和Token,可以更加靈活地?cái)U(kuò)展各項(xiàng)功能。對(duì)于具備開(kāi)發(fā)能力的人員,同時(shí)擁有一臺(tái)可供轉(zhuǎn)發(fā)消息的服務(wù)器,itchatmp可以提供強(qiáng)大的技術(shù)支持。
開(kāi)發(fā)前準(zhǔn)備:
- Python版本:2.7,3.5
- 供轉(zhuǎn)發(fā)的服務(wù)器
- 微信公眾平臺(tái)賬號(hào)
搭建web服務(wù)
Python Web框架有許多,最流行的如Django,F(xiàn)lask,WSGI等。這里重點(diǎn)推薦一個(gè)開(kāi)源的微信公眾號(hào)接口itchatmp。它將公眾號(hào)許多功能接口都整合到了代碼里,開(kāi)發(fā)者無(wú)需自行構(gòu)造請(qǐng)求訪問(wèn)鏈接,簡(jiǎn)單易上手。
1. 安裝itchatmp
pip install itchatmp
注意:itchat基于tornado框架,本人在python3.5版本安裝過(guò)程中,發(fā)現(xiàn)高版本的tornado(5.0以上)有許多兼容問(wèn)題。如執(zhí)行import itchatmp時(shí),發(fā)生RuntimeError: There is no current event loop in thread 'Thread-1';在接受圖片消息時(shí),set_event_loop無(wú)法建立事件循環(huán)等。
解決辦法:安裝較低版本的tornado。
pip uninstall tornado
pip install tornado==4.5.3
# 安裝futures庫(kù)報(bào)錯(cuò)
pip install futures==3.1.1
2. 設(shè)置自動(dòng)回復(fù)
- 處理文本消息
def getBasicInfo(msg):
date = time.strftime("%Y-%m-%d %H-%M-%S", time.localtime(int(msg['CreateTime']))) # 接收消息的時(shí)間
user = msg['FromUserName'] # 關(guān)注用戶的OpenId,同一個(gè)公眾號(hào)所有關(guān)注者都是唯一的
return date, user
@itchatmp.msg_register(TEXT)
def text_reply(msg):
content = msg['Content']
date, user = getBasicInfo(msg)
save_path = SAVE_PATH + TEXT_PATH + user + '.txt' # 使用OpenID來(lái)保存不同用戶的消息記錄
if not os.path.exists(save_path):
with open(save_path,'w',encoding='utf-8') as file:
file.write(date + " --- " + content + "\n")
else:
with open(save_path,'a',encoding='utf-8') as file:
file.write(date + " --- " + content + "\n")
return "消息保存成功" # 去掉return語(yǔ)句時(shí),表示不回復(fù)內(nèi)容
保存結(jié)果:

- 處理多媒體消息
多媒體消息,包括圖片,語(yǔ)音,視頻,小視頻等,這類消息的共同點(diǎn)是,返回參數(shù)中都帶有MediaId。MediaId是消息媒體id,可以使用該參數(shù),通過(guò)調(diào)用獲取臨時(shí)素材接口下載數(shù)據(jù)。
@itchatmp.msg_register([IMAGE, VIDEO, SHORT_VIDEO, VOICE])
def media_reply(msg):
date, user = getBasicInfo(msg)
pathSymbol = {
IMAGE: IMAGE_PATH,
VIDEO: VIDEO_PATH,
SHORT_VIDEO: SHORT_VIDEO_PATH,
VOICE: VOICE_PATH
}.get(msg["MsgType"]) # 通過(guò)判斷消息類型,獲取媒體信息相應(yīng)的保存路徑
r = itchatmp.messages.download(msg["MediaId"])
filename = date + ' '+ user + os.path.splitext(r.get('FileName', 'myfile'))[1] # 命名規(guī)則:時(shí)間 + OpenId +文件后綴名
if 'File' in r:
with open(SAVE_PATH + pathSymbol + filename, 'wb') as f:
f.write(r['File'].getvalue()) # 保存數(shù)據(jù)到本地
else:
print(r)
微信公眾平臺(tái)上多媒體消息最多只能保存3天,上述代碼可以實(shí)時(shí)地將所有信息,按照相應(yīng)的格式(jpg,mp4,amr等)永久保存在本地。
- 其它消息
其它消息類型,可以參考微信工作平臺(tái)技術(shù)文檔,里面列舉了不同消息參數(shù)的格式,根據(jù)需要自定義回復(fù)內(nèi)容。
@itchatmp.msg_register(LOCATION)
def location_reply(msg):
lat = msg['Location_X']
lon = msg['Location_Y']
label = msg['Label']
return str(label) + '\n' + '經(jīng)度:' + lat + '\n' + '緯度:' + lon
例如對(duì)收到的地理位置消息,可以自動(dòng)回復(fù)該位置的名稱,經(jīng)緯度信息。

3. 一個(gè)簡(jiǎn)單的例子
import itchatmp
itchatmp.update_config(itchatmp.WechatConfig(
token='yourToken',
appId = 'yourAppId',
appSecret = 'yourAppSecret'))
@itchatmp.msg_register(itchatmp.content.TEXT)
def text_reply(msg):
return msg['Content']
itchatmp.run()
此處的appId,appSecret分別為開(kāi)發(fā)者ID,開(kāi)發(fā)者密碼,可以在微信工作平臺(tái)查看,見(jiàn)下一步。token用于驗(yàn)證開(kāi)發(fā)者服務(wù)器,由開(kāi)發(fā)者隨機(jī)設(shè)置(3-32字符)。
在服務(wù)器上運(yùn)行該程序(默認(rèn)開(kāi)啟80端口),外網(wǎng)訪問(wèn)出現(xiàn)以下語(yǔ)句時(shí),表示服務(wù)開(kāi)啟成功。

服務(wù)器配置
1. 開(kāi)發(fā)者ID(AppID),開(kāi)發(fā)者密碼(AppSecret),IP白名單

- 開(kāi)發(fā)者ID可以在微信公眾平臺(tái) - 開(kāi)發(fā) - 基本配置 - 公眾號(hào)開(kāi)發(fā)信息中查看。
- 開(kāi)發(fā)者密碼是校驗(yàn)公眾號(hào)開(kāi)發(fā)者身份的密碼,公眾平臺(tái)不會(huì)單獨(dú)儲(chǔ)存AppSecret,因此在初次設(shè)置后需要另行保存。
- 將提供轉(zhuǎn)發(fā)的服務(wù)器地址添加到IP白名單中。
2. 配置服務(wù)器

- URL填寫服務(wù)器地址,http協(xié)議必須使用80端口。
- 將開(kāi)啟web服務(wù)代碼中設(shè)置的token填到這里。
- 點(diǎn)擊隨機(jī)生成EncodingAESKey。
- 個(gè)人訂閱號(hào),消息加解密方式可以選擇明文模式。
在提交服務(wù)器配置信息時(shí),會(huì)進(jìn)行token驗(yàn)證。因此提交前確保在服務(wù)器上已經(jīng)搭建好web服務(wù),并且成功運(yùn)行,否則會(huì)出現(xiàn)請(qǐng)求URL超時(shí)提示。
關(guān)于接口權(quán)限
針對(duì)個(gè)人未認(rèn)證訂閱號(hào),可以使用的接口主要有:
- 接收消息(所有類型消息)
- 發(fā)送消息(僅僅支持自動(dòng)回復(fù))
- 永久素材的管理(上傳,修改,刪除)
- 其它圖像、音頻接口,界面操作等
在開(kāi)發(fā)者中心開(kāi)啟了回調(diào)URL和Token后,公眾平臺(tái)設(shè)置的自動(dòng)回復(fù)、自定義菜單等功能都將失效并且停用。而個(gè)人訂閱號(hào)不具備自定義菜單接口權(quán)限,因此在改用開(kāi)發(fā)者模式后,可能會(huì)丟失平臺(tái)上設(shè)置的自定義菜單信息。