0%

使用 Flask 实现微信公众号自动回复 Bot

人都是被逼出来的,业务突然来了的时候才能感到全速赶工的效率。这里记录一下如何用 10 分钟快速配置一个微信公众号自动回复机器人。

一些准备工作

首先需要关闭微信提供的自动回复功能,然后登录微信公众平台,前往开发者配置的基本配置。

  • URL :在这里输入你的接口地址,在下方的例子中,是 https://url/wechat。
  • Token:你可以自己输入 Token,用于验证。
  • EncodingAESKey:随机生成就好,同样用于验证。
  • 消息加密方式:只要采用了 https 协议,明文模式也已经足够安全。为了便于开发调试我直接使用了明文方式。

快速让后端跑起来

需求很重要。没有必要在部署和非逻辑层上花费太多时间。下面是我使用的框架,在 get_reply(msg) 中写下你的业务逻辑就好。

对于比较复杂的项目,你可以考虑把一些方法拆分单独的文件中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import hashlib
from flask import *
import xml.etree.ElementTree as ET

app = Flask(__name__, static_url_path='/static')
WECHAT_TOKEN = 'YOUR TOKEN'
AES_KEY = 'YOUR AES KEY'

def get_reply(msg):
return 'You can write your own handler here.'

def send(to_user, from_user, content):
reply = """
<xml><ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag></xml>
"""
response = make_response(reply % (to_user, from_user,
str(int(time.time())), content))
response.content_type = 'application/xml'
return response

@app.route('/', methods=['POST', 'GET'])
def index():
return 'You can write your own index page.'

@app.route('/result', methods=['GET'])
def export():
return app.send_static_file('result.html')

@app.route('/wechat', methods=['POST', 'GET'])
def wechat_post():
if (request.method == 'GET'):
# 验证信息
data = request.args
signature = data.get('signature', '')
timestamp = data.get('timestamp', '')
nonce = data.get('nonce', '')
echostr = data.get('echostr', '')
s = sorted([timestamp, nonce, WECHAT_TOKEN])
# 字典排序
s = ''.join(s)
if hashlib.sha1(s.encode('utf-8')).hexdigest() == signature:
# 判断请求来源,并对接受的请求转换为utf-8后进行sha1加密
response = make_response(echostr)
return echostr
return 'Only requests from wechat will be accepted.'

if(request.method == 'POST'):
xml = ET.fromstring(request.data)
toUser = xml.find('ToUserName').text
fromUser = xml.find('FromUserName').text
msgType = xml.find("MsgType").text
if msgType == 'text':
# 文本消息
content = xml.find('Content').text
reply = get_reply(content)
return send(fromUser, toUser, reply)
elif msgType == 'event':
# 关注消息
return send(fromUser, toUser, 'Write your own follow message here.')
else:
return send(fromUser, toUser, "非文字消息。")
return 'Unexpected handler.'


if __name__ == '__main__':
app.run(host='0.0.0.0', threaded=True)

用 Apache 部署起来

在项目根目录下新建一个 wsgi 文件,写入配置,修改成你的部署目录:

1
2
3
4
5
6
7
8
#! /usr/bin/python3.6

import logging
import sys
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, '/var/www/seeyoubot') # Your own deploy path
from server import app as application
application.secret_key = 'just_a_secret_key' # Anything you want

接着上传项目,在 Apache 的配置文件(通常位于 /etc/apache2/sites-enabled )下的新增一个 conf 文件,写入以下配置。修改一下 ServerNameWSGIScriptAliasDirectory 成你的工程位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<VirtualHost *:80>
# Add machine's IP address or your subdomain
ServerName yourserver.com
# Give an alias to to start your website url with
WSGIScriptAlias / /var/www/seeyoubot/seeyoubot.wsgi
<Directory /var/www/seeyoubot/>
# set permissions as per apache2.conf file
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

接下来service apache2 restart,回到微信公众平台点击提交,你应该已经可以提交成功了。现在你可以专注于处理回复消息的逻辑了。

References

https://zhuanlan.zhihu.com/p/50801694
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html

青年节到了,顺祝节日快乐。

Welcome to my other publishing channels