H5活动的微信授权与分享

背景

某一天接到个H5的活动页面需求,需求是如下:

  • 总共三个页面(不重要)
  • 第一个页面点击跳转第二个页面获取授权,拿取微信信息
  • 在第二个页面能长按保存整个图片
  • 自定义分享内容,(三个页面都能分享,是同样的分享内容)

    开始

    1,你需要准备的东西

  • 微信公众平台——服务号
  • jquery
  • html2canvas.js
  • jweixin-1.4.0.js
  • sha1.js

    2,准备页面

    3,公众平台配置网页授权域名

    在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头;
    前端的东西必须通过这个域名能访问到。
    参数定义
    参数定义

    4,微信授权

    微信授权分为两种形式,snsapi_base,snsapi_userinfo,区别在于前者是静默状态,只能获取进入页面的用户的openid的,后者是会出现以下页面的,获取用户的基本信息,需要用户手动同意授权,如下:
    微信授权
    要到达上面的页面,需要开发者调用
    https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
    //若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
    上面链接的意思就是,跳转到授权页面,获取code(注意不要改变参数顺序)每个参数的定义如下:
    参数定义
    参数定义
    以上其实主要修改的参数就是appid和redirect_uri,一个是你的公众号的唯一id,一个是你授权成功后的重定向路径(授权成功后要跳转的页面)。 ### 5,通过code获取access_token与openId,并且获取到信息 获取token的接口
    https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

这儿你可能需要这个函数,获取url参数

1
2
3
4
5
function 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
4
noncestr=''  //随机字符串
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
2
3
4
5
6
7
8
9
10
11
12
13
14
function sort_ASCII(obj) {
var arr = new Array();
var num = 0;
for (var i in obj) {
arr[num] = i;
num++;
}
var sortArr = arr.sort();
var sortObj = {};
for (var i in sortArr) {
sortObj[sortArr[i]] = obj[sortArr[i]];
}
return sortObj;
}
6,排序后拼接成如下字符串
1
jsapi_ticket=对应的值&noncestr=对应的值&timestamp=对应的值&url=对应的值
7,调用sha1.js,进行签名,后获得签名字符串

这个就要用到文章开始得工具了sha1.js

1
2
var str = 'jsapi_ticket=对应的值&noncestr=对应的值&timestamp=对应的值&url=对应的值';
sha1(str);

6,注入wx.config配置参数

timestamp,nonceStr,signature,即上一步所生成的字符串,但是得与上面得保持一致,appId就是前面授权时得唯一标识Id

1
2
3
4
5
6
7
8
wx.config({
debug: true, // 调试(调试完毕后请关闭或者注释)
appId: '', // 必填,公众号的唯一标识
timestamp: '', // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline'] // 必填,需要调用的接口列表
});

7, 通过ready接口处理成功验证(在此调用接口),error接口处理错误

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

更多接口,请参考微信文档

7,长按保存图片(html2canvas)

用这个原因时因为,H5不可能是一张图,它是多张图与标签组合的,往往需要微信用户的名字与头像和活动的结果图一起构成的,但是如果直接调用微信的保存图片,只是保存了选中的图片,所以,我们需要把网页截屏成图片覆盖html,让用户直接保存这张截图。
网上很多介绍都很简单,类似与

1
2
3
html2canvas(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
12
html2canvas(
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
20
function 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活动页的经过。
接受所有向上的建议,向各位大佬学习,不接受无理的吐槽喷人。