微信服务号的消息处理
2016-07-26
编程
新产品会和微信公众号有交互,所以就来尝尝鲜,做一做微信公众号的各种东西.
首先:注册,认证,bla bla bla,设置一堆东西
在获得了开发权限之后,就可以仔细阅读开发文档了.
和微信的交互有两种:
- 服务器给微信发送消息
- 微信给服务器发送消息
说说他们的区别.
服务器给微信发消息,很方便,发表单格式的就行了,微信回复的是json格式的
微信服务器主动给服务器发消息,就很恶心了.
- 如果在配置页面设置了消息模式是加密的,那么收到了微信的消息之后需要先对包进行解密,才能得知微信发送的消息的确切内容.
- 微信的每次请求,都需要按照和它一样的变态格式回复.
- 还得验证验证消息到底是不是微信发的~
先来看看微信给服务器发的是什么样子的东西
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
哦,这个是没加密的,加密的更难看…
应该用正则来提取内容吧,我把他们都写了出来,方便方便
REGEX_TOUSERNAME = r'\<ToUserName\>\<\!\[CDATA\[(.*)\]\]\>\<\/ToUserName\>'
REGEX_FROMUSERNAME = r'\<FromUserName\>\<\!\[CDATA\[(.*)\]\]\>\<\/FromUserName\>'
REGEX_MSGTYPE = r'\<MsgType\>\<\!\[CDATA\[(.*)\]\]\>\<\/MsgType\>'
REGEX_EVENT = r'\<Event\>\<\!\[CDATA\[(.*)\]\]\>\<\/Event\>'
REGEX_EVENT_KEY = r'\<EventKey\>\<\!\[CDATA\[(.*)\]\]\>\<\/EventKey\>'
REGEX_SCANTYPE = r'\<ScanType\>\<\!\[CDATA\[(.*)\]\]\>\<\/ScanType\>'
REGEX_SCANRESULT = r'\<ScanResult\>\<\!\[CDATA\[(.*)\]\]\>\<\/ScanResult\>'
REGEX_CREATETIME = r'\<CreateTime\>(.*)\<\/CreateTime\>'
REGEX_CONTENT = r'\<Content\>\<\!\[CDATA\[(.*)\]\]\>\<\/Content\>'
还傻乎乎的搞了个类来解析这坨东西
class wechat_xml_object(object):
def __init__(self, xml):
self.origin = str(xml)
@property
def toUserName(self):
return self.returnValueForKey(REGEX_TOUSERNAME)
@property
def fromUserName(self):
return self.returnValueForKey(REGEX_FROMUSERNAME)
@property
def msgType(self):
return self.returnValueForKey(REGEX_MSGTYPE)
@property
def event(self):
return self.returnValueForKey(REGEX_EVENT)
@property
def eventKey(self):
return self.returnValueForKey(REGEX_EVENT_KEY)
@property
def scanType(self):
return self.returnValueForKey(REGEX_SCANTYPE)
@property
def scanResult(self):
return self.returnValueForKey(REGEX_SCANRESULT)
@property
def createTime(self):
return self.returnValueForKey(REGEX_CREATETIME)
@property
def content(self):
return self.returnValueForKey(REGEX_CONTENT)
def returnValueForKey(self, regex):
match = re.search(regex,self.origin)
if match:
return match.group(1)
else:
return None
虽然我知道有kissXML这种神器,但是我懒
得装……
上面是把明文的XML解包出来,现在我们把想回复的数据给封装起来
class wechat_xml_builder(object):
def __init__(self, data_type):
self.type = data_type
self.content = ''
self.contains = []
def addObject(self, key, value, data_mark):
if key in self.contains:
return False
if data_mark:
self.content += '<{0}><![CDATA[{1}]]></{2}>'.format(key, value, key)
else:
self.content += '<{0}>{1}</{2}>'.format(key, value, key)
self.contains.append(key)
return True
def add_default_from(self, dictionary):
fromUser = dictionary['toUser']
openid = dictionary['openid']
createTime = dictionary['createTime']
self.addObject('ToUserName', openid, True)
self.addObject('FromUserName', fromUser, True)
self.addObject('CreateTime', createTime, False)
def exportString(self):
return '<xml>' + self.content + '</xml>'
我感觉这个类用起来还是蛮简单的.
至于说加密和解密,微信还是很良心的提供了一个库,可以直接操作.
下次再整理一下微信开发中其他的坑儿吧