Python3-Flask-微信公众号开发-3

当普通用户想公众号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。

微信的可以收到用户的消息类型分文本、图片、语言、视频、小视频、地理位置和链接,所对应的MsgType分别为[text,image,voice,video,shortvideo,location,link]。

请注意:
1、关于重试的消息排重,推荐使用msgid排重。
2、微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。假如服务器无法保证在五秒内处理并回复,
可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。详情请见“发送消息-被动回复消息”。
3、如果开发者需要对用户消息在5秒内立即做出回应,即使用“发送消息-被动回复消息”接口向用户被动回复消息时,可以在
公众平台官网的开发者中心处设置消息加密。开启加密后,用户发来的消息和开发者回复的消息都会被加密(但开发者通过客服
接口等API调用形式向用户发送消息,则不受影响)。关于消息加解密的详细说明,请见“发送消息-被动回复消息加解密说明”。

微信收到的消息类型结构
微信被动回复的消息类型结构

微信文本自动回复

我们以微信的文本消息类型做为列子说明。
首先我们来看看文本消息的XML结构个说明

<xml>
 <ToUserName>ToUserName>
 <FromUserName>FromUserName>
 <CreateTime>1348831860CreateTime>
 <MsgType>MsgType>
 <Content>Content>
 <MsgId>1234567890123456MsgId>
 xml>
参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType text
Content 文本消息内容
MsgId 消息id 64位整型

由于POST过来的是XML类型我数据,所以我们首要做的就是做xml解析。Python中自带了xml解析模块了。就直接导入进行解析

import xml.etree.cElementTree as et


xmldata = '''<xml>
 <ToUserName>ToUserName>
 <FromUserName>FromUserName>
 <CreateTime>1348831860CreateTime>
 <MsgType>MsgType>
 <Content>Content>
 <MsgId>1234567890123456MsgId>
 xml>'''


xml_rec = et.fromstring(xmldata)

ToUserName = xml_rec.find('ToUserName').text
fromUser = xml_rec.find('FromUserName').text
MsgType = xml_rec.find('MsgType').text
Content = xml_rec.find('Content').text
MsgId = xml_rec.find('MsgId').text

print(ToUserName, fromUser ,MsgType ,Content, MsgId)

打印结果

toUser fromUser text this is a test 1234567890123456

解析了xml之后,我们就要给用户回消息。我们回复的消息也是xml类型

<xml>
<ToUserName>ToUserName>
<FromUserName>FromUserName>
<CreateTime>12345678CreateTime>
<MsgType>MsgType>
<Content>Content>
xml>
参数 是否必须 描述
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间 (整型)
MsgType text
Content 回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)

回复消息的时候需要注意一点,就是我们回复给用户的ToUserName和FromUserName和接收到的应该是相反的,就是邮件的发送一样。
新建一个muban.py

text_str = '''
                ![CDATA[%s]]
                ![CDATA[%s]]
                %s
                ![CDATA[text]]
                ![CDATA[%s]]
                '''

def reply_muban(type):

    if type == 'text':
         return text_str

打开我们之前的main.py,导入模板,添加xml解析代码和返回代码,由于是POST过来的,所以我们需要做POST判断

# -*- coding:utf-8 -*-

from flask import Flask,request
from time import time
import xml.etree.ElementTree as et
import muban

import hashlib

app = Flask(__name__)
app.debug = True

@app.route('/wx_flask',methods=['GET','POST'])
def wechat():

    if request.method == 'GET':
        token = 'xiaoqingxin'
        data = request.args
        signature = data.get('signature','')
        timestamp = data.get('timestamp','')
        nonce = data.get('nonce','')
        echostr = data.get('echostr','')

        list = [token, timestamp, nonce]
        list.sort()

        s = list[0] + list[1] + list[2]

        hascode = hashlib.sha1(s.encode('utf-8')).hexdigest()

        if hascode == signature:
            return echostr
        else:
            return ""

    if request.method == 'POST':
        xmldata = request.args
        xml_rec = et.fromstring(xmldata)

        ToUserName = xml_rec.find('ToUserName').text
        fromUser = xml_rec.find('FromUserName').text
        MsgType = xml_rec.find('MsgType').text
        Content = xml_rec.find('Content').text
        MsgId = xml_rec.find('MsgId').text

        return muban.reply_muban(MsgType) % (fromUser, ToUserName, int(time()), Content)




if __name__ == '__main__':
    app.run()

现在来运行我们的代码,在公众号中发送消息就可以收到回复了。
Python3-Flask-微信公众号开发-3_第1张图片

可以看到我这里还有其他的回复,我把代码贴下,和文本回复差不多。

muban.py

# -*- coding:utf-8 -*-



text_str = "<xml><ToUserName>ToUserName><FromUserName>FromUserName><CreateTime>%sCreateTime><MsgType>MsgType><Content>Content>xml>"

img_str = "<xml><ToUserName>ToUserName><FromUserName>FromUserName><CreateTime>%sCreateTime><MsgType>MsgType><Image><MediaId>MediaId>Image>xml>"


image_text_lj = "<ArticleCount>%sArticleCount><Articles>%sArticles>xml>"
image_text_item = "<item><Title>Title><Description>Description><PicUrl>PicUrl><Url>Url>item>"


def reply_muban(type):

    if type == "text":
        return text_str
    elif type == "image":
        return img_str



def image_text_new_muban(itemDic):

    items = ""
    for item in itemDic:
        items += image_text_item % (item['Title'], item['Description'], item['PicUrl'], item['Url'])


    return image_text_str + (image_text_lj % (len(itemDic), items))

main.py

 if request.method == 'POST':

        str_xml = request.stream.read()
        xml = etree.fromstring(str_xml)
        msgType = xml.find("MsgType").text
        xml_muban = muban.reply_muban(msgType)
        if msgType == "text":
            content = xml.find("Content").text
            fromUser = xml.find("FromUserName").text
            toUser = xml.find("ToUserName").text
            return xml_muban % (fromUser, toUser, int(time()), content)
        elif msgType == "image":
            fromUser = xml.find("FromUserName").text
            toUser = xml.find("ToUserName").text
            mediaid = xml.find("MediaId").text
            print(xml_muban % (fromUser, toUser, int(time()), mediaid))
            return xml_muban % (fromUser, toUser, int(time()), mediaid)
        else:
            itemDic = [{'Title':'Title','Description':'Description',
                    'PicUrl':'https://ss0.baidu.com/73x1bjeh1BF3odCf/it/u=3705265267,3767781981&fm=85&s=DE0A5C2A7D264E1B62FD99CB0300C0B1',
                    'Url':'www.baidu.com'},{'Title':'Title1','Description':'Description1',
                    'PicUrl':'https://ss0.baidu.com/73x1bjeh1BF3odCf/it/u=3705265267,3767781981&fm=85&s=DE0A5C2A7D264E1B62FD99CB0300C0B1',
                    'Url':'www.baidu.com'}]
            fromUser = xml.find("FromUserName").text
            toUser = xml.find("ToUserName").text
            mediaid = xml.find("MediaId").text
            return muban.image_text_new_muban(itemDic) % (fromUser, toUser, int(time()))

if __name__ == '__main__':
   app.run()

微信收到的消息类型结构
微信被动回复的消息类型结构

你可能感兴趣的:(Python3-Flask-微信公众号开发-3)