tornado开发的页面跳转到微信小程序

官方也有一些资料,网上也有不少资料,但是抄起来,不少坑,而且我这边还是python写的,阻力更大,还是我自己总结一下,能给他人带来遍历,那就算欣慰的了。
使用tornado的问题,要注意文件上传到centos上直接覆盖,重启不一定会生效,这个问题花了我2小时。
1 微信公众号-功能设置
注意这里的业务、JS接口安全、网页授权域名,如果加了www.test.cn/mp路径之类,会提示invalid domain,所以最好还是根目录
2
于是,配置路由的时候

(r'/MP_verify_2ge90RVBsxxxx.txt',WxJsCheckHandler),

代码比较简单,也就是将微信授权的文件,返回就可以。

from tornado import web
class WxJsCheckHandler(web.RequestHandler):

    def get(self):
        self.write("2ge90Rxxxx")

2 微信签名
这个页面上会用到,通过h5页面跳转到小程序需要微信公众号授权

import redis
import string
import random
import time
import json
import requests
import hashlib
from settings import ENV,REDIS_CONFIG,WX_CONFIG

pool = redis.ConnectionPool(host=REDIS_CONFIG[ENV]['host'], port=REDIS_CONFIG[ENV]['port'], db=REDIS_CONFIG[ENV]['db'])
r = redis.StrictRedis(connection_pool=pool)

class WxService():

    def __init__(self):
        self.wx_url = 'https://api.weixin.qq.com/cgi-bin'

    def _create_nonce_str(self):
        return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))

    def _create_timestamp(self):
        return int(time.time())

    def get_token(self):
        ACCESS_TOKEN = r.get('wx:ACCESS_TOKEN')
        if ACCESS_TOKEN:
            return ACCESS_TOKEN
        else:
            token_url = self.wx_url + '/token?grant_type=client_credential&appid={}&secret={}' \
                .format(WX_CONFIG['appid'],WX_CONFIG['secret'])
            res = requests.get(token_url)
            print('请求微信的token is {}'.format(res.text))
            token = json.loads(res.text)
            ACCESS_TOKEN = token.get("access_token")
            r.set('wx:ACCESS_TOKEN', ACCESS_TOKEN, 7200)
            return ACCESS_TOKEN

    def get_ticket(self):
        ticket = r.get('wx:ticket')
        if ticket:
            tic = str(ticket, encoding='utf-8')
            return tic
        else:
            token = self.get_token()
            ticket_url = self.wx_url + "/ticket/getticket?access_token={}&type=jsapi".format(token)
            res = requests.get(ticket_url)
            js_ticket = json.loads(res.text)
            ticket = js_ticket.get('ticket')
            r.set('wx:ticket', ticket, 7200)
            return ticket

    def sign(self,url):
        jsapi_ticket = self.get_ticket()
        ret = {
            'nonceStr':self._create_nonce_str(),
            'jsapi_ticket': jsapi_ticket,
            'timestamp':self._create_timestamp(),
            'url':url
        }
        string = '&'.join(['%s=%s' % (key.lower(), ret[key]) for key in sorted(ret)]) # 根据字符的ASCII值进行排序,拼接
        ret['signature'] = hashlib.sha1(string.encode('utf-8')).hexdigest() # 对字符串进行sha1加密
        return ret

配置路由

(r"/wx/sign",WxSignHandler),

3 前端页面

 # web
    settings = {
        'debug': True,
        'static_path':os.path.join(os.path.dirname(__file__), 'static'),
        'template_path':os.path.join(os.path.dirname(__file__), "views")
    }
    # app
    app = web.Application([
        (r'/MP_verify_2xxxxsxxxx.txt',WxJsCheckHandler),
        (r'/js/(.*)',web.StaticFileHandler,{'path':'assets/js'}),
        (r"/test/xcx",ToTestXcxHandler),
        (r"/test/order/add",OrderHandler),
        (r"/wx/sign",WxSignHandler),
        web.url(provider.authorize_path,TokenHandler,dict(provider=provider)),
        web.url(provider.token_path,TokenHandler,dict(provider=provider)),
        ],
        **settings
    )
   

