起源:

最近公司在做一个活动的h5页面,在微信内打开时需要进行微信授权,然后后端会重定向到这个页面并且携带了一些参数(openid等)。问题是点击微信的原生分享时,会把携带的这些参数一起分享出去,等于把用户信息泄露了。所以为了解决这个问题,只能实现自定义微信分享的功能,可以自定义分享的地址、标题、图标还有简介。

事先需要做的:

1.微信公众号:必须是经过微信认证的,没有认证的或者认证过期的都不可以;

2.经过备案的域名:必须是备案过的,不然是无法使用的;

3.绑定域名:首先你需要将需要分享的网址的域名绑定到微信公众平台上面,

具体操作:先登录微信公众平台进入“公众号设置”的“功能设置”里填写:JS接口安全域名;还要在"安全中心"中设置:IP白名单

 

后台需要做的:

1.后台服务器:前台页面需要后台服务器传过来一些配置参数,比如appId、timestamp、nonceStr、signature这几个参数都是后台从微信公众平台获取到的, 需要后台进行配合;

2.获取access_token:利用公共号APPID、APPSECRET从微信服务器获取对应的access_token,这里是后台开发小伙伴的范围不多做解释;

后台需要传的参数格式:

签名的生成步骤:

生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

1. 获取access_token(有效期7200秒,2个小时开发者必须在自己的服务全局缓存access_token):access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。具体请参考以下官方文档:

https://link.zhihu.com/?target=https%3A//developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

公众号和小程序均可以使用AppID和AppSecret调用本接口来获取access_token。AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得(需要已经成为开发者,且帐号没有异常状态)。调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。小程序无需配置IP白名单。示例代码如下所示:

  1. https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

返回的JSON如下:

  1. {"access_token":"ACCESS_TOKEN","expires_in":7200}

2. 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,2个小时,开发者必须在自己的服务全局缓存jsapi_ticket)

  1. https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

成功返回JSON如下:

  1. {
  2. "errcode":0,
  3. "errmsg":"ok",
  4. "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  5. "expires_in":7200
  6. }

3. 生成JS-SDK权限验证的签名

参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。

首先:对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1:

顺序依次为:jsapi_ticket,noncestr,timestamp,url。

  1. jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

然后:对string1进行sha1签名,得到signature。

  1. signature=sha1(string1) // 0f9de62fce790f9a083d5c99e95740ceb90c27ed

注意事项

  1. 签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
  2. 签名用的url必须是调用JS接口页面的完整URL。
  3. 出于安全考虑,开发者必须在服务器端实现签名的逻辑。

前端需要做的:

参考官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#3

1、在项目中引用微信的js-sdk

官方文档上写的是1.6.0

在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)。

2、配置config

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用。其中的签名信息signature需要服务器端提供。timestamp和nonceStr是参与签名生成的字段,因此也可以由服务端一并提供,代码如下所示:

  1. wx.config({
  2. debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  3. appId: '',
  4. timestamp: ,
  5. nonceStr: '',
  6. signature: '',
  7. jsApiList: []
  8. });

参数说明:

  • appId:公众号的唯一标识,在公众号中可以取到;
  • timestamp:生成签名的时间戳
  • nonceStr: 生成签名的随机串
  • signature: 最后生成的签名
  • jsApiList: 需要使用的JS接口列表,我们这里是用分享接口,将分享几个api接口填进去,例如:['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareQQ']

3、通过ready接口处理成功验证 

  1. wx.ready(function(){
  2. // config信息验证通过后会执行ready方法,
  3. // 所有接口调用都必须在config接口获得结果之后,
  4. // config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,
  5. // 则须把相关接口放在ready函数中调用来确保正确执行。
  6. // 对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
  7. });

4、通过error接口处理失败验证

  1. wx.error(function(res){
  2. // config信息验证失败会执行error函数,
  3. // 如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,
  4. // 也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
  5. });

所有接口通过wx对象(也可使用jWeixin对象)来调用,参数是一个对象,除了每个接口本身需要传的参数之外,还有以下通用参数:

  1. success:接口调用成功时执行的回调函数。
  2. fail:接口调用失败时执行的回调函数。
  3. complete:接口调用完成时执行的回调函数,无论成功或失败都会执行。
  4. cancel:用户点击取消时的回调函数,仅部分有用户取消操作的api才会用到。
  5. trigger: 监听Menu中的按钮点击时触发的方法,该方法仅支持Menu中的相关接口。

备注:不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回。

以上几个函数都带有一个参数,类型为对象,其中除了每个接口本身返回的数据之外,还有一个通用属性errMsg,其值格式如下:

调用成功时:"xxx:ok" ,其中xxx为调用的接口名

用户取消时:"xxx:cancel",其中xxx为调用的接口名

调用失败时:其值为具体错误信息

官方示例代码:

