本文面向有初步 python 语言基础的用户,详细描述了如何利用 flask 框架实现一个处理 POST 信息的 web api, 用以给 WxPusher 提供事件回调地址,获取用户在微信公众号 WxPusher消息推送平台
中的上行信息。
上一篇文章《python 收发微信之一:利用 WxPusher 的 web api 及 python SDK 两种方式给自己发微信》描述了如何让用户接收微信信息,随之而来的一个需求就是,用户反馈回来的信息怎么处理。比如有个自动化的维保任务,进行到一半出现需要人工选择的时候,用户如果可以通过微信直接返回信息,让程序按用户选择进行下去,是不是就比较方便。
WxPusher 提供了一个功能,称为上行信息,是指用户在 WxPusher 微信公众号里手工发送的信息,如果用户发送的信息以 #AppId 开头,则该信息被认为是用户发送到 WxPusher 下注册的特定应用的上行信息。WxPusher 经由 web api 将上行信息 post 过来。因此我们需要做的事情如下:
下面开始描述具体的做法。本文假设用户具备一定的 python 基础,对 python 的安装、模块的安装、语法、生产服务器的部署等不予进一步解释。为简化示例代码,我们只是将上行信息保存到一个文本文档中,不做额外处理。
方法很多,可以去各商业云平台购买虚拟机,也可以通过各种内网穿透技术通过光猫对外提供服务,具体描述略。
Flask 是 python 的一个 web 框架,提供了简洁的语法用以实现 web 各方面功能。在确保正常安装 python 与 Flask 最新版后,我们首先实现一个最小化的 http 服务,用以验证我们的代码可以被互联网正常访问。代码如下:
import json
from flask import Flask
app = Flask(__name__)
@app.route("/") # 指定用户访问的相对地址
def hello_world():
return "Hello world!
" # 这里就是用户看到的最终页面
if __name__ == '__main__':
app.run(port=8080, debug=True, host='0.0.0.0')
简单解释一下最后一句app.run(port=8080, debug=True, host='0.0.0.0')
:
port 是服务端口,可以根据实际需求进行修改
debug 选项开启调试模式,可以让 flask 在代码修改后自动刷新服务
host 选项指定服务绑定的 IP,0.0.0.0 表示绑定本机所有IP
验证本地服务成功开启。将上述代码保存为 simple_flask_server.py
,在命令终端里运行 python simple_flask_server.py
,在本机使用浏览器打开 http://127.0.0.1:8080
这个地址,应该可以看到Hello world!
这个简单的页面。该页面使用 flask 自带的调试服务提供web 服务,只能用于开发。
验证远程服务成功开启。然后我们可用一台与前述服务器不在一个局域网的计算机(比如使用移动网络的智能手机),使用浏览器访问 http://服务器IP:8080
(比如 http://1.2.3.4:8080
),如果也看到Hello world!
页面,恭喜你,软硬件基础打好了,可以进行下一步了。
参考WxPusher的上行信息文档,上行信息的接收使用POST方法,数据格式如下:
{
"action":"send_up_cmd",//动作,send_up_cmd 表示上行消息回调,后期可能会添加其他动作,请做好兼容。
"data":{
"uid":"UID_xxx",//用户uid
"appId":97, //应用id
"appKey":null,//废弃字段
"appName":"WxPusher演示",//应用名称
"userName":"",//新用户微信不再返回 ,强制返回空
"userHeadImg":"",//新用户微信不再返回 ,强制返回空
"time":1603002697386,//发生时间
"content":"内容" //用户发送的内容
}
}
我们继续使用 flask 构建最小化 POST
服务,代码如下,我添加了大量注释方便理解:
import json
import time
from flask import Flask, jsonify, request
API = '/api/for_wxpusher_post' # 回调地址,可以随意编制
app = Flask(__name__)
@app.route(API, methods=['POST']) # 指定服务地址、服务类型
def get_send_up_cmd():
'''通过回调接口,获取上行消息,写入文本文件'''
datas = json.loads(request.data) # 接口传入的数据
action = datas['action'] # 上行信息类别
user_time = convert_time_format(datas['data']['time']/1000) # 用户发信息的时间
user_data = datas['data']['content'] # 用户的上行信息
if action == 'send_up_cmd':
# 本示例只是将上行消息写入文本文档,可在此处添加其他功能
with open('logs.txt', 'a', encoding='UTF-8') as f:
f.write(f'{user_time} {user_data}\n') # 不得不再提一句,python 的 f 字符串真好用
return jsonify({'code':0, 'status':'ok'}) # 一定要有返回值,不然 flask 会报错
def convert_time_format(t):
'''将 WxPusher 提供的数值时间,转换成人类友好型字符串
比如 1603002697386 --> "2020-10-18 14:31:37" '''
return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(t/1000))
if __name__ == '__main__':
app.run(port=8080, debug=True, host='0.0.0.0')
将上述代码保存、运行之,即可进行下一步。代码在 win10 x64、python3.10.4、flask2.1.2 下调试通过。
假如我们的服务器对外提供服务的IP为 1.2.3.4
,服务端口为 8080
,wei api 如步骤3代码所示为 /api/for_wxpusher_post
,则需要提供给 WxPusher 的事件回调地址
为http://1.2.3.4:8080/api/for_wxpusher_post
,填入 WxPusher 的应用管理–应用信息的事件回调地址
中即可。
打开手机微信APP,找到 WxPusher消息推送平台
公众号,发送 #1234 消息
(其中 1234
是你注册的 WxPusher 应用的 AppId),则我们服务器后台的 logs.txt 文件就会被写入一行类似 2022-05-13 08:10:11 消息
这样的文本。
至此,整个流程调试通过了。此后可以根据需要,添加自己的控制代码,最后将 Flask 代码正式部署到服务器的生产环境上,一切就ok了。