node接微信分享

本文基于工作使用学习,做的整理笔记
当我们进行微信分享时,分享出去的效果,我们最容易发现的是没有图,那我们就埋一个301 * 301的图。但是,我们又发现没有描述,只有链接。这个该怎么解决呢。最终方法就是需要使用微信公众平台的JS-SDK来实现,调用分享接口。实现这个功能时遇到不少坑,走了不少弯路,这里就整理记录一下以便后面查阅。那么,来一起看看吧。

前提条件:
本文后台基于nodeJS,需要有一点这一方面基础。
(还需域名,服务器,微信公众号或测试号)

编码环境:
系统:OS X EI Capitan
版本:10.12.5

 
微信JS-SDK.jpg

目录
| - 0.题外话
| - 1.JS-SDK使用说明
| - 2.实例开发
  | - 1)获取access_token
  | - 2)获取jsapi_ticket
  | - 3)计算signature
  | - 4)前端调用
  | - 5)配置测试
| - 6)优化请求
| - 3.常见问题
  | - 1)config错误
  | - 2)signature错误
  | - 3)url domain错误
  | - 4)其他错误
| - 4.附QQ分享
| - 5.结束

0.题外话

当不使用JS-SDK,我们该怎么实现“分享”带缩略图呢?之前有一个取巧的方法,如下:

  • 标题:取meta标签title的内容。
  • 缩略图:取body内第1张符合条件的图片。
    图片规格要求:尺寸必须大于300 * 300,放在<img src="" alt="">标签内。

所以,我们会埋一张301 * 301的图片,比如:

  // ![](.../share.png)

在分享的时候会自动获取到这张图片,但实际并没有显示。(但有一定的概率失效,原因未仔细查找,因为准备使用JS-SDK)

1.JS-SDK使用说明

微信JS-SDK说明文档传送门:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

阅读文档,发现其实真对我们想要的分享功能,阅读前3大点内容就够了,如下:

  • 绑定域名,配置“JS接口安全域名”
  • 引入JS文件
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script> 
  • 通过config接口注入权限验证配置
wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识 timestamp: , // 必填,生成签名的时间戳 nonceStr: '', // 必填,生成签名的随机串 signature: '',// 必填,签名,见附录1 jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); 
其中,最重要的就是signature签名的生成。附录1告诉我们:
1)生成`signature`需要`jsapi_ticket`, 2)生成`jsapi_ticket`需要`access_token` 3)还有7200秒过期等规则,组装规则(稍后再看) 
  • 通过ready接口处理成功验证
wx.ready(function(){
    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 }); 
  • 通过error接口处理失败验证
wx.error(function(res){
    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 }); 

【用自己的话】解释整个流程就是:

  • 先有个公众号,这样就有appID和appSecret(在开发/基本配置分类下)
  • 引入JS文件http://res.wx.qq.com/open/js/jweixin-1.2.0.js,去使用微信JS-SDK
  • 拿access_token,配置IP白名单才能调此接口,根据appID和appSecret进行请求 (有效期7200秒,每次使用前检查,过期重新获取)
  • 拿jsapi_ticket,根据上一步的access_token进行请求 (有效期7200秒,每次使用前检查,过期重新获取)
  • 计算signature,根据上一步的jsapi_ticket
    1)排序,参与签名的字段:noncestr(随机字符串),有效的jsapi_ticket,timestamp(时间戳),url(不带#后面部分部分),字典序从小到大排序,
    2)拼接,使用URL键值对的格式拼接字符串string1,参数名必须均为小写字符
    3)加密,对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义
    注意:计算签名必须在服务端完成签名,返回前端。
  • 添加JS接口安全域名(在公众号后台的设置/公众号设置/功能设置中添加),这里需要实现MP_verify_AwmmQFM5B0vHg035.txt文件检查功能
  • 部署测试,注意事项:80端口,域名已备案

2.实例开发

官方DEMO页面和例子传送门:附录6

如果你有可以使用的公众号,那么直接用就好了。如果没有,就需要使用测试公众号。在在公众号后台的开发/开发者工具/公众平台测试帐号,登陆进入就可以使用测试公众号了。

我这里的信息如下:
appID:wx5ee658102855e872
appSecret:af7207aaa4bec3b9b1ed941564a4580f