自定义“分享给微信朋友”及“分享到QQ好友”按钮的分享内容(JSSDK 1.4.0以上版本支持):

  1. wx.ready(function () { //需在用户可能点击分享按钮前就先调用
  2. wx.updateAppMessageShareData({
  3. title: '', // 分享标题
  4. desc: '', // 分享描述
  5. link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
  6. imgUrl: '', // 分享图标
  7. success: function () {
  8. // 设置成功
  9. }
  10. })
  11. });

自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容(JSSDK 1.4.0以上版本支持):

  1. wx.ready(function () { //需在用户可能点击分享按钮前就先调用
  2. wx.updateTimelineShareData({
  3. title: '', // 分享标题
  4. link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
  5. imgUrl: '', // 分享图标
  6. success: function () {
  7. // 设置成功
  8. }
  9. })
  10. });

获取“分享给朋友”按钮点击状态及自定义分享内容接口(即将废弃):

  1. wx.onMenuShareAppMessage({
  2. title: '', // 分享标题
  3. desc: '', // 分享描述
  4. link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
  5. imgUrl: '', // 分享图标
  6. type: '', // 分享类型,music、video或link,不填默认为link
  7. dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
  8. success: function () {
  9. // 用户点击了分享后执行的回调函数
  10. }
  11. });

获取“分享到朋友圈”按钮点击状态及自定义分享内容接口(即将废弃):

  1. wx.onMenuShareTimeline({
  2. title: '', // 分享标题
  3. link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
  4. imgUrl: '', // 分享图标
  5. success: function () {
  6. // 用户点击了分享后执行的回调函数
  7. }
  8. },

获取“分享到QQ”按钮点击状态及自定义分享内容接口(即将废弃):

  1. wx.onMenuShareQQ({
  2. title: '', // 分享标题
  3. desc: '', // 分享描述
  4. link: '', // 分享链接
  5. imgUrl: '', // 分享图标
  6. success: function () {
  7. // 用户确认分享后执行的回调函数
  8. },
  9. cancel: function () {
  10. // 用户取消分享后执行的回调函数
  11. }
  12. });

注意:

如果用旧版的 wx.onMenuShareTimelinewx.onMenuShareAppMessage、wx.onMenuShareQQ 接口,请用1.4.0或者1.0.0的SDK。

我们用新接口的时候一直提示没有权限,用原接口的时候提示签名错误,后来换了1.0.0的SDK,后台又重新检查了下签名,并把 jsapi_ticket 缓存去掉。主要就是要一步步去测试,然后就神奇的好了。

完整的自定义分享代码:

  1. getWXShare() {
  2. axios.get('***/***/getShareTicket', MD5({
  3. url: location.href
  4. }), function (data) {
  5. if (data.code === 200) {
  6. wx.config({
  7. // debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  8. appId: data.data.appId, //后台 必填,公众号的唯一标识
  9. timestamp: data.data.timestamp, // 必填,后台生成签名的时间戳
  10. nonceStr: data.data.nonceStr, // 必填,后台生成签名的随机串
  11. signature: data.data.signature,// 必填,后台签名
  12. jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareAppMessage','onMenuShareTimeline', 'onMenuShareQQ', 'onMenuShareQZone']
  13. });
  14.  
  15. wx.ready(function () {
  16. //分享到朋友圈(旧)
  17. wx.onMenuShareTimeline({
  18. title: '要分享的标题', // 分享标题
  19. desc: '要分享的简介',
  20. link: "要分享的地址", // 分享链接,
  21. imgUrl: '要分享图标', // 分享图标
  22. success: function () {
  23. // 用户点击了分享后执行的回调函数
  24. // console.log("分享成功");
  25. },
  26. cancel: function () {
  27. // 用户取消分享后执行的回调函数
  28. // console.log("分享取消");
  29. }
  30. });
  31. // 朋友(旧)
  32. wx.onMenuShareAppMessage({
  33. title: '要分享的标题', // 分享标题
  34. desc: '要分享的简介',
  35. link: "要分享的地址", // 分享链接,
  36. imgUrl: '要分享图标', // 分享图标
  37. success: function () {
  38. // 用户点击了分享后执行的回调函数
  39. // console.log("分享成功2");
  40. },
  41. cancel: function () {
  42. // 用户取消分享后执行的回调函数
  43. // console.log("分享取消2");
  44. }
  45. });
  46. });
  47. //必须放wx.ready后面 否则无法执行
  48. wx.error(function(res){
  49. //config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
  50. });
  51. } else {
  52. alert('请稍后后再试')
  53. }
  54. })
  55. },

总结

到这一步分享的操作基本就完成了,建议在测试时将debug打开,看看分享提示,从而判定是否分享成功。如果不成功,可以参考一下在开发时候遇到的坑。

    • 出现nvalid url domain提示
      1)检查当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,仅支持80(http)和443(https)两个端口,因此不需要填写端口号。
    • 出现invalid signature签名错误提示
      1)检查生成signature是否正确,可以通过签名校验工具来判定后端传过来的nonceStr、timestamp与请求后端接口传的地址,与最后签名是否一致。
      2) config时,nonceStr 记得驼峰写法。
      3) 签名用的url必须是调用JS接口页面的完整URL,即当前页面的完整URL。
    • 提示是成功的,但是分享出来图标不见或者desc不显示的情况
      1) 分享的地址不要带端口号。
      2)分享desc 不要带有敏感词汇。

