细数Python Flask微信公众号开发中遇到的那些坑

0 评论
/ /
1295 阅读
/
8859 字
30 2018-07
最近两三个月的时间,断断续续边学边做完成了一个微信公众号页面的开发工作。这是一个快递系统,主要功能有用户管理、寄收件地址管理、用户下单,订单管理,订单查询及一些宣传页面等。本文主要细数下开发过程中遇到的各种坑,也算是另外一种总结吧。

1. 开发语言及框架

Python + Flask + Bootstrap,数据库使用的是MySQL
 

2. 相关文档及Lib库

1) Bootstrap官方文档 http://v3.bootcss.com/getting-started/
2) 微信公众号开发文档 https://mp.weixin.qq.com/wiki
 

3. 那些坑

3.1 微信

3.1.1 微信登陆

首先你需要仔细阅读官方文档,简单来说微信登陆有如下几步:
1) 生成微信认证跳转URL,注意有`snsapi_base`跟`snsapi_userinfo`两种方式,前者是静默授权只获取用户openid,后者需要用户手动同意获取用户基本信息
2) 获取access_token
3) 获取用户信息
 
解决微信OAuth2.0网页授权只能设置一个回调域名的问题,参考 https://github.com/HADB/GetWeixinCode

3.1.2 模版消息

登陆微信公众平台 -> 功能 -> 模版消息,选择右侧模版消息接口文档 ,即可查看详细的接口文档。
主要步骤如下:
1)获取access_token,其中token有效期为7200s,而且微信限制了每天的调用次数,这里使用functools.lru_cache维护了一个token的内存缓存
2)获取模版ID
3)请求接口
POST URL: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
POST Data: 请求包为json
 

3.2 MySQL

3.2.1 编码问题

MySQL遇到最大的坑还是编码问题,因为涉及到获取微信用户名含有各种emoji表情的问题,需要设置字符编码为utf8mb4,具体可以参考这篇文章(https://mathiasbynens.be/notes/mysql-utf8mb4),然而设置成功在Flask SQLAlchemy配置app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘mysql://root@localhost:3306/test?charset=utf8mb4’后,运行报错sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (2019, “Can’t initialize character set utf8mb4 (path: C:\\mysql\\\\share\\charsets\\)”),解决无果。
最终解决方案是:
1) Flask SQLAlchemy配置app.config[‘SQLALCHEMY_DATABASE_URI’] = ‘mysql://root@localhost:3306/test?charset=utf8’
2) 微信用户名写入数据库时使用repr()方法将写入原始unicode字符,读取的时候再使用eval()进行转换
 

3.2.2 SQLAlchemy查询数据转换为Dict

for u in session.query(User).all():

    u = dict(u.__dict__)

    u.pop(‘_sa_instance_state’, None)
参考文章:
 

3.4 Flask

3.4.1 cookie相关

1) 设置cookie
@app.route('/set_cookie') 
def set_cookie(): 
    response=make_response('Hello World'); 
    response.set_cookie('Name','Joo')  
    return response
 
2) 获取cookie
@app.route('/get_cookie') 
def get_cookie(): 
    name=request.cookies.get('Name')  
    return name
 
3) 删除cookie
 
设置过期时间为0
@app.route('/del_cookie') 
def del_cookie(): 
    response=make_response('delete cookie') 
    response.set_cookie('Name','',expires=0)  
    return response
 
使用delete_cookie方法
@app.route('/del_cookie')
def del_cookie():
    response = make_response('delete cookie')
    response.delete_cookie('Name')
    return response
 

3.4.2 flask.make_response() 实例

3.4.3 详细解读Jquery各Ajax函数:$.get(),$.post(),$.ajax(),$.getJSON()

3.4.4 bootstrap对话框插件

3.4.5 Flask flash增加link

3.4.6 HTML颜色编码

3.4.7 Python缓存

微信获取access_token时有效期是7200s,而且微信限制了每天的调用频率(2000次/天),所以简单使用lru_cache在内存中维护了一个token缓冲,示例代码如下:

@lru_cache(None)
def getAccessToken():
    url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}'.format(app_id, app_secret)
    r = requests.get(url)
    access_token = r.json().get('access_token')
    time_now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    print '[{0}] getAccessTokenResult:\t{1}'.format(time_now, r.text)
    return access_token, datetime.now()

def getToken():
    token, t = getAccessToken()
    if (datetime.now()-t).seconds > 3600:
        getAccessToken.cache_clear()
        token, t = getAccessToken()
        return token
    else:
        return token