NodeJs实现自定义分享功能,获取微信授权+用户信息
最近公司搞了個運營活動,入口放在了微信公眾號里,好久沒碰過微信了,剛拾起來瞬間感覺有點懵逼。。。。似乎把之前的坑又都重新踩了一遍,雖然過程曲折,不過好在順利完成了,而且印象也更加深刻了,抽時間記錄一下過程,不然下次再被絆倒的話,就要被老鐵們笑話啦。好了,廢話不多說,進入正題(先捋一捋流程,再說要注意的問題):
1.公眾號配置相關:
登錄微信開放平臺,找到對應公眾號,設置業務域名,JS接口安全域名,網頁授權域名等亂七八糟的一堆(文檔或者網上都有,可對比參考一下,這里就不贅述了)。
2.接入JSSDK:
頁面頭部引入即可:
<script src="http://res.wx.qq.com/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.weixin.qq.com/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.weixin.qq.com/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 + '×tamp=' + 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.weixin.qq.com/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.weixin.qq.com/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.weixin.qq.com/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.其實代碼已經寫在上一步了,就是拿到初始化頁面所需要的信息之后,重定向至該頁面。
轉載于:https://www.cnblogs.com/kakayang/p/8745061.html
總結
以上是生活随笔為你收集整理的NodeJs实现自定义分享功能,获取微信授权+用户信息的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怀孕梦到大乌龟什么预兆
- 下一篇: 梦到闪电劈死别人是什么征兆