微信内 H5 页面自定义分享的更多相关文章

  1. 微信公众号h5页面自定义分享

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  2. Java微信公众平台开发之公众号支付(微信内H5调起支付)

    官方文档点击查看准备工作:已通过微信认证的公众号,必须通过ICP备案域名(否则会报支付失败)借鉴了很多大神的文章,在此先谢过了 整个支付流程,看懂就很好写了 一.设置支付目录 在微信公众平台设置您的公 ...

  3. 微信支付 第三篇 微信调用H5页面进行支付

    上一篇讲到拿到了 预支付交易标识 wx251xxxxxxxxxxxxxxxxxxxxxxxxxxxxx078700 第四步,是时候微信内H5调起支付了! 先准备网页端接口请求参数列表 微信文档中已经明 ...

  4. 基于Jquery WeUI的微信开发H5页面控件的经验总结(1)

    在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...

  5. 基于Jquery WeUI的微信开发H5页面控件的经验总结(2)

    在微信开发H5页面的时候,往往借助于WeUI或者Jquery WeUI等基础上进行界面效果的开发,由于本人喜欢在Asp.net的Web界面上使用JQuery,因此比较倾向于使用 jQuery WeUI ...

  6. vue 微信内H5调起支付

    在微信内H5调起微信支付,主要依赖于一个微信的内置对象WeixinJSBridge,这个对象在其他浏览器中无效. 主要代码: import axios from 'axios'; export def ...

  7. Hybrid App中原生页面 VS H5页面(分享)

    本文部分转自  http://www.jianshu.com/p/00ff5664e000 现有3类主流APP,分别为:Web App.Hybrid App(混合模式移动应用,Hybrid有“混合的” ...

  8. 微信公众号jssdk自定义分享,二次分享自定义失败解决技巧

    百度上自定义微信分享标题以及描述的解决方法有很多,基本上都能实现一次分享:流程基本上是这样的 1.首先引入微信jssdk =><script src="http://res.wx ...

  9. .netcore2.1 JS-SDK 从后台获取微信签名,实现自定义分享标题、描述、图片

    最近项目移动端需要实现微信自定义分享功能,包含分享自定义标题.描述等. 首先到公众号的后台,功能设置里面,添加将要被分享的域名,如图 后端签名算法实现 ,参考腾讯开发者文档https://mp.wei ...

随机推荐

  1. 1072 Gas Station

    A gas station has to be built at such a location that the minimum distance between the station and a ...

  2. 基于Docker安装的MindSpore-1.2 GPU版本

    技术背景 在前面一篇博客中,我们介绍过MindSpore-CPU版本的Docker部署以及简单的案例测试,当时官方还不支持GPU版本的Docker容器化部署.经过MindSpore团队的努力,1.2. ...

  3. 逆向工程第005篇:跨越CM4验证机制的鸿沟(下)

    一.前言 本文是逆向分析CM4系列的最后一篇,我会将该游戏的序列号验证机制分析完毕,进而编写出注册码生成器. 二.分析第二个验证循环 延续上一篇文章的内容,来到如下代码处: 图1 上述代码并没有特别需 ...

  4. 【js】Leetcode每日一题-完成所有工作的最短时间

    [js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...

  5. 百度地图api根据用户IP获取用户位置(PHP)

    1.百度地图开放平台找的你的ak ,链接:http://lbsyun.baidu.com/apiconsole/key 2.获取用户ip地址(外网ip 服务器上可以获取用户外网Ip 本机ip地址只能获 ...

  6. Linux下为Calibre书库打中文目录名与文件名补丁

    本文由来 临近下班突然看到知乎上有篇文章是给Calibre打中文目录与文件名补丁的,想起我之前为啥放弃Calibre的--存进书库里书的名称都变成了拼音!手动找起来或者搜索工具找起来太麻烦了(有时想不 ...

  7. .NET 在信创常用软件适配清单之中?

    2020年8月份写了一篇文章<.NET Core也是国产化信息系统开发的重要选项>, 这又过去了大半年了,在信创领域发生了很大的变化,今天写这篇文章主要是想从信创常用软件适配清单 看一看. ...

  8. C++入门教程之一:Hello world

    C++入门教程之一:Hello world C++是各位程序员跳不过的一个坑,也是各位想学编程的人必备的知识,更是各大比赛(如NOI)的官方指定语言. 在TIOBE(一个编程语言社区排行榜)中,截止2 ...

  9. 用fseek和ftell获取文件的大小

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc,char ...

  10. 通俗易懂的JS之Proxy

    与掘金文章同步,地址:https://juejin.cn/post/6964398933229436935 什么是代理模式 引入一个现实生活中的案例 我们作为用户需要去如何评估一个房子的好坏.如何办理 ...