微信小程序授权功能
授权
部分接口需要经过用户授权同意才能调用。我们把这些接口按使用范围分成多个 scope ,用户选择对 scope 来进行授权,当授权给一个 scope 之后,其对应的所有接口都可以直接使用。
部分接口需要获得用户授权同意后才能调用。此类接口调用时:
1.如果用户未接受或拒绝过此权限,会弹窗询问用户,用户点击同意后方可调用接口;
2.如果用户已授权,可以直接调用接口;
3.如果用户已拒绝授权,则不会出现弹窗,而是直接进入接口 fail 回调。请开发者兼容用户拒绝授权的场景。
获取用户授权设置
开发者可以使用 wx.getSetting 获取用户当前的授权状态。
打开设置界面
用户可以在小程序设置界面(「右上角」 – 「关于」 – 「右上角」 – 「设置」)中控制对该小程序的授权状态。
开发者可以调用 wx.openSetting 打开设置界面,引导用户开启授权。
提前发起授权请求
开发者可以使用 wx.authorize 在调用需授权 API 之前,提前向用户发起授权请求。
scope 列表
scope.userInfo wx.getUserInfo 用户信息 scope.userLocation wx.getLocation, wx.chooseLocation 地理位置 scope.address wx.chooseAddress 通讯地址 scope.invoiceTitle wx.chooseInvoiceTitle 发票抬头 scope.invoice wx.chooseInvoice 获取发票 scope.werun wx.getWeRunData 微信运动步数 scope.record wx.startRecord 录音功能 scope.writePhotosAlbum wx.saveImageToPhotosAlbum, wx.saveVideoToPhotosAlbum 保存到相册 scope.camera <camera /> 组件 摄像头 注意:wx.authorize({scope: "scope.userInfo"}),不会弹出授权窗口,请使用 <button open-type="getUserInfo"></button> |
获取用户信息demo
// 查看是否授权() wx.getSetting({ //获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。 success(res) { console.log('getSetting' + JSON.stringify(res)); //getSetting{"errMsg":"getSetting:ok","authSetting":{}} if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称 wx.getUserInfo({ success(res) { //{nickName: "1111", gender: 1, language: "zh_CN", city: "Jining", province: "Shandong", …} console.log(res.userInfo) } }) } else { console.log('scope.userInfo授权不存在') //授权不存在则跳转到用户授权页面或者发起授权请求 } } }) |
小程序可以通过各种前端接口获取微信提供的开放数据。考虑到开发者服务器也需要获取这些开放数据,微信会对这些数据做签名和加密处理。开发者后台拿到开放数据后可以对数据进行校验签名和解密,来保证数据不被篡改。
签名校验以及数据加解密涉及用户的会话密钥 session_key。 开发者应该事先通过 wx.login 登录流程获取会话密钥 session_key 并保存在服务器。为了数据不被篡改,开发者不应该把 session_key 传到小程序客户端等服务器外的环境。
数据签名校验
为了确保开放接口返回用户数据的安全性,微信会对明文数据进行签名。开发者可以根据业务需要对数据包进行签名校验,确保数据的完整性。
1.通过调用接口(如 wx.getUserInfo)获取数据时,接口会同时返回 rawData、signature,其中 signature = sha1( rawData + session_key )
2.开发者将 signature、rawData 发送到开发者服务器进行校验。服务器利用用户对应的 session_key 使用相同的算法计算出签名 signature2 ,比对 signature 与 signature2 即可校验数据的完整性。
通过uni.getUserInfo接口获取用户信息 https://developers.weixin.qq.com/community/develop/doc/0000a26e1aca6012e896a517556c01
{ encryptedData:"omOZMH+hVwxt6MGGTVb6BzfY4SciBVPEj4pebZjIAqwcmPhwFcTL2OrWS2eV885oSFKTZbCFsv6Z8yRl/Y98tBoyvXj0Z2xbSexiWWp/zrWx6JAoRol+CY8hfyy6Fveu/IwD0etV3mXr5Rj42QSBpgJXlgV61T4pDtG8XgH3neu7kovNo4x0jd98BQiwKOrWznBGXQYwHe32INYKNx4oosD2ZlDKemKrwN3rvyezFHWyMMQ1pue5PgEtM4V6mJIndDOMfGJ/TtuMO7/NfKgOrZOUrs5q2QqaQfy0eKjhD9IcDadURbuZCwWPmJF1hv5w6/3LjJF2/PflqZjP40D3mOFaWGoh+xp73Z7VvqWQQpPhl6Nr5SzpRTpVGGAmU8QLhM3MTYnV5tDdifhcG5vMavi8GaQpTudT7DSTU8Z1gyYzIsmcGKWZ9iciA2CJNjy1ksdXHPEv+eyv02WHQBJGe+leRLLZA2cPkUH78uWQhyg=" errMsg:"getUserInfo:ok" iv:"ef/NM11oC+sga9Ltb4/k5A==" rawData:"{"nickName":"1111","gender":1,"language":"zh_CN","city":"Jining","province":"Shandong","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/ABV2HiavCONyA7ssrjfkKwGlwNibXhsmwuj6dOXRyW8HTYBYGNPf5S67GcotJTTcYgAG2A7framqibmnuuorPwWQw/132"}" signature:"62eef65a0609c51f69916cc8ae3e3fd5de2a5f61" userInfo:{nickName: "1111", gender: 1, language: "zh_CN", city: "Jining", province: "Shandong", …} } |
encryptedData数据进行解密(php版本)
demo和sdk下载地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/demo/aes-sample.zip
decryptData($encryptedData, $iv, $data );
if ($errCode == 0) {
/* 获取的解密数据如下:
$data {
“openId”:”orwIJ0fjAUInTl-7kGBkdVRw4MKM”,
“nickName”:”nickName”,
“gender”:1,
“language”:”zh_CN”,
“city”:”Jining”,
“province”:”Shandong”,
“country”:”China”,
“avatarUrl”:”https://wx.qlogo.cn/mmopen/vi_32/ABV2HiavCONyA7ssrjfkKwGlwNibXhsmwuj6dOXRyW8HTYBYGNPf5S67GcotJTTcYgAG2A7framqibmnuuorPwWQw/132″,
“watermark”:{“timestamp”:1547781041,”appid”:”wxaf151ae9618b2917″}
}*/
print($data . “\n”);
} else {
print($errCode . “\n”);
}
?>
会话密钥 session_key 有效性
开发者如果遇到因为 session_key 不正确而校验签名失败或解密失败,请关注下面几个与 session_key 有关的注意事项:
1.wx.login 调用时,用户的 session_key 可能会被更新而致使旧 session_key 失效(刷新机制存在最短周期,如果同一个用户短时间内多次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确需要重新登录时才调用 wx.login,及时通过 code2Session 接口更新服务器存储的 session_key。
2.微信不会把 session_key 的有效期告知开发者。我们会根据用户使用小程序的行为对 session_key 进行续期。用户越频繁使用小程序,session_key 有效期越长。
3.开发者在 session_key 失效时,可以通过重新执行登录流程获取有效的 session_key。使用接口 wx.checkSession可以校验 session_key 是否有效,从而避免小程序反复执行登录流程。
4.当开发者在实现自定义登录态时,可以考虑以 session_key 有效期作为自身登录态有效期,也可以实现自定义的时效性策略。
19年3月22日记录内容
最完整的授权流程(兼容授权弹窗时用户点击拒绝),获取地理位置示例:
注意:给一个按钮设置点击事件调用wx.authorize,如果第一次用户点击了授权弹框的拒绝的话,下一次点击按钮的话就不会调起授权弹框
data: { settingShow:false //是否显示位置按钮 } wx.getSetting({ success(res) { if (res.authSetting['scope.userLocation'] === false) { // ①如果用户设置过获取位置权限 但是为不允许状态 //需要打开设置允许地理位置权限,显示设置按钮 _that.setData({settingShow:true}); } else if (res.authSetting['scope.userLocation22'] === undefined) { // ②如果用户未请求过获取位置授权,首次弹出授权弹窗 wx.authorize({ //请求用户授权地理位置 scope: 'scope.userLocation', success(e) { wx.getLocation({ type: 'wgs84', success(res) { console.log(res) //地理位置信息 } }) } }) } else { // ③允许用户获取地理位置 wx.getLocation({ type: 'wgs84', success(res) { /* accuracy:65 errMsg:"getLocation:ok" horizontalAccuracy:65latitude:35.4082 longitude:116.59649 speed:-1 verticalAccuracy:65 */ console.log(res) const latitude = res.latitude const longitude = res.longitude const speed = res.speed const accuracy = res.accuracy } }) } } }) |
服务器端坐标转换为地址信息(腾讯接口地址)
public function coord2Address($lat,$long,$getPoi = 1){ $location= "{$lat},{$long}"; $url = "https://apis.map.qq.com/ws/geocoder/v1/?location={$location}&get_poi={$getPoi}&output=JSON&key=FRHBZ-BCAKF-AP2JF-NS2MF-Y5YUH-CTF7H"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($ch); dump(json_decode($result,true)); //相关地理位置信息 } |
打开小程序设置页(wx.openSetting)接口调整 只有请求过授权接口才会显示相关scope
<button open-type="openSetting" bindopensetting="opensetting">打开设置页</button> |