h5页面,signature,timestamp,nonceStr并不是随便填的,signature是会被微信公众号验签的,这一点特别要注意。
参考了公众号h5网页跳转小程序,但也被误导了,随机数、时间戳与签名是由关系的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎使用</title>
    <style>
        .home {
            position: relative;
            width: 100%;
            height: 100vh;
        }
        .logo-wrap {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            width: 100%;
            height: 400px;
        }
        .content {
            position: absolute;
            bottom: 123px;
            width: 100%;
            display: flex;
            justify-content: center;
        }
        .tip {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            position: absolute;
            bottom: 32px;
            width: 100%;
            height: 14px;
            color: #666;
            line-height: 14px;
            font-size: 10px;
        }
    </style>
    <script src="/js/jquery-3.6.0.min.js"></script>
    <script src="/js/jweixin-1.6.0.js"></script>
</head>
<body>
    <div class="home">
        <div class="logo-wrap" id="logoUrl">
            <img src="/static/logo.jpg" style="width:120px;height: 120px"/>
            <div>欢迎使用</div>
        </div>
        <div class="content" id="content">
        </div>
        <div class="tip">
            <div>微信版本要求为:7.0.12及以上</div>
            <div>系统版本要求为:iOS 10.3及以上、Android 5.0及以上</div>
        </div>
    </div>
    <script>
        getUrlParam = function (name) {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
            var r = window.location.search.substr(1).match(reg);
            if (r != null) return unescape(r[2]); return null;
        }
        href = window.location.href.split('#')[0]
        console.log(href)
        console.log(window.location.href)
        nsrsbh = getUrlParam('nsrsbh')
        // alert('nsrsbh is '+ nsrsbh)
        console.log('nsrsbh is '+ nsrsbh)
        $.ajax({
            url: '/wx/sign',
            type: 'POST',
            data: JSON.stringify({
                appId: '微信公众号的appid',
                url: href
            }),
            async: false,
            dataType: "json",
            contentType : "application/json;charset=UTF-8",
            success: function (res) {
                console.log(JSON.stringify(res.data))
                if (res) {
                    wx.config({
                        debug: false,
                        appId: '微信公众号的appid',
                        timestamp: res.data.timestamp,
                        nonceStr: res.data.nonceStr,
                        signature: res.data.signature,
                        jsApiList: ['scanQRCode'], // 必填,随意一个接口即可
                        openTagList:['wx-open-launch-weapp'], // 填入打开小程序的开放标签名
                    })
                    wx.ready(function (){
                        console.log("微信环境准备成功");
                        getContent();
                    })
                    wx.error(function (res) {
                        console.log("微信环境准备失败,原因:"+ res);
                    });
                }
            },
            error: function(err){
                console.log("后台接口获取签名异常,原因:", error);
            }
        })
        getContent = function (){
            var color = "#d02329";
            var buttonStyle = "width: 343px; height: 200px; color: #FFFFFF; border-radius: 27px; border: 1px solid " + color +"; "
                +"background-color: #07ba22; font-size:32px";
  
            var content = '';
            var weappurl = "/pages/index/test?nsrsbh="+nsrsbh;
            var id = "launch-btn";
            content += '<wx-open-launch-weapp id="'+id+'" username="'+"微信小程序的原始ID gh_xxx"+'" path="'+weappurl+'">';
            content += '<template>';
            content += '<button style="'+buttonStyle+'">打开小程序</button>';
            content += '</template>';
            content += '</wx-open-launch-weapp>';
            $("#content").html(content);
            var btn = document.getElementById( 'launch-btn');
            btn.addEventListener( 'launch', function(e) {
                console.log("调起成功", e.detail);
            });
            btn.addEventListener( 'error', function(e) {
                console.log("调起失败:", e.detail);
            });
        }
    </script>
</body>
</html>
class ToTestXcxHandler(BaseHandler):

    def get(self):
        self.render("test.html")

4 微信公众号关注自动回复
<a href='https://www.test.cn/test/xcx?nsrsbh=123456789'>欢迎使用</a>
1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warrah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值