村农

莫笑农家腊酒浑,丰年留客足鸡豚。


微信signature签名,网页授权

冬冬

突然要整微信IOT airkiss设备配网,然后就以这为目的,看了点东西,此处做下记录,待续......

微信服务端signature签名,网页授权

var express = require('express');
var crypto = require('crypto');
var request = require('request');
var router = express.Router();
var config = {
    wechat : {
        appID:'wx085c110a6db61dc4',
        appsecret:'c44a77a451b13e29ed4e3c43854ddb4a',
        token:'winter',
        webUrl : 'http://r4bgse.natappfree.cc/wx/',
        access_token: '',
        jsapi_ticket:''
    }
};

var last_update_time = 0;

router.get('/',function(req,res,next){
    res.render('wx',{title:'wx测试'})
});

router.get('/checkToken',function(req,res,next){
    var token = config.wechat.token,
        signature = req.query.signature,
        nonce = req.query.nonce,
        timestamp = req.query.timestamp,
        echostr = req.query.echostr;
    var str = [token,timestamp,nonce].sort().join('');
    var sha = crypto.createHash('sha1').update(str).digest('hex');
    console.log(sha,signature);
    if(sha == signature && req.method == 'GET'){
        res.end(echostr);
    }else{
        res.end('signature fail');
    }
});
router.get('/sign',async function(req,res,next){
    let noncestr = Math.random().toString(36).substr(2,15);
    let time = parseInt(new Date().getTime() / 1000)+'';
    let url = req.query.url;
    let jsapi_ticket = await getJsApiTicket();
console.log(jsapi_ticket,noncestr,time,url);
    let str = 'jsapi_ticket='+ jsapi_ticket+'&noncestr='+noncestr+'&timestamp='+time+'&url='+url;
    let sha = crypto.createHash('sha1').update(str).digest('hex');
    console.log(sha);
    res.json({
        appId: config.wechat.appID,
        timestamp: time,
        nonceStr: noncestr,
        signature: sha
    });
});
router.get('/wxLogin',function(req,res,next){
    var router = 'getWxAccessToken';
    var return_url = config.wechat.webUrl+router;
    var scope = "snsapi_userinfo";
    res.redirect('https://open.weixin.qq.com/connect/oauth2/authorize?appid='+config.wechat.appID
        +'&redirect_uri='+return_url
        +'&response_type=code&scope='+scope
        +'&state=STATE#wechat_redirect');
});

router.get('/getWxAccessToken', function(req,res, next){
    //console.log("get_wx_access_token")
    //console.log("code_return: "+req.query.code)

    // 第二步:通过code换取网页授权access_token
    var code = req.query.code;
    request.get(
        {   
            url:'https://api.weixin.qq.com/sns/oauth2/access_token?appid='+config.wechat.appID
            +'&secret='+config.wechat.appsecret
            +'&code='+code+'&grant_type=authorization_code',
        },
        function(error, response, body){
            if(response.statusCode == 200){

                // 第三步:拉取用户信息(需scope为 snsapi_userinfo)
                console.log(JSON.parse(body));
                var data = JSON.parse(body);
                var access_token = data.access_token;
                var openid = data.openid;

                request.get(
                    {
                        url:'https://api.weixin.qq.com/sns/userinfo?access_token='+access_token
                        +'&openid='+openid+'&lang=zh_CN',
                    },
                    function(error, response, body){
                        if(response.statusCode == 200){

                            // 第四步:根据获取的用户信息进行对应操作
                            var userinfo = JSON.parse(body);
                            //console.log(JSON.parse(body));
                            console.log('获取微信信息成功!');

                            // 小测试,实际应用中,可以由此创建一个帐户
                            res.send("\
                                <h1>"+userinfo.nickname+" 的个人信息</h1>\
                                <p><img src='"+userinfo.headimgurl+"' /></p>\
                                <p>"+userinfo.city+","+userinfo.province+","+userinfo.country+"</p>\
                            ");

                        }else{
                            console.log(response.statusCode);
                        }
                    }
                );
            }else{
                console.log(response.statusCode);
            }
        }
    );
});


async function getAccessToken(){
    let url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='+config.wechat.appID
    +'&secret='+config.wechat.appsecret;
    let new_time = new Date();
    if((new_time-last_update_time)/1000 > 7200){
        let access_token = await new Promise(function(resolve,reject){
            request.get({
                url:url
            },function(err,response,body){
                if(response.statusCode == 200){
                    var data = JSON.parse(body);
                    console.log(data);
                    config.wechat.access_token = data.access_token;
                    resolve(data.access_token);
                }
            })
        });
        return access_token;
    }else{
        return config.wechat.access_token;
    }
}

async function getJsApiTicket(){
    let access_token = await getAccessToken();
    let url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='+access_token+'&type=jsapi';
    let new_time = new Date();
    if((new_time-last_update_time)/1000 > 7200){
        let ticket = await new Promise(function(resolve,reject){
            request.get({
                url:url
            },function(err,response,body){
                if(response.statusCode == 200){
                    let data = JSON.parse(body);
                    console.log(data);
                    config.wechat.jsapi_ticket = data.ticket;
                    last_update_time = new_time;
                    resolve(data.ticket);
                }
            })
        });
        return ticket;
    }else{
        return config.wechat.jsapi_ticket;
    }
}

module.exports = router;

网页端js

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