1)获取access_token
// 这里应该判断是否存在签名,是否已过期
//(稍后添加)
// ...
// 公众号字段 var appID = "wxa2c416de84300ee5"; var appSecret = "bba57000821ac67cbcee3a573db85498"; // 获取access_token var tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='+appID+'&secret='+appSecret; request(tokenUrl, function (error, response, body) { if (response.statusCode === 200) { body = JSON.parse(body); // 这里我缓存到了global global.wxshare.access_token = body.access_token; // 获取jsapi_ticket // ... } 
2)获取jsapi_ticket
// 获取jsapi_ticket
var ticketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + body.access_token + '&type=jsapi'; request(ticket, function (err, response, content) { content = JSON.parse(content); if (content.errcode == 0) { // 这里我缓存到了global global.wxshare.jsapi_ticket = content.ticket; // 计算signature // ... } }) 
3)计算signature
// 计算signature
// 先拿一个当前时间戳,这里我缓存到了global
global.wxshare.deadline = new Date().getTime(); // 通过调用计算签名方法 var signatureStr = sign(content.ticket, req.body.url); // 当前时间戳 signatureStr.deadline = new Date().getTime(); // 缓存签名 if (signindex && signindex !== 0) { global.wxshare.signs(signindex, 1, signatureStr); } else { global.wxshare.signs.push(signatureStr); } // 返回给页面 res.status(200).json(signatureStr); 
// 随机字符串
var createNonceStr = function () { return Math.random().toString(36).substr(2, 15); }; // 时间戳 var createTimestamp = function () { return parseInt(new Date().getTime() / 1000) + ''; }; // 排序拼接 var raw = function (args) { var keys = Object.keys(args); keys = keys.sort() var newArgs = {}; keys.forEach(function (key) { newArgs[key.toLowerCase()] = args[key]; }); var string = ''; for (var k in newArgs) { string += '&' + k + '=' + newArgs[k]; } string = string.substr(1); return string; }; /** * @synopsis 签名算法 * * @param jsapi_ticket 用于签名的 jsapi_ticket * @param url 用于签名的 url ,注意必须动态获取,不能 hardcode * * @returns */ var sign = function (jsapi_ticket, url) { var ret = { jsapi_ticket: jsapi_ticket, nonceStr: createNonceStr(), timestamp: createTimestamp(), url: url }; var string = raw(ret); jsSHA = require('jssha'); shaObj = new jsSHA(string, 'TEXT'); ret.signature = shaObj.getHash('SHA-1', 'HEX'); return ret; }; module.exports = sign; 
//检查页面链接对应的签名是否可用
var signtag = false;
var signindex; // 检查签名 global.wxshare.signs.forEach(function (item, index) { if (item.url === req.body.url) { signindex = index; if (item.deadline && new Date().getTime() - item.deadline < 6000000) { signtag = true; } } }); //当签名不可用时,检测jsapi_ticket是否可用,来决定是直接请求签名还是先请求jsapi_ticket再请求签名 if (!signtag) { // 请求操作 // 计算签名操作 // ... } 
// 相应路由
app.post('/signture', Base.wxconfig);
// 对应方法
exports.wxconfig = function(req,res,next) { // ... } 
4)前端调用
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script> // 请求签名 $.ajax({ url: "/signture", type: 'post', data: { url: location.href.split('#')[0] }, success:function(res){ wx.config({ debug: false, appId: 'wxa2c416de84300ee5', timestamp: res.timestamp, nonceStr: res.nonceStr, signature: res.signature, jsApiList: [ 'checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ' ] }); wx.ready(function () { var shareData = { title: document.title, desc: getDesc(), link: res.url, imgUrl: getImage() }; wx.onMenuShareAppMessage(shareData); wx.onMenuShareTimeline(shareData); wx.onMenuShareQQ(shareData); }); wx.error(function (res) { alert(res.errMsg); // 正式环境记得关闭啊!!!! }); } }); // 获取描述字段方法 function getDesc() { var meta = document.getElementsByTagName("meta"); for (var i=0;i<meta.length;i++){ if(typeof meta[i].name!="undefined"&&meta[i].name.toLowerCase()=="description"){ return meta[i].content; } } }; // 获取图片 function getImage() { return 'http://'+location.host+'/images/logo.png'; }; </script> 
5)配置测试

添加JS接口安全域名(在公众号后台的设置/公众号设置/功能设置中添加),这里需要实现MP_verify_AwmmQFM5B0vHg035.txt文件检查功能。

因为这个MP_verify_AwmmQFM5B0vHg035.txt文件里,只有一行字符串,直接返回即可

// 相应路由
app.get('/MP_verify_CwPkZ2phenWhKlmR.txt', Base.checkWx);

// 对应方法
exports.checkWx = function(req, res) { res.send('CwPkZ2phenWhKlmR'); } 
6)优化请求(检查微信环境,减少不必要的微信接口调用次数)
<script>
  // 检查微信环境
  function isWeiXin() { var ua = window.navigator.userAgent.toLowerCase(); if (ua.match(/MicroMessenger/i) == 'micromessenger') { return true; } else { return false; } }; // 如果为真,则请求 if(isWeiXin()){ // 去获取signature签名 .... }); </script> 

3.常见问题

