Django docks WeChat official account to realize automatic message reply

Preface

  This blog uses the Django framework, combined with uWsgi and Nginx, combined with the Postman API debugging tool, to realize the automatic response function of WeChat public account users' messages, and successfully deployed to the Tencent Cloud server.

  In the previous blog , we have configured the Tencent Cloud server and can perform simple interactions.

1. Configure WeChat Official Account

Insert picture description here

  • Click on modify configuration on the right and fill in the corresponding information
	URL:	http://服务器公网IP/wx
	Token:	自己设置一条字符串
	EncodingAESKey:	随机生成就可
	消息加解密方式:	为方便调试,暂时选择明文模式

Insert picture description here

2. Verify the source of the information

  After the above information is filled in, choosing to submit will trigger a GETrequest to verify the Token. The logic diagram of the verification is as follows:

Insert picture description here
  Below we views.pyimplement this logic in a file in the project directory , the code is as follows:

	from django.http import HttpResponse
	import hashlib
	
	
	# Create your views here.
	def TencentView(request):
	    if request.method == 'GET':
	        # 解析参数
	        data = request.GET
	        if len(data) == 0:
	            return HttpResponse(content="hello, this is WeChat view")
	        signature = data.get(key='signature', default='')
	        timestamp = data.get(key='timestamp', default='')
	        nonce = data.get(key='nonce', default='')
	        echostr = data.get(key='echostr', default='')
	        # 请按照公众平台官网\基本配置中信息填写
	        token = "xxxxxxxxxxxxxxxxxx"
	
	        list_para = [token, timestamp, nonce]
	        list_para.sort()
	        list_str = ''.join(list_para).encode('utf-8')
	
	        sha1 = hashlib.sha1()
	        sha1.update(list_str)
	        # map(sha1.update, list_para)
	        # 加密
	        hashcode = sha1.hexdigest()
	
	        print("/GET func: hashcode: {0}, signature: {1}".format(hashcode, signature))
	
	        if hashcode == signature:
	            return HttpResponse(content=echostr)
	        else:
	            return HttpResponse(content='验证失败')
	
	    elif request.method == 'POST':
	    	pass

  There is a pit here. The official examples are written in Python2, but the hashlib encryption of Python2 is different from that in Python3 utf-8. Python3 needs to be encoded first .

  After the above configuration is correct, the verification will be successful if you submit it again. If it is still unsuccessful, please check whether the encryption result is wrong. If the token verification is successful, it will automatically return to the main page of the basic configuration and click the start button.

3. Message reception-reply test

  Fans send a text message to the official account: "hello". In the developer's backend, they receive the xmlfollowing from the official platform :

	<xml>
		 <ToUserName><![CDATA[公众号]]></ToUserName>
		 <FromUserName><![CDATA[粉丝号]]></FromUserName>
		 <CreateTime>1460537339</CreateTime>
		 <MsgType><![CDATA[text]]></MsgType>
		 <Content><![CDATA[hello]]></Content>
		 <MsgId>6272960105994287618</MsgId>
	</xml>

  The field descriptions are as follows:

Field effect
ToUserName the public
FromUserName Fan number
CreateTime WeChat public platform records the specific time when the fan sent the message
MsgType Message type, there are text, image, voiceetc.
Content Message content
MsgId The public platform records a tag value identifying the message, and the WeChat background system automatically generates it

  The official account wants to reply to a fan with a text message with the content "test", then the xmlcontent sent by the developer to the backend of the official platform is as follows:

	<xml>
		 <ToUserName><![CDATA[粉丝号]]></ToUserName>
		 <FromUserName><![CDATA[公众号]]></FromUserName>
		 <CreateTime>1460541339</CreateTime>
		 <MsgType><![CDATA[text]]></MsgType>
		 <Content><![CDATA[test]]></Content>
	</xml>

  If the server cannot guarantee to process the reply within five seconds, it must reply with "success" or "" (empty string), otherwise the WeChat background will prompt "The official account is temporarily unavailable, please try again later".

  The message receiving-response flow chart is as follows:

Insert picture description here
  Let's continue views.pyto implement this process in the files in the project directory , adding the following code:

from xml.etree import ElementTree
import time


class ParseXmlMsg(object):
    def __init__(self, xmlData):
        self.ToUserName = xmlData.find('ToUserName').text
        self.FromUserName = xmlData.find('FromUserName').text
        self.CreateTime = xmlData.find('CreateTime').text
        self.MsgType = xmlData.find('MsgType').text
        self.MsgId = xmlData.find('MsgId').text

        if self.MsgType == 'text':
            self.Content = xmlData.find('Content').text.encode('utf-8')
        elif self.MsgType == 'image':
            self.PicUrl = xmlData.find('PicUrl').text
            self.MediaId = xmlData.find('MediaId').text


class TextMsg(object):
    def __init__(self, toUserName, fromUserName, content):
        # 私有对象,禁止外部访问
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['Content'] = content

    def send(self):
        XmlForm = """
            <xml>
                <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
                <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
                <CreateTime>{CreateTime}</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[{Content}]]></Content>
            </xml>
            """
        return XmlForm.format(**self.__dict)


class ImageMsg(object):
    def __init__(self, toUserName, fromUserName, mediaId):
        self.__dict = dict()
        self.__dict['ToUserName'] = toUserName
        self.__dict['FromUserName'] = fromUserName
        self.__dict['CreateTime'] = int(time.time())
        self.__dict['MediaId'] = mediaId

    def send(self):
        XmlForm = """
            <xml>
                <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
                <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
                <CreateTime>{CreateTime}</CreateTime>
                <MsgType><![CDATA[image]]></MsgType>
                <Image>
                <MediaId><![CDATA[{MediaId}]]></MediaId>
                </Image>
            </xml>
            """
        return XmlForm.format(**self.__dict)

  Also need elifto add the following code in the statement:

	elif request.method == 'POST':
        # 解析发送过来的body
        webData = request.body
        # print("Post webdata is ", webData)
        xmlData = ElementTree.fromstring(webData)
        recMsg = ParseXmlMsg(xmlData)

        if recMsg.MsgType == 'text':
            toUser = recMsg.FromUserName
            fromUser = recMsg.ToUserName
            content = 'test'

            replyMsg = TextMsg(toUser, fromUser, content)
            return HttpResponse(content=replyMsg.send())
        elif recMsg.MsgType == 'image':
            print('暂时不做处理')
            return HttpResponse(content='success')

4. Postman debugging

  For debugging convenience, we can start the project locally, and then send-receive messages through Postmanxml , and upload to the server after debugging.

  • First start the project locally
	# 在启动之前,先注释掉settings.py文件中的一行代码,关闭CSRF验证
	# 否则POST时会触发CSRF验证失败
	# 'django.middleware.csrf.CsrfViewMiddleware'
	python manage.py runserver

Insert picture description here

  • Open Postman, use the POSTrequest, and Bodyfill in the xmlmessage we need to send in the menu bar . The specific configuration information is shown in the figure below

Insert picture description here

  • After filling in, click Sendsend, we will receive the returned information in the response information column below

Insert picture description here
  The message sent is "hello" and the message received is "test", indicating that it is OK, and then upload the code to the server.

  Remember to restart after uploading the server uWsgiand Nginxoh!

5. Official interface debugging

  The WeChat public platform provides an online testing platform through which the interaction between fans and the public account can be simulated.

Insert picture description here

  FromUserName When configuring the WeChat official account, you can see it in the basic configuration menu bar.

  After the configuration is correct, click the 检查问题button below , if nothing happens, you will get the following information:

Insert picture description here
  Sending a message to the WeChat official account, it seems that the emoji is also of the texttype:

Insert picture description here

  OK! Very nice! ! !

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_42730750/article/details/112366788