Article Directory
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
- Log in to the official WeChat public account platform , scroll down to the bottom of the page, and click Basic Configuration
- Click on modify configuration on the right and fill in the corresponding information
URL: http://服务器公网IP/wx
Token: 自己设置一条字符串
EncodingAESKey: 随机生成就可
消息加解密方式: 为方便调试,暂时选择明文模式
2. Verify the source of the information
After the above information is filled in, choosing to submit will trigger a GET
request to verify the Token. The logic diagram of the verification is as follows:
Below we views.py
implement 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 xml
following 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 , voice etc. |
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 xml
content 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:
Let's continue views.py
to 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 elif
to 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
- Open Postman, use the
POST
request, andBody
fill in thexml
message we need to send in the menu bar . The specific configuration information is shown in the figure below
- After filling in, click
Send
send, we will receive the returned information in the response information column below
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
uWsgi
andNginx
oh!
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.
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:
Sending a message to the WeChat official account, it seems that the emoji is also of the text
type:
OK! Very nice! ! !