微信网页开发

套用《围城》里老学究的的一句开场白:"兄弟我刚入行的时候…“兄弟我是很不喜欢微信这样一款应用的——尽管我在2011年就已经是微信的注册用户。在我看来,第一个,能用qq达到的目的为什么还要微信?其次,凭什么一个开发要绑在一款微信里?但是,周边的人似乎在我毕业的前后通通用上了微信。

我的第一个老板,也非常喜欢微信。她给我第一份工作,就是运营一个微信公众号,持续至今。

我上一个老板,则给我安利了一部叫《创业时代》的商战电视剧。讲的就是另外一条平行世界线里,一款类似微信的语音即时通讯软件创业的故事。

这大概是2007年之后影响我最大的电视剧——尽管这部电视剧只有6分多的评分,尽管我2007年之后没看过电视剧。

扯远了。

本文延续上一讲的程序进行实验。需要安装微信web开发工具。

  1. auth2.0授权
  2. jssdk
  3. 科学算命应用

网页auth2.0鉴权

官方资料 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842 npm库 https://github.com/node-webot/wechat-oauth 阮一峰的OAuth2 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

网页授权原理:

(A)用户访问客户端,客户端将前者导向认证服务器。

(B)用户选择是否给客户端授权

(C)如果用户授权,认证服务器将用户导向客户端指定的重定向uri(redirection URI),同时附上授权码

(D)客户端收到授权码,附上之前的重定向uri,向认证服务器申请令牌,

(E)认证服务器核对了授权码和URi,向客户端发送令牌包括访问令牌(access_token)和更新令牌(refresh_token)。

微信做auth2.0认证需要以下信息:

在此处配置你的域名:

配置JS安全接口:

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432

注意,这里的配置域名都不需要加http://,后面也不能带/

微信授权登录

调用第三方服务器接口—>导向到微信服务器认证—>第三方认证—>成功后回调微信code。

需要引入一个新的co-wecaht-oauth库。

首先我们写一个前端请求方法。比如说,我点击一个按钮,跳转到一个/wxAuthorize下的微信认证页面。然后成功了的话,跳转回/wxCallback那么后端就要写一个路由:

// index.js
const const Oauth=require('co-wechat-oauth');
const oauth=new Oauth(config.appid,config.appsecret);

router.get('/wxAuthorize', async (ctx, next) => {
    //重定向到微信界面
    const state = ctx.query.id;
    // const target = ctx.href
    console.log('ctx...' + ctx.href);

    // 目标地址
    let redirectUrl = ctx.href;
    redirectUrl = redirectUrl.replace('wxAuthorize', 'wxCallback')
    const scope = 'snsapi_userinfo'

    // 导向微信认证页面
    var url = oauth.getAuthorizeURL(redirectUrl, state, scope);
    console.log('url' + url)
    ctx.redirect(url)

})

跳转的接口写一下:

router.get('/wxCallback',async (ctx, next) => {
    const code = ctx.query.code
    console.log('callback:', code)
    const token=await oauth.getAccessToken(code);
    const access_token=token.data.access_token;

    const openid=token.data.openid;
    console.log(token);
    // 接着让丫跳转到一个认证后的界面:带上openid

})

点击用户登录按钮:

同意之后就跳转了wxCallback,还有了一个授权码:

现在我就完成了第一步功能。

认证完了。有了access_token和openid,就可以肆意搞起来了。

获取用户信息

微信用户的公开信息包括:

router.get('/authed',async (ctx,next)=>{

再执行流程:

用户信息就拿到了。

openid对于前端来说是没有用的。真正需要的其实是后端。如果一个后端老是要你发openID给他,那就是他的问题了。因此上面的例子是把openid放到链接里。其实是不合理的。

全局票据的缓存

这里的access_token是和服务器端的access_token不太一样,服务器端的只需要一个就好了。但是网页端的。每个用户登录都会产生一个token。

还是得存在mongodb里。

修改mongoose.js,添加如下内容:

// ClientAccessToken
schema = new Schema({
    access_tokeåån: String,
    expires_in: Number,
    refresh_token: String,
    openid: String,
    scope: String,
    create_at: String
});
// 自定义getToken方法
schema.statics.getToken = async function (openid) {
    return await this.findOne({
        openid: openid
}); };
schema.statics.setToken = async function (openid, token) { // 有则更新,无则添加
const query = {
        openid: openid
    };
    const options = {
        upsert: true
};
    return await this.updateOne(query, token, options);
};
exports.ClientToken = mongoose.model('ClientToken', schema);

上面这一段添加了两个方法:查询和更新。

然后在new出Oauth的时候调用这两个方法:

const { ServerToken, ClientToken } = require('./mongoose');
const Oauth = require('co-wechat-oauth');
const oauth = new Oauth(
    config.appid,
    config.appsecret,
    async function (openid) {
        return await ClientToken.getToken(openid)
    },
    async function (openid, token) {
        return await ClientToken.setToken(openid, token)
    }
);

好了。你每次登录之后,就产生了一个token存到了mongo的clienttoken表里了。如果你要调用,就可以使用ClientToken.getToken(openid)获取。

微信JS-SDK

官方资料:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 npm库: https://github.com/node-webot/co-wechat-api

所谓微信JS-SDK,就是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包。node操作这个,已经有封装好的调用了,就是上一讲的co-wechat-api。

通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。

简单说,网页想调用设备端的一些特性?微信帮你做。前提是获得授权。这个过程是微信认证我们开发的网页。

微信给前端的设备能力(扫码可看):

我们看文档:

首先是配置jssdk,然后是引入js文件http://res.wx.qq.com/open/js/jweixin-1.4.0.js(前两步已做),会生成一个wx对象。接下来就是在前端做配置:

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [] // 必填,需要使用的JS接口列表
});

