django+python微信开发之三-消息处理类
###消息处理类wechatUtil.py
上一篇封装了三种消息类型,wechatMessage.py,wechatEvent.py和wechatReply.py。微信是以xml格式处理信息的,所以要处理xml得到相应的信息。这里用lxml库来处理,先贴上代码再解释:
# -*- coding:utf-8 -*-
"""
# Author: Pegasus Wang (pegasuswang@qq.com, http://ningning.today)
# Created Time : Wed Feb 18 18:18:10 2015
# File Name: wechatUtil.py
# Description:
# :copyright: (c) 2015 by Pegasus Wang.
# :license: MIT, see LICENSE for more details.
"""
import hashlib
from lxml import etree
def checkSignature(request):
"""check signature.
:param request: get method
:return: if success return True else False
"""
signature = request.GET.get(u'signature', None)
timestamp = request.GET.get(u'timestamp', None)
nonce = request.GET.get(u'nonce', None)
token = u'pegasuswang' # your wechat token
tmplist = [token, timestamp, nonce]
tmplist.sort()
tmpstr = '%s%s%s' % tuple(tmplist)
tmpstr = hashlib.sha1(tmpstr).hexdigest()
if tmpstr == signature:
return True
else:
return False
class MessageUtil(object):
"""MessageUtil has some methods to process message."""
# request message types
REQ_MESSAGE_TYPE_TEXT = u'text'
REQ_MESSAGE_TYPE_IMAGE = u'image'
REQ_MESSAGE_TYPE_VOICE = u'voice'
REQ_MESSAGE_TYPE_VIDEO = u'video'
REQ_MESSAGE_TYPE_LOCATION = u'location'
REQ_MESSAGE_TYPE_LINK = u'link'
REQ_MESSAGE_TYPE_EVENT = u'event'
# event types
EVENT_TYPE_SUBSCRIBE = u'subscribe'
EVENT_TYPE_UNSUBSCRIBE = u'unsubscribe'
EVENT_TYPE_SCAN = u'scan'
EVENT_TYPE_LOCATION = u'LOCATION'
EVENT_TYPE_CLICK = u'CLICK'
# reply message types
RESP_MESSAGE_TYPE_TEXT = u'text'
RESP_MESSAGE_TYPE_IMAGE = u'image'
RESP_MESSAGE_TYPE_VOICE = u'voice'
RESP_MESSAGE_TYPE_VIDEO = u'video'
RESP_MESSAGE_TYPE_MUSIC = u'music'
RESP_MESSAGE_TYPE_NEWS = u'news'
# message types
MESSAGETYPE = [u'Image', u'Voice', u'Video', u'Music', u'Articles']
@staticmethod
def parseXml(request):
"""parse request post xml message.
:param request: post request
:return: dict of xml message
"""
raw_xml = request.body.decode(u'UTF-8')
xmlstr = etree.fromstring(raw_xml)
dict_xml = {}
for child in xmlstr:
dict_xml[child.tag] = child.text.encode(u'UTF-8') # note
return dict_xml
@staticmethod
def class2xml(obj):
"""convert reply message class to xml.
:param obj: reply message class' object
:return: xml of the object
"""
root = etree.Element(u'xml')
for key, value in vars(obj).items():
if key in MessageUtil.MESSAGETYPE:
tmproot = etree.SubElement(root, key)
if key == u'Articles': # solve Article, it's special
for eachArticle in value:
etree.SubElement(tmproot, u'item')
for tmpkey, tmpvalue in vars(eachArticle).items():
tmpkey_ele = etree.SubElement(tmproot, tmpkey)
tmpkey_ele.text = etree.CDATA(unicode(tmpvalue))
else:
for tmpkey, tmpvalue in vars(obj.__getattribute__(key)).items():
tmpkey_ele = etree.SubElement(tmproot, tmpkey)
if u'time' in tmpkey.lower() or u'count' in tmpkey.lower():
tmpkey_ele.text = unicode(tmpvalue)
else: # CDATA tag for str
tmpkey_ele.text = etree.CDATA(unicode(tmpvalue))
else:
if u'time' in key.lower() or u'count' in key.lower():
etree.SubElement(root, key).text = unicode(value)
else:
etree.SubElement(root, key).text = etree.CDATA(unicode(value))
return etree.tostring(root, pretty_print=True, xml_declaration=False, encoding=u'utf-8')
###checkSignature方法
参考:验证消息真实性http://mp.weixin.qq.com/wiki/4/2ccadaef44fe1e4b0322355c2312bfa8.html
开发文档给出的是php的代码,改写成python也很简单。
加密/校验流程如下:
- 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行sha1加密
- 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
###消息处理类MessageUtil
- 类型定义:定义了一些列变量标识消息类型
- parseXml方法:用来解析微信公众账号post过来的xml信息,得到发送人、发送时间、消息内容等信息,返回一个字典。使用lxml库。
- class2xml方法:没有找到相应的库把reply消息对应的类转换成xml格式,这个是我自己写的一个方法,用来把reply类转换成xml返回给微信公众账号。测试信息如下: