1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > NodeJs实现自定义分享功能 获取微信授权+用户信息

NodeJs实现自定义分享功能 获取微信授权+用户信息

时间:2024-05-12 07:41:50

相关推荐

NodeJs实现自定义分享功能 获取微信授权+用户信息

最近公司搞了个运营活动,入口放在了微信公众号里,好久没碰过微信了,刚拾起来瞬间感觉有点懵逼。。。。似乎把之前的坑又都重新踩了一遍,虽然过程曲折,不过好在顺利完成了,而且印象也更加深刻了,抽时间记录一下过程,不然下次再被绊倒的话,就要被老铁们笑话啦。好了,废话不多说,进入正题(先捋一捋流程,再说要注意的问题):

1.公众号配置相关:

登录微信开放平台,找到对应公众号,设置业务域名,JS接口安全域名,网页授权域名等乱七八糟的一堆(文档或者网上都有,可对比参考一下,这里就不赘述了)。

2.接入JSSDK:

页面头部引入即可:

<script src="http://res./open/js/jweixin-1.0.0.js"></script>

3.获取access_token、ticket及signature:

//appid、秘钥、随机字符串(不要试图用这些做坏事,因为机智的我已经预料到了。。。)

const APPID = 'wxdc8b4f8e3esdfsdfasd';const SECRET = 'f5a5fa443923e3fdsfasdasf0';const NONCESTR = 'Wm3WZYTPz0fdsfasdf';

let timestamp = (new Date()).getTime();let access_token = '';let jsapi_ticket = '';

//获取access_token

function getToken(callback) {

const newsUrl= 'https://api./cgi-bin/token?grant_type=client_credential&appid=' + APPID + '&secret=' + SECRET;

request(newsUrl, function (error, response, body) {

if(error || response.statusCode != '200'){

getToken(callback);

return;

}

let obj;

try{

obj = JSON.parse(body);

}catch(e){

console.log(e);

}

if(!obj || !('access_token' in obj)){

console.log('Get access token error!', error, response.statusCode, body);

getToken(callback);

return;

}

access_token = JSON.parse(body).access_token;

console.log('Got new access token:', access_token);

timestamp = (new Date()).getTime();

getTicket(callback);

});

}

function getTicket(callback) {

const newsUrl= 'https://api./cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi';

request(newsUrl, function (error, response, body) {

if (!error && response.statusCode == '200') {

if (JSON.parse(body).errcode === 0) {

jsapi_ticket = JSON.parse(body).ticket;

if(callback) {

callback();

}

}

} else {

response.status(response.statusCode).send(body);

}

});

}

//签名加密

function getSignature(url) {

const str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + NONCESTR + '&timestamp=' + timestamp + '&url=' + url;

const sha1 = crypto.createHash('sha1');

return sha1.update(str).digest('hex');

}

4.通过接口将appId、timestamp、noncestr、signature返回值页面:

router.get('/wxconfig', function(req, res) {let date = (new Date()).getTime();

//access_token有效时间为2小时if(date - timestamp >= 7200 * 1000) {getToken(function () {let signature = getSignature(req.query.url);res.send({appId: APPID,timestamp: timestamp,nonceStr: NONCESTR,signature: signature});});}else {

//这里的url是调用接口时传来的,必须是动态获取当前页面地址‘#’号之前的部分let signature = getSignature(req.query.url);res.send({appId: APPID,timestamp: timestamp,nonceStr: NONCESTR,signature: signature});}});

5.调用'/wxconfig'接口,配置自定义分享信息:

getSignature() {

let url = window.location.href.split('#')[0];this.$http.get('/lucky-draw/wxconfig', { params: { url: url } }).then(data => {this.wxConfig(data.body);this.wxReady();}, error => {console.log(error);});}

wxConfig(options) {

wx.config({

debug: false,

appId: options.appId,

timestamp: options.timestamp,

nonceStr: options.nonceStr,

signature: options.signature,

openid: '',

jsApiList: [

'onMenuShareTimeline',

'onMenuShareAppMessage'

]

});

}

wxReady() {

let _this = this;

let id = _this.getQueryString('acti');

let options = {

title: 'xxxxxxxxxxx',

desc: 'xxxxxxxxxxx',

link: 'xxxxxxxxx',

imgUrl: 'xxxxxxxxxx',

success: function (data) {

_this.addOneChanceAfterShare();

},

cancel: function (data) {

console.log(data);

}

};

wx.ready(function () {

wx.onMenuShareTimeline(options);

wx.onMenuShareAppMessage(options);

});

}

6.获取微信授权:

因为授权登录的权限较高,所以微信平台会对链接的顺序进行校验,顺序是固定的。链接格式如下:

“https://open./connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect”

解释一下参数:

appid:公众号的appid;

redirect_uri:微信授权成功之后需要跳转的链接(你希望授权成功之后跳转到哪个页面,这里就填哪个);

response_type:固定参数“code”(告诉微信给你返回code,这个解释是不是简单粗暴了些);

scope:授权权限,主要分两种,“snsapi_base”:静默授权,用户无感知,但是只能获取到openid;“snsapi_userinfo”:弹出询问框,需要用户手动确认,可以拿到openid及用户基本信息;

state:没搞太明白是干什么用的,但有一点可以确定,你传什么参数,微信授权跳转之后还会给你带回去这个参数,特定场合可能会用到;

wechat_redirect:这个可以去掉,没有影响。

7.拿code换取openid:

因为我这次做的是一个活动的单页面,页面上需要根据用户的openid及unionid从后台获取数据,所以我希望在进入页面之前就已经拿到我需要的东西了(openid和unionid以及一些数据),我的做法是把回调地址写在node里,以接口的形式接受微信的跳转(这里用词是不是太生硬了啊,哈哈,自行理解一下吧):

//获取code时微信回调地址router.get('/is_wx_redirect', function (req, res) {//拿codelet code = req.query.code || '';console.log('Get code success!!!', code);//拿活动idlet id = req.query.acti;req.session.acti_id = id;let openid, unionid, subscribe; getOpenId();//获取openidfunction getOpenId () {let url = 'https://api./sns/oauth2/access_token?appid=' + APPID + '&secret=' + SECRET + '&code=' + code + '&grant_type=authorization_code';request(url, function (error, response, body) {if (error || response.statusCode != '200') {console.log('获取openid时发生错误:', error);res.send('获取openid时发生错误,错误信息为:' + error);return false;}let data = JSON.parse(body);if (!data.openid) {console.log('发送请求openid成功,但是返回信息中没有openid');res.send(body);}//获取openid成功后,获取unionid和是否关注等信息openid = data.openid;console.log('我拿到openid了,openid是:', openid);getIsFocus();});}//获取unionid和是否关注等信息function getIsFocus () {let url = 'https://api./cgi-bin/user/info?access_token=' + access_token + '&openid=' + openid + '&lang=zh_CN';request(url, function (error, response, body) {if (error || response.statusCode != '200') {console.log('获取unionid时发生错误:', error);res.send('获取unionid时发生错误,错误信息为:' + error);return false;}let data = JSON.parse(body);subscribe = data.subscribe || '';unionid = data.unionid || '';//存sessionreq.session.openid = openid;req.session.unionid = unionid;req.session.subscribe = subscribe;console.log('我拿到unionid了,unionid是:', unionid);console.log('我拿到subscribe了,subscribe是:', subscribe);if (!subscribe) {//未关注console.log('The user is not focus!!');res.redirect('/lucky-draw/focus_page', 302);return false;}if (!unionid) {//返回信息中无unionidres.send('返回信息中未包含unionid' + data);return false;}//重定向至主页面console.log('Start redirect!!!!');res.redirect('/lucky-draw/?acti=' + id, 302);console.log('Redirect success!!');});}});

眼尖的老铁可能一眼就发现了几个问题:

1)我并没有用拿到的code去换access_token,而是用之前自定分享时获取过的全局token,这里需要注意了,全局access_token和网页授权access_token是有区别的,获取地址、参数、时效及用途都不同,千万可别弄混淆了,不然非得坑死你(别胡说,我才没被这个坑过。。。。),关于这两个access_toekn的具体区别及用途,可以自行查一下。因为我只需要判断用户是否关注了公众号,从而完成一项业务需求,并不需要用户的基本信息,所以我只拿code换取了openid,然后用openid和全局access_token获取unionid;

2)大堆的log有木有!!微信开发的调试相对来说还是比较简(恶)单(心)的,关键位置的log获取错误处理,会让我们少走很多弯路。

8.其实代码已经写在上一步了,就是拿到初始化页面所需要的信息之后,重定向至该页面。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。