前言
公众号后台使用Python Flask进行快速开发,核心代码不到100行。因此,开源这个应用的目的也只是为了将其作为一个微信公众号自动回复的HelloWorld
项目,给感兴趣的同学提供一点参考。
微信API
微信API是微信公众平台为有开发能力的用户提供的工具和接口,开发的介绍可以参考微信的开发者文档。开发公众号后台需要一个公网的服务器,用户在对公众号进行关注、发送消息时,微信后台会将对应的事件和信息以结构化数据(XML)的方式发送到我们配置的公网服务器上,根据文档中定义的格式封装响应就可以事件自定义的自动回复了。
微信的API除了包括公众号后端的消息接口,还包括客户端的jsapi,后者我们暂时不会涉及到。
签名
当普通微信用户向公众账号发消息时,微信服务器将POST消息的XML数据包到开发者填写的URL上。理论上直接解析也可以,但实际上请求还带有请求数据的签名。一方面是防止上传数据被中间篡改,更重要的另一方面是验证消息来源的真实性,确保消息都是来自合法的微信的服务器。
在官网中给了一个PHP的示例,这里看下python的例子:
def verify_request(request):
signature = request.args.get('signature', '')
timestamp = request.args.get('timestamp', '')
nonce = request.args.get('nonce', '')
echostr = request.args.get('echostr', '')
data = [MP_TOKEN, timestamp, nonce]
data.sort()
calc_sig = hashlib.sha1(''.join(data).encode()).hexdigest()
if calc_sig == signature:
return echostr
else:
print('Invalid message: signature error!')
return None
其中MP_TOKEN
就是公众号开发者后台的token。上面代码很简单,就是将token、时间戳和随机数组合进行SHA1哈希,并与请求的哈希进行比对。
自动回复
在开发者文档中接收普通消息一节介绍了微信服务器发送的用户发送消息所呈现的格式,示例XML请求数据如下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
使用Python自带的lxml等模块提取所需要的内容,进行处理,并构建对应的返回即可实现自动回复。响应同样是XML格式,示例响应如下:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>
上面的响应给发送消息的用户回复文本消息“你好”,对应其他类型的消息,如图片、语音、视频、图文消息等,可以参考文档中的被动回复用户消息部分。
The Code
在报价机器人公众号中,我将用户发送的消息通过API请求的方式到电子货币交易网站上查询对应的电子货币价格、涨幅、交易量信息,并以文本消息的方式返回给用户。这里值得一提的是,并不是每个用户请求我都会进行在线查询,而是设置一定的时间窗口,在此期间的用户请求直接返回缓存数据,这样可以减轻各方服务器的压力。
最终的完整代码见Gitee,运行前需要修改data/token.txt
文件,内容是微信公众平台后台中自行定义的token。最终实现效果如下:
感兴趣的小伙伴也可以微信扫码体验:
后记
之前我测试用的公众号名为“报价机器人”,主要用来查询电子货币价格。本想新建一个账号用于更新文章,但由于微信要求一个身份只能注册一个订阅号,所以就只能将其占用了。因此把报价机器人的代码也公开,方便有需要的小伙伴自行搭建。
未来公众号会改个名字,并不定时更新一些关于网络安全的杂谈。而比较专业的技术文章视情况还是会放到博客上,毕竟手机还是不太适合作为严肃学习研究的工具。