问题在于,这些乱七八糟的东西前端都没有。

获取配置

写一个请求方法和接口:

// 前端
const res=await axios.get('/getJsConfig',{
    params:{
          //把你的url参数带上!
        url:window.location.href
    }
});
console.log(res.data)

//后端
router.get('/getJsConfig', async ctx => {
    console.log('getJSSDK...', ctx.query)
    var res = await api.getJsConfig(ctx.query);
    console.log('res', res)
    ctx.body = res
})

申请权限

拿到配置后,我们继续修改前端要让网页拿到onMenuShareTimelineonMenuShareAppMessage的授权:

res.data.jsApiList = ['onMenuShareTimeline', 'onMenuShareAppMessage']
wx.config(res.data);
wx.ready(function (e) {
    console.log('wx.ready......',e)
});

jsApiList参考 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 附录2

在微信开发者工具上看到:

接口就申请成功了。

实例:科学算命

现在一个乙方给你一个任务:我要做一个科学算命的应用。需要分享之后才能看到结果。应该怎么搞?

首先是点击get一个路由/test_wxAuthorize,登录后跳转share.html

router.get('/test_wxAuthorize', async (ctx, next) => {
    const state = ctx.query.id;
    // 目标地址
    let redirectUrl = ctx.href;
    redirectUrl = redirectUrl.replace('wxAuthorize', 'share.html')
    const scope = 'snsapi_userinfo'

    // 导向微信认证页面
    var url = oauth.getAuthorizeURL(redirectUrl, state, scope);
    ctx.redirect(url)
});

然后让他跳转到test_share.html:

router.get('/test_wxAuthorize', async (ctx, next) => {
    const state = ctx.query.id;
    // 目标地址
    let redirectUrl = ctx.href;
    redirectUrl = redirectUrl.replace('wxAuthorize', 'share.html')
    const scope = 'snsapi_userinfo'

    // 导向微信认证页面
    var url = oauth.getAuthorizeURL(redirectUrl, state, scope);
    ctx.redirect(url)
});

写下这个页面吧:

<!--test_share.html-->
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
    <script src="https://unpkg.com/vue@2.1.10/dist/vue.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://unpkg.com/cube-ui/lib/cube.min.js"></script>
    <script src="https://cdn.bootcss.com/qs/6.6.0/qs.js"></script>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/cube-ui/lib/cube.min.css">
    <style>
        /* .cube-btn {
            margin: 10px 0;
        } */
    </style>
</head>

<body>
    <div id="app">
        <div>右上角分享到朋友圈后看答案</div>
        <p>我家的mbp提供云计算服务</p>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                value: 'input'
            },

            methods: {
                getQueryVariable(variable) {
                    var query = window.location.search.substring(1);
                    var vars = query.split("&");
                    for (var i = 0; i < vars.length; i++) {
                        var pair = vars[i].split("=");
                        if (pair[0] == variable) { return pair[1]; }
                    }
                    return (false);
                }
            },
            mounted: async function () {
                //用户信息
                const code = this.getQueryVariable('code');
                let userInfo=await axios.get(`/userInfo?code=${code}`);
                userInfo=userInfo.data;

                //测试结果
                const _res = await axios.get('/getTest')
                let num = _res.data;

                // 获取配置
                const res = await axios.get('/getJsConfig', {
                    params: {
                        url: window.location.href
                    }
                })

                // jssdk权限:分享给朋友,分享给个人
                res.data.jsApiList = ['onMenuShareTimeline', 'onMenuShareAppMessage']
                wx.config(res.data);
                wx.ready(function (e) {
                    console.log('wx.ready......', e)
                    let conf = {
                        title: `震惊!原来${userInfo.nickname}的命运是这样的...`, // 分享标题
                        link: 'http://djtao.free.idcfengye.com/test_wxAuthorize', // 分享链接
                        imgUrl: userInfo.headimgurl, // 分享图标
                        success: async function () {
                            window.location.href = `/server/${num}.html`
                        }
                    }
                    wx.onMenuShareTimeline(conf)
                });
            },
        });
    </script>
</body>
</html>

我曾经无聊爬取了51支签及其解读(html)格式,分为1-51.html在server文件夹下,刚好可以用来求签。

补充接口:

router.get('/test_wxAuthorize', async (ctx, next) => {
    const state = ctx.query.id;
    // 目标地址
    let redirectUrl = ctx.href;
    redirectUrl = redirectUrl.replace('wxAuthorize', 'share.html')
    const scope = 'snsapi_userinfo'

    // 导向微信认证页面
    var url = oauth.getAuthorizeURL(redirectUrl, state, scope);
    ctx.redirect(url)
});
//科学算命核心接口
router.get('/getTest',async (ctx,next)=>{
    var num=Math.round(Math.random()*51);
    // let data=fs.readFileSync(`server/${num}.html`)
    // console.log(data);
    ctx.body=num;
})

那么功能就完成了。

这种病毒式应用要少搞,搞了会封号的。

原文发布于微信公众号 - 一Li小麦(gh_c88159ec1309)

原文发表时间:2019-08-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券