zoukankan      html  css  js  c++  java
  • 细数Python Flask微信公众号开发中遇到的那些坑

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

    1. 开发语言及框架

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

    2. 相关文档及Lib库

    2) 微信公众号开发文档 https://mp.weixin.qq.com/wiki
    4) PDF 《FlaskWeb开发:基于Python的Web应用开发实战》

    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}] getAccessToken Result:	{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

    参考:

     

    3.4.8 修改Bootstrap使用国内源

    由于默认Bootstrap使用的CDN是http://cdnjs.cloudflare.com,国内访问较慢,所以需要修改默认CDN为国内源。
    找到C:Python27Libsite-packagesflask_bootstrap\__init__.py(C:Python27 为你当前Python版本路径),在文件最后找到如下代码:
            bootstrap = lwrap(
                WebCDN('//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/%s/' %
                       BOOTSTRAP_VERSION), local)
    
            jquery = lwrap(
                WebCDN('//cdnjs.cloudflare.com/ajax/libs/jquery/%s/' %
                       JQUERY_VERSION), local)
    
            html5shiv = lwrap(
                WebCDN('//cdnjs.cloudflare.com/ajax/libs/html5shiv/%s/' %
                       HTML5SHIV_VERSION))
    
            respondjs = lwrap(
                WebCDN('//cdnjs.cloudflare.com/ajax/libs/respond.js/%s/' %
                       RESPONDJS_VERSION))
    替换为国内源cdn.bootcss.com,代码如下:
            bootstrap = lwrap(
                WebCDN('//cdn.bootcss.com/twitter-bootstrap/%s/' %
                       BOOTSTRAP_VERSION), local)
    
            jquery = lwrap(
                WebCDN('//cdn.bootcss.com/jquery/%s/' %
                       JQUERY_VERSION), local)
    
            html5shiv = lwrap(
                WebCDN('//cdn.bootcss.com/html5shiv/%s/' %
                       HTML5SHIV_VERSION))
    
            respondjs = lwrap(
                WebCDN('//cdn.bootcss.com/respond.js/%s/' %
                       RESPONDJS_VERSION))
    参考资料:
     

    3.4.9 flask部署

    flask通常在Linux上部署方式是 flask + wsgi + nginx,windows上则是flask + iis + nginx。这里实际部署的环境是Windows Server 2007,由于项目实际访问量较小的关系,最终选用简单的flask + tornado部署方式。
    在flask项目里原来的入口程序假设为run.py的同级目录添加tornado_server.py,内容如下:
    # coding:utf-8
     
    from tornado.wsgi import WSGIContainer
    from tornado.httpserver import HTTPServer
    from tornado.ioloop import IOLoop
    from run import app
    http_server = HTTPServer(WSGIContainer(app))
    
    # address为实际访问URL,port为端口号
    http_server.listen(port=5000, address="127.0.0.1")
    IOLoop.instance().start()
    使用python tornado_server.py即可启动。
     
    参考文档:
  • 相关阅读:
    Scan image with TWAIN scanner and insert into Rich Text (R5/Win32)
    软件测试工具汇总
    domino升级602>651
    domino SMTP验证LDAPPOP3的实现
    domino升级602>651>851
    DOMINO中的内置域
    Attaching and importing image files in one click
    传西门子中国运营中近一半业务涉及行贿 沧海
    IT程序员:如何化蛹为蝶? 沧海
    年度个人职业规划秘笈 沧海
  • 原文地址:https://www.cnblogs.com/lovesoo/p/8427697.html
Copyright © 2011-2022 走看看