验证URL有效性成功后即接入生效,成为开发者。如果公众号类型为服务号(订阅号只能使用普通消息接口),可以在公众平台网站中申请认证,认证成功的服务号将获得众多接口权限,以满足开发者需求。
此后用户每次向公众号发送消息、或者产生自定义菜单点击事件时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,然后开发者可以依据自身业务逻辑进行响应,例如回复消息等。
用户向公众号发送消息时,公众号方收到的消息发送者是一个OpenID,是使用用户微信号加密后的结果,每个用户对每个公众号有一个唯一的OpenID。
1.接收普通消息
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。
各消息类型的推送使用XML数据包结构,如:
<xml> <ToUserName><![CDATA[gh_866835093fea]]></ToUserName> <FromUserName><![CDATA[ogdotwSc_MmEEsJs9-ABZ1QL_4r4]]></FromUserName> <CreateTime>1478317060</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你好]]></Content> <MsgId>6349323426230210995</MsgId> </xml>
注意:<![CDATA 与 ]]>
括起来的数据不会被xml解析器解析。
1.1 xmltodict 模块基本用法
xmltodict 是一个用来处理xml数据的很方便的模块。包含两个常用方法parse和unparse
1.parse
xmltodict.parse()方法可以将xml数据转为python中的dict字典数据:
>>> import xmltodict >>> xml_str = """ ... <xml> ... <ToUserName><![CDATA[gh_866835093fea]]></ToUserName> ... <FromUserName><![CDATA[ogdotwSc_MmEEsJs9-ABZ1QL_4r4]]></FromUserName> ... <CreateTime>1478317060</CreateTime> ... <MsgType><![CDATA[text]]></MsgType> ... <Content><![CDATA[你好]]></Content> ... <MsgId>6349323426230210995</MsgId> ... </xml> ... """ >>> >>> xml_dict = xmltodict.parse(xml_str) >>> type(xml_dict) <class 'collections.OrderedDict'> # 类字典型,可以按照字典方法操作 >>> >>> xml_dict OrderedDict([(u'xml', OrderedDict([(u'ToUserName', u'gh_866835093fea'), (u'FromUserName', u'ogdotwSc_MmEEsJs9-ABZ1QL_4r4'), (u'CreateTime', u'1478317060'), (u'MsgType', u'text'), (u'Content', u'\u4f60\u597d'), (u'MsgId', u'6349323426230210995')]))]) >>> >>> xml_dict['xml'] OrderedDict([(u'ToUserName', u'gh_866835093fea'), (u'FromUserName', u'ogdotwSc_MmEEsJs9-ABZ1QL_4r4'), (u'CreateTime', u'1478317060'), (u'MsgType', u'text'), (u'Content', u'\u4f60\u597d'), (u'MsgId', u'6349323426230210995')]) >>> >>> for key, val in xml_dict['xml'].items(): ... print key, "=", val ... ToUserName = gh_866835093fea FromUserName = ogdotwSc_MmEEsJs9-ABZ1QL_4r4 CreateTime = 1478317060 MsgType = text Content = 你好 MsgId = 6349323426230210995 >>>
2. unparse
xmltodict.unparse()方法可以将字典转换为xml字符串:
xml_dict = { "xml": { "ToUserName" : "gh_866835093fea", "FromUserName" : "ogdotwSc_MmEEsJs9-ABZ1QL_4r4", "CreateTime" : "1478317060", "MsgType" : "text", "Content" : u"你好", "MsgId" : "6349323426230210995", } } >>> xml_str = xmltodict.unparse(xml_dict) >>> print xml_str <?xml version="1.0" encoding="utf-8"?> <xml><FromUserName>ogdotwSc_MmEEsJs9-ABZ1QL_4r4</FromUserName><MsgId>6349323426230210995</MsgId><ToUserName>gh_866835093fea</ToUserName><Content>你好</Content><MsgType>text</MsgType><CreateTime>1478317060</CreateTime></xml> >>> >>> xml_str = xmltodict.unparse(xml_dict, pretty=True) # pretty表示友好输出 >>> print xml_str <?xml version="1.0" encoding="utf-8"?> <xml> <FromUserName>ogdotwSc_MmEEsJs9-ABZ1QL_4r4</FromUserName> <MsgId>6349323426230210995</MsgId> <ToUserName>gh_866835093fea</ToUserName> <Content>你好</Content> <MsgType>text</MsgType> <CreateTime>1478317060</CreateTime> </xml> >>>
1.2 普通消息类别
- 文本消息
- 图片消息
- 语音消息
- 视频消息
- 小视频消息
- 地理位置消息
- 链接消息
1.3 文本消息
<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>
2.被动回复消息
当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包中返回特定XML结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。
假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。详见下面说明:
- 直接回复success(推荐方式)
- 直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)
一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:
- 开发者在5秒内未回复任何内容
- 开发者回复了异常数据,比如JSON数据等
2.1 回复的消息类型
- 文本消息
- 图片消息
- 语音消息
- 视频消息
- 音乐消息
- 图文消息
2.2 回复文本消息
<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[你好]]></Content> </xml>