官方常见错误查阅传送门:附录5

因为在实际开发的时候,真的是不端的遇到问题,不断的去找答案。错误出现的话,是有一定顺序的,这对我们找原因有一定的帮助。首先是config fail,若没错的话,才有可能出现invalid signature,若没错的话,才有可能出现``` invalid url domain``。最后就完全没错了,说明已成功。

1)config 错误

如果config fail,一般说明存在配置字段遗漏,或者配置字段的值为空(null,undefined,"")。

2)signature错误

如果报invalid signature错误,一般说明签名没有生成正确,再核对一遍规则。可以使用微信 JS 接口签名校验工具:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign,对比代码生成出来的是否和检验工具生成的一样。比如时间戳长度,顺序,拼接遗漏。

3)url domain错误

如果报invalid url domain错误,说明配置工作已经OK啦。出现这个的原因是域名没有添加到JS接口安全域名下,或者没有使用80、443端口。

4)其他错误

permission denied接口无权限等等,查阅文档吧。

4.附QQ分享

手机QQ对外分享组件接口文档传送门:http://open.mobile.qq.com/api/component/share

阅读文档后发现比较简单,引用一个JS文件,然后几行配置代码。但注意一下:文档页面举例代码含有“微信配置”,请勿重复配置WXconfig

// 引入JS脚本
<script type="text/javascript" src="http://qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js"></script> <script type="text/javascript"> // 配置 setShareInfo({ title: document.title, // 获取页面的标题 summary: getDesc, //获取页面的desc pic: 'http://xxx/xx/pic.png', // 获取图片(这里自己写吧,整站固定图片or页面第一张或指定图片) url: location.href // 获取地址 }); // 获取描述字段方法 function getDesc() { var meta = document.getElementsByTagName("meta"); for (var i=0;i<meta.length;i++){ if(typeof meta[i].name!="undefined"&&meta[i].name.toLowerCase()=="description"){ return meta[i].content; } } }; </script> 

5.结束

本文的主要内容就是关于“微信JS-SDK的接口调用”,那这里举例就是分享接口,其他接口类推吧,用到什么去看文档。觉得难就不去看的话,就相当于弃坑了;可是仔细去看一下文档,先理清思路步骤,在每个步骤去完成,串联起来也就实现了。回头一看,发现并不难。文章的最后附了一个QQ的分享配置方法,需要可以尝试。

最后针对不同浏览器,这个就说不准了。有的浏览器自己就可以帮你完成图片和描述的完美呈现,有的就只能是URL地址(没有描述)。真要去看这个,可能要进行反复测试找规律,想想都心累了。我们比较常见的也就是“微信”,“QQ”,也许还有“企业微信”。补充一句,“企业微信”不会使用JS-SDK的,但是它可以自动帮你获取到标题、描述,但图片地址就和页面图有关了。需要可以自己留意下。

到这里,就先结束了。



作者:SeasonDe
链接:https://www.jianshu.com/p/1a35e1dbe1ad
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

转载于:https://www.cnblogs.com/SharkChilli/p/8334568.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Node.js中实现微信分享,你可以按照以下步骤进行操作: 1. 首先,你需要在代码中引用微信的JavaScript SDK,你可以从该GitHub仓库获取源码。这个仓库中包含了微信JS-SDK的示例代码和使用方法。 2. 在你的Node.js项目中,创建一个路由或者控制器用于处理分享功能。你可以使用Express框架来创建路由。例如,你可以创建一个名为`activityWxShare`的路由来处理分享。 3. 在路由或者控制器中,你需要获取分享的URL,并对其进行签名。你可以使用SHA1算法来对URL进行签名。如果你的环境无法使用现有的SHA1库,你可以自己编写实现。在示例代码中,使用了`wxShare.prototype.accessToken`方法对URL进行签名。 4. 在路由或者控制器中,你可以使用axios库来发送HTTP请求。你可以创建一个名为`access_token.js`的文件来处理获取access_token的逻辑。 5. 在`access_token.js`文件中,你可以使用`axios.get`方法向微信API发送请求,获取access_token。你需要提供你的微信公众号的AppID和AppSecret来获取有效的access_token。在示例代码中,使用了`https://api.weixin.qq.com/cgi-bin/token`的口来获取access_token。 通过这些步骤,你可以在Node.js中实现微信分享功能。请注意,你需要根据你的具体需求和环境进行适当的配置和调整。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [微信JS-SDK“分享信息设置”API及数字签名生成方法(NodeJS版本)](https://blog.csdn.net/weixin_30642267/article/details/96222935)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [nodeJS微信分享](https://blog.csdn.net/zhwangchao/article/details/78851357)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [nodejs使用express框架实现微信个性化分享H5](https://blog.csdn.net/weixin_38946164/article/details/117623017)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值