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 + '&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) {//拿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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398359.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git的简单理解及基础操作命令

前端小白一枚&#xff0c;最近开始使用git&#xff0c;于是花了2天看了廖雪峰的git教程(偏实践&#xff0c;对于学习git的基础操作很有帮助哦)&#xff0c;也在看《git版本控制管理》这本书(偏理论&#xff0c;内容完善&#xff0c;很不错)&#xff0c;针对所学内容建了git仓库…

iOS 后台挂起的一些坑

特别说明&#xff1a;后台状态&#xff1a;当前app如果不是作为屏幕中的第一层&#xff0c;呈现显示给用户&#xff0c;那么此时app就是后台状态。锁屏&#xff08;包括&#xff1a;当前应用下锁屏、其他应用下锁屏、桌面锁屏&#xff09; 用户在使用其他应用app2&#xff0c;…

OSGI 生命周期

1 生命周期管理 对于非模块化应用&#xff0c;生命周期将应用作为一个整体来操作&#xff1b;而对于模块化应用&#xff0c;则可以以细粒度的方式来管理应用的某一个独立部分。OSGi生命周期管理 OSGi生命周期层有两种不同的作用&#xff1a; 在应用程序外部&#xff0c;定义了对…

tomcat+nginx+redis实现均衡负载、session共享

在项目运营时&#xff0c;我们都会遇到一个问题&#xff0c;项目需要更新时&#xff0c;我们可能需先暂时关闭下服务器来更新。但这可能会出现一些状况:1.用户还在操作&#xff0c;被强迫终止了(我们可以看日志等没人操作的时候更新&#xff0c;但总可能会有万一)2.不知道的用户…

洛谷 P3184 [USACO16DEC]Counting Haybales数草垛

洛谷 P3184 [USACO16DEC]Counting Haybales数草垛 题目描述 Farmer John has just arranged his NN haybales (1 \leq N \leq 100,0001≤N≤100,000 ) at various points along the one-dimensional road running across his farm. To make sure they are spaced out appropria…

关于笔试的一些博客

这里收集了一些阿里的网上笔试题目 阿里笔试题(2015)持续更新中腾讯阿里实习生招聘笔试总结阿里2014研发实习生笔试题解析【阿里】算法工程师笔试题整理&#xff08;13&14年&#xff09;【阿里】算法工程师笔试【2015.04.02】转载于:https://www.cnblogs.com/chen310/p/438…

Entity Framework 6 Recipes 2nd Edition(13-2)译 - 用实体键获取一个单独的实体

问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Painting(绘画)类型的实体,如Figure 13-2所示: Figure 13-2. The Painting entity type in our model 在代码In Listi…

C#心得与经验(二)

本周学到很多C#关于Interface, Array的知识&#xff0c;在这里简单复习一下几个易混的地方&#xff0c;重在理解。 一、Interface 使用as来避免多态时没有接口的Exception&#xff1a; Document [] folder new Document[5]; for (int i 0; i < 5; i) {if (i % 2 0){fold…

java实例化对象

摘要&#xff1a;分享牛&#xff0c;分享牛分享&#xff0c;java类加载机制&#xff0c;java实例化对象&#xff0c;java实例化对象机制&#xff0c;java基础。 java是如何实例化对象的呢&#xff1f;以及实例化对象的先后顺序是什么&#xff1f;下面我们以测试的方式说明. 1.1…

项目总结(3.28)

项目是用vuewebpackelementUI 完成的。虽然没有什么深奥的技术和难点&#xff0c;但是有些细节还是值得注意的。 1、满足不同屏幕尺寸下缩放全屏显示。 单单只靠宽度、高度百分比是不可以实现的&#xff0c;比如如果宽度设置百分比&#xff0c;当屏幕宽度比较小时&#xff0c;这…

Android开发删除短信

本人一直有一个需求&#xff0c;想要手机自动拦截黑名单里联系人的信息并自动删除这些短信&#xff0c;手机管家之类的软件可以拦截但是没找到能删除这些短信的&#xff0c;于是就萌生了想自己写一个android软件的想法。 加上物联网的兴起&#xff0c;安卓设备开发肯定前景很好…

让你提升命令行效率的 Bash 快捷键 [完整版]

生活在 Bash shell 中&#xff0c;熟记以下快捷键&#xff0c;将极大的提高你的命令行操作效率。 编辑命令 Ctrl a &#xff1a;移到命令行首Ctrl e &#xff1a;移到命令行尾Ctrl f &#xff1a;按字符前移&#xff08;右向&#xff09;Ctrl b &#xff1a;按字符后移&…

Okhttp的封装和回调

public class HttpUtil {static HttpUtil util;private final OkHttpClient client;// 私有化构造方法private HttpUtil(){client new OkHttpClient();}public static HttpUtil getInstance(){if(util null){synchronized (HttpUtil.class){util new HttpUtil();}}return u…

将Session写入Memcache

通过session_set_save_handler()方法自定义Session写入Memcache 1 <?php 2 class MemSession{3 private static $handler null;4 private static $lifetime null;5 private static $time null;6 const MS session;7 8 …

微软解决方案全景

我遇到过一家企业的CTO&#xff0c;做过很多知名大企业的信息化规划设计&#xff0c;但他基本是一个Like Unix派系的技术&#xff0c;而我是一个Microsoft派系的技术&#xff0c;在这里我不是讨论哪个派系的技术好和不好&#xff0c;我只是在和他的聊天中发现了一些非常有意思的…

Going Dutch BAPC( 状态转移DP)

题目描述 You and your friends have just returned from a beautiful vacation in the mountains of the Netherlands. When on vacation, it’s annoying to split the bill on every expense every time, so you just kept all the receipts from the vacation, and wrote d…

查询指定目录下的文件中是否包含指定字符串

cd /etc/apache2/site-enable/rep -rl test.com ./*意为查询apache虚拟主机中是否包含test.com的域名转载于:https://blog.51cto.com/linuxtips/1773938

使用 C# 编程对RTF文档的支持

http://www.68design.net/Development/Aspnet/Basis-AspNet/26011-1.html 转载于:https://www.cnblogs.com/faxian/p/4402910.html

algorand共识协议_【Filecoin】理解预期共识 - 及它的优缺点

摘 要预期共识就是上帝掷飞镖预期共识的优点在于简单&#xff0c;而且每一次选举胜出者数量的平均数为1但预期共识不能保证每次选举的胜出者数量&#xff0c;这是其最大的问题期待有更好的基于可验证随机函数的共识算法出现&#xff0c;设计者可获得20万美金奖赏预期共识 就是 …

Android软件安全与逆向分析之Dalvik

注意点 首先&#xff0c;让我们来思考下面几个问题&#xff1a; 什么是Dalvik虚拟机? Dalvik VM与JVM有什么区别&#xff1f; Dalvik VM有什么新的特点&#xff1f; Dalvik VM的架构是怎么样的&#xff1f; 首先&#xff0c;我得承认第一个问题问得很傻&#xff1a;什么是Dalv…