H5活动的微信授权与分享
背景
某一天接到个H5的活动页面需求,需求是如下:
- 总共三个页面(不重要)
- 第一个页面点击跳转第二个页面获取授权,拿取微信信息
- 在第二个页面能长按保存整个图片
- 自定义分享内容,(三个页面都能分享,是同样的分享内容)
开始
1,你需要准备的东西
- 微信公众平台——服务号
- jquery
- html2canvas.js
- jweixin-1.4.0.js
- sha1.js
2,准备页面
3,公众平台配置网页授权域名
在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;
前端的东西必须通过这个域名能访问到。4,微信授权
微信授权分为两种形式,snsapi_base,snsapi_userinfo,区别在于前者是静默状态,只能获取进入页面的用户的openid的,后者是会出现以下页面的,获取用户的基本信息,需要用户手动同意授权,如下:
要到达上面的页面,需要开发者调用
上面链接的意思就是,跳转到授权页面,获取code(注意不要改变参数顺序)每个参数的定义如下: 以上其实主要修改的参数就是appid和redirect_uri,一个是你的公众号的唯一id,一个是你授权成功后的重定向路径(授权成功后要跳转的页面)。 ### 5,通过code获取access_token与openId,并且获取到信息 获取token的接口https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect //若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
这儿你可能需要这个函数,获取url参数1
2
3
4
5function getUrlParam(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
这儿H5前端请求会存在跨域问题,微信也不支持jsonp,这儿需要解决跨域的问题,才能请求到数据,我在这儿是把code参数传给后端让后端去拿数据,并且通过access_token与openId去拿取用户信息,后面的跨域接口,都是通过后端去转发的
请根据你的业务需求,与后端配合解决
获取信息得接口:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
以上就拿到信息了:1
2
3
4
5
6
7
8
9
10
11{
"openid":" OPENID",
"nickname": NICKNAME,
"sex":"1",
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl":"http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
了解更多请参考微信网页授权文档
5,接下来是微信分享自定义
我们一般是想想要下面的这种结果,微信官方的文档就很清晰了
微信JS_SDK
1,绑定域名
同授权的域名方式,进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
2,引入js
1.0.0的版本存在二次分享无效的问题,1.2.0以上就没出现过了1
http://res.wx.qq.com/open/js/jweixin-1.4.0.js
3,基础access_token获取
这儿的token和网页授权的token是不一样的,通过下面的接口获取1
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
4,获得jsapi_ticket
拿到access_token后,请求下面的接口,获得ticket,获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。1
https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
5,JS-SDK权限验证签名
官网说明要以下四个参数1
2
3
4noncestr='' //随机字符串
jsapi_ticket='' //获取的jsapi_ticket
timestamp='' //当前时间戳(以秒换算)
url='' //需要调用的当前url(只需要‘#’前面的部分)
1,随机字符串
1 | Math.random().toString(36).slice(-8) |
2,获取的jsapi_ticket
3,时间戳
1 | Date.parse(new Date()) / 1000 |
4,当前网页的URL
1 | window.location.href.split('#')[0] |
5,签名参数按照字段名的ASCII 码从小到大排序
1 | function sort_ASCII(obj) { |
6,排序后拼接成如下字符串
1 | jsapi_ticket=对应的值&noncestr=对应的值×tamp=对应的值&url=对应的值 |
7,调用sha1.js,进行签名,后获得签名字符串
这个就要用到文章开始得工具了sha1.js1
2var str = 'jsapi_ticket=对应的值&noncestr=对应的值×tamp=对应的值&url=对应的值';
sha1(str);
6,注入wx.config配置参数
timestamp,nonceStr,signature,即上一步所生成的字符串,但是得与上面得保持一致,appId就是前面授权时得唯一标识Id1
2
3
4
5
6
7
8wx.config({
debug: true, // 调试(调试完毕后请关闭或者注释)
appId: '', // 必填,公众号的唯一标识
timestamp: '', // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline'] // 必填,需要调用的接口列表
});
7, 通过ready接口处理成功验证(在此调用接口),error接口处理错误
1 | //需在用户可能点击分享按钮前就先调用 |
更多接口,请参考微信文档
7,长按保存图片(html2canvas)
用这个原因时因为,H5不可能是一张图,它是多张图与标签组合的,往往需要微信用户的名字与头像和活动的结果图一起构成的,但是如果直接调用微信的保存图片,只是保存了选中的图片,所以,我们需要把网页截屏成图片覆盖html,让用户直接保存这张截图。
网上很多介绍都很简单,类似与1
2
3html2canvas(document.querySelector("#capture")).then(canvas => {
var imgUri = canvas.toDataURL("image/png", 1);
});
我大概讲一下我所遇到的坑吧!
解决图片跨域,画布污染的问题,crossorigin=”anonymous” 和 useCORS: true
调用插件,截屏,你需要选择body一下的某个容器。1
2
3
4
5
6
7
8
9
10
11
12html2canvas(
document.getElementById("content"),
{
useCORS: true,
allowTaint: true
}
).then(function (canvas) {
// 获取生成的图片的base64
var imgUri = canvas.toDataURL("image/png", 1);
//压缩
suofang(imgUri, '1.5');
});
base64压缩,不多讲了,网上一大堆,直接上函数吧1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function suofang(base64, bili) {
var _img = new Image();
_img.src = base64;
_img.onload = function () {
var _canvas = document.createElement("canvas");
var w = this.width / bili;
var h = this.height / bili;
_canvas.setAttribute("width", w);
_canvas.setAttribute("height", h);
_canvas.getContext("2d").drawImage(this, 0, 0, w, h);
var base64 = _canvas.toDataURL("image/jpeg");
_canvas.toBlob(function (blob) {
if (blob.size > 1024 * 1024) {
suofang(base64, bili);
} else {
$("#newImg").attr("src", base64);
}
}, "image/jpeg");
}
}
了解更多canvas画布污染和图片跨域的问题,请参考安全性和“被污染”的 canvas
到此,就是本次H5活动页的经过。
接受所有向上的建议,向各位大佬学习,不接受无理的吐槽喷人。