微信小程序API文档:https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html
在实际的小程序开发中,往往需要用户授权登陆并获取用户的数据,快速对接用户系统。
openId : 用户在当前小程序的唯一标识
unionId : 如果开发者拥有多个移动应用、网站应用、和公众帐号(包括小程序),可通过unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号(包括小程序),用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionId是相同的。详情登录微信开放平台(open.weixin.qq.com) 。
在微信小程序开发中,unionId等敏感数据则被加密在encryptedData,于是需要以下流程来解密敏感数据,从而获取unionId等信息。
当 withCredentials 为 true 时,要求此前有调用过 wx.login 且登录态尚未过期,此时返回的数据会包含 encryptedData, iv 等敏感信息;当 withCredentials 为 false 时,不要求有登录态,返回的数据不包含 encryptedData, iv 等敏感信息。
1、(客户端)微信小程序客户端调用 wx.login()接口获取登录凭证(code)
调用微信登录接口,获取code
wx.login({
success: function (r) {
var code = r.code;//登录凭证
if (code) {
//2、调用获取用户信息接口
//...
} else {
console.log('获取用户登录态失败!' + r.errMsg)
}
},
fail: function () {
callback(false)
}
})
客户端:微信小程序客户端调用 wx.getUserInfo()接口获取 用户基本信息、encryptedData(用户敏感信息加密数据) 和 iv(加密算法的初始向量 )
调用微信登录接口,获取code
wx.login({
success: function (r) {
var code = r.code;//登录凭证
if (code) {
//2、调用获取用户信息接口
wx.getUserInfo({
success: function (res) {
console.log({encryptedData: res.encryptedData, iv: res.iv, code: code})
//3.解密用户信息 获取unionId
//...
},
fail: function () {
console.log('获取用户信息失败')
}
})
} else {
console.log('获取用户登录态失败!' + r.errMsg)
}
},
fail: function () {
callback(false)
}
})
客户端:将前面获取到的 code 、encryptedData、iv发送到自己的服务器(开发者服务器),通过自己的服务器(开发者服务器)解密获取信息
调用微信登录接口,获取code
wx.login({
success: function (r) {
var code = r.code;//登录凭证
if (code) {
//2、调用获取用户信息接口
wx.getUserInfo({
success: function (res) {
console.log({encryptedData: res.encryptedData, iv: res.iv, code: code})
//3.请求自己的服务器,解密用户信息 获取unionId等加密信息
wx.request({
url: 'https://xxxx.com/wxsp/decodeUserInfo',//自己的服务接口地址
method: 'post',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
data: {encryptedData: res.encryptedData, iv: res.iv, code: code},
success: function (data) {
//4.解密成功后 获取自己服务器返回的结果
if (data.data.status == 1) {
var userInfo_ = data.data.userInfo;
console.log(userInfo_)
} else {
console.log('解密失败')
}
},
fail: function () {
console.log('系统错误')
}
})
},
fail: function () {
console.log('获取用户信息失败')
}
})
} else {
console.log('获取用户登录态失败!' + r.errMsg)
}
},
fail: function () {
console.log('登陆失败')
}
})
服务端php:自己的服务器发送code到微信服务器获取openid(用户唯一标识)和session_key(会话密钥),最后将encryptedData、iv、session_key通过AES解密获取到用户敏感数据
/**
* 解密用户敏感数据
*
* @param encryptedData 明文,加密数据
* @param iv 加密算法的初始向量
* @param code 用户允许登录后,回调内容会带上 code(有效期五分钟),开发者需要将 code 发送到开发者服务器后台,使用code 换取 session_key api,将 code 换成 openid 和 session_key
* @return
*/
include_once "wxBizDataCrypt.php";
function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
$code = $_GET['code'];
$iv = $_GET['iv'];
$encryptedData = $_GET['encryptedData'];
$appid = '';//小程序唯一标识 (在微信小程序管理后台获取)
$appsecret = '';//小程序的 app secret (在微信小程序管理后台获取)
$grant_type = "authorization_code"; //授权(必填)
$params = "appid=".$appid."&secret=".$appsecret."&js_code=".$code."&grant_type=".$grant_type;
$url = "https://api.weixin.qq.com/sns/jscode2session?".$params;
$res = json_decode(httpGet($url),true);
//json_decode不加参数true,转成的就不是array,而是对象。 下面的的取值会报错 Fatal error: Cannot use object of type stdClass as array in
$sessionKey = $res['session_key'];//取出json里对应的值
$pc = new WXBizDataCrypt($appid, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data);
if ($errCode == 0) {
print($data . "\n");
} else {
print($errCode . "\n");
}
加密数据解密算法
接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和unionId ),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据( encryptedData )进行对称解密。
解密算法如下:
对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
对称解密的目标密文为 Base64_Decode(encryptedData)。
对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
微信官方提供了多种编程语言的示例代码 下载:https://developers.weixin.qq.com/miniprogram/dev/demo/aes-sample.zip)。
每种语言类型的接口名字均一致。调用方式可以参照示例。
发表评论 取消回复