前言
之前用flask开发微信公众号时,遇到了诸多问题。因此,写下问题的解决方案供大家参考。
服务器
开发微信公众号需要一个能够提供公网ip的服务器,我直接在腾讯云买了服务器。当然大家也可以使用其他办法,比如花生壳,可以实现动态域名解析,从而让外网也可以访问本地服务器。
购买服务器后,需要配置生产环境,建议使用docker打包自己的开发环境,或者拉取别人的镜像,免去配置环境的烦恼,这样后续的python、nginx等应用程序可以直接通过docker使用。
验证
根据微信公众号平台给出的开发文档,接入微信公众平台开发,开发者需要按照如下步骤完成:
- 填写服务器配置
- 验证服务器地址的有效性
- 依据接口文档实现业务逻辑
开发步骤
第一步、填写服务器配置
在基本配置一栏,点击修改配置,可以看到如下画面:
URL示例:http://公网ip/路由路径
Token:自己可以设置任意字符
第二步、验证消息的确来自微信服务器
开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
- 将token、timestamp、nonce三个参数进行字典序排序
- 将三个参数字符串拼接成一个字符串进行sha1加密
- 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
检验signature的python示例代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, request, abort
import hashlib
# 微信的token令牌
WECHAT_TOKEN = "test"
app = Flask(__name__)
@app.route('/wechat', methods=["GET"])
def wechat():
"""对接微信公众号服务器"""
signature = request.args.get("signature")
timestamp = request.args.get("timestamp")
nonce = request.args.get("nonce")
echostr = request.args.get("echostr")
# 校验参数
if not all([signature, timestamp, nonce]):
abort(400)
# 按照微信的流程进行计算签名
array = [WECHAT_TOKEN, timestamp, nonce]
# 排序
array.sort()
# 拼接字符串
tmp_str = "".join(array)
# 进行sha1加密,得到正确的签名值
sign = hashlib.sha1(tmp_str.encode("utf-8")).hexdigest()
print(sign == signature)
# 将自己计算的签名值与请求的签名参数进行对比
if signature != sign:
abort(403)
else:
return echostr
if __name__ == '__main__':
app.run(port=8000, debug=True)
需要注意的是:网络上有一些代码没有转码的步骤,但是实际测试中需要将拼接的字符串tmp_str转为utf-8。
开发文档中注明,http对应80端口,https对应443端口,因此flask运行时必须通过上述两个端口。在此,我选择80端口,但是在开发测试中,访问80端口存在异常,即使在打开了腾讯云服务器的安全组端口访问权限,依然无法解决问题。因此,同时考虑到后续可能存在多个开发实例,我在服务器上安装了nginx,通过nginx(80端口)来进行分发。因此,开启nginx服务后,代码里flask的端口可以自行决定。
第三步:依据接口文档实现业务逻辑
现在就可以进行业务开发了,关于业务逻辑不再赘述。
参考:微信公众号开发文档