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

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 + '&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.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) {
//拿code
let code = req.query.code || '';
console.log('Get code success!!!', code); //拿活动id
let id = req.query.acti;
req.session.acti_id = id; let openid, unionid, subscribe; getOpenId(); //获取openid
function 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 || ''; //存session
req.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) {
//返回信息中无unionid
res.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.其实代码已经写在上一步了,就是拿到初始化页面所需要的信息之后,重定向至该页面。

NodeJs实现自定义分享功能,获取微信授权+用户信息的更多相关文章

  1. ThinkPHP5集成JS-SDK实现微信自定义分享功能

    最近开发一个项目,需要将链接分享给好友时能够自定义标题.简介和logo,现将ThinkPHP5集成JS-SDK实现微信自定义分享功能的过程整理成文. 一.准备工作 1.认证的公众号 不管是订阅号还是服 ...

  2. c#微信开发,使用JS-SDK自定义分享功能,分享朋友圈,分享给朋友等

    如果一个后端开发掌握了微信开发,甚至有微信开发上线项目,这在换工作的时候 还是有竞争力的. 微信开发的资料很多,但是用asp.net c#进行微信开发好像比较少,或者资料不够完整. 使用JS-SDK自 ...

  3. Chrome获取微信授权,调试公众号页面

    1.目的 你可能遇到过这种情况,在微信中打开公众号是这样的. 复制链接,在chrome中打开是这样的. 博主今天要解决的就是,如果在chrome中加载需要微信授权的页面,至于加载成功后要干嘛,测试?抓 ...

  4. 微信公众号基础02_获取accessToken和用户信息

    上一篇分享了搭建微信公众号server,本文分享一下假设获取access_Token和用户信息.工具还是新浪云SAE 1.获取access_Token 相见开发文档:https://mp.weixin ...

  5. 微信公众号开发之如何一键导出微信所有用户信息到Excel

    微信开发交流群:148540125 系列文章参考地址 极速开发微信公众号欢迎留言.转发.打赏 项目源码参考地址 点我点我--欢迎Start 极速开发微信公众号系列文章之如何一键导出微信所有用户信息到E ...

  6. spring oauth2获取当前登录用户信息。

    使用spring oauth2框架做授权鉴定.想获取当前用户信息怎么办? 我们知道spring oauth2是基于spring security的实现的. spring security可以通过Sec ...

  7. 黄聪:WordPress 多站点建站教程(五):获取子站点用户信息(通过输入站点ID号来获取该站点的所有用户)

    得到站点ID为1的用户 <ul> <?php $blogusers = get_users('blog_id=1'); foreach ($blogusers as $user) { ...

  8. C# 微信openid 用户信息

    前段demo index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  9. 使用微信JS-SDK 实现 自定义 分享 功能

    微信PC端点击页面,转发给朋友.

随机推荐

  1. 26.Django模板语言和分页

    继承 extends 子版只能继承一个父模板 1.父模板 master.html <!DOCTYPE html> <html lang="en"> < ...

  2. cocos creator实现棋牌游戏滑动选牌的功能

    最近在玩cocos creator,打算学着做一款类似双扣游戏的棋牌,名字叫文成三星,比双扣还要多一扣,因为需要三幅牌,在我们老家比较流行这种玩法. 目前实现了绝大部分的逻辑效果如下: 有一点不好的体 ...

  3. 使用NPOI导出Excel引发异常(IsReadOnly = “book.IsReadOnly”引发了类型“System.NotImplementedException”的异常)

    前言: 本人调式npoi导入.导出试用成功后,引入到项目中,导入完美运行,但是导出怎么样都看不到现在的页面,而且浏览器和后台都没有报任务错误,让人好事纳闷,后来去调式,发现在除了一个IsReadOnl ...

  4. asp.net WebApi 使用总结

    如果想让服务端直接返回json或者xml的话,可以考虑使用webservice.wcf,或者webapi.webservice基于xml,效率较慢,wcf虽然可以返回json,但是配置繁琐.webap ...

  5. vue-cli工具搭建vue-webpack项目

    1.安装node环境 下载地址 https://nodejs.org/en/download/ node -v   安装成功后在命令行查看node版本 npm-v   安装成功后在命令行查看npm版本 ...

  6. MySQL多数据源笔记4-Mycat中间件实战

    Mycat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服 务.由于前面讲的对数据进行分片处理之后,从原有的一个库,被切分为多个分片数据库,所有的分片数据库集 群构成了整个完整的 ...

  7. Numpy库的下载及安装(吐血总结)

    Python很火,我也下了个来耍耍一阵子.可是渐渐地,我已经不满足于它的基本库了,我把目光转到了Numpy~~~~~ 然而想法总是比现实容易,因为我之前下的是Python3.3.x,所有没有自带pip ...

  8. NGUI_slider

    十一.进度条UISlider 1.一般按以下规律使用进度条; 如果某一钟值,他有最大值,需要表达当前的值得占比,则可以使用不可拖动的进度条 如果某一值,他有最大值,需要玩家记性滑动设置,则可以使用可拖 ...

  9. 以太坊挖矿源码:ethash算法

    本文具体分析以太坊的共识算法之一:实现了POW的以太坊共识引擎ethash. 关键字:ethash,共识算法,pow,Dagger Hashimoto,ASIC,struct{},nonce,FNV ...

  10. 从源码浅析Java中的Lock和AbstractQueuedSynchronizer

    在之前的文章中我也曾经介绍过Lock,像ReentrantLock(可重入锁)和ReentrantReadWriteLock(可重入读写锁),这些所我们在说的时候并没有详细的说明它们的原理,仅仅说明了 ...