微信小程序获取手机号登录
大约 3 分钟
微信小程序获取手机号登录
旧版登录
登录流程图
登录操作步骤
- 因为需要用户主动触发才能发起获取手机号接口,需用 button 组件的点击来触发
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
getPhoneNumber (e) {
console.log(e.detail.code)
console.log(e.detail.errMsg)
console.log(e.detail.iv) //加密算法的初始向量
console.log(e.detail.encryptedData)//包括敏感数据在内的完整用户信息的加密数据
}
- 获取微信用户绑定的手机号,调用 uni.login() 获取 code 值 对应微信 wx.login()
// uniapp
getPhoneNumber (e) {
//....
uni.login({
provider: 'weixin',
success: (res) => {
console.log(res.code)
}
})
}
//微信
getPhoneNumber (e) {
//...
wx.login({
success(res) {
console.log(res.code)
}
})
}
发送请求到业务系统后端,使用 code 换取 openid、unionid、session_key 等信息
后端 https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
前端
getPhoneNumber (e) { //.... let _this = this uni.login({ provider: 'weixin', success: (res) => { // 发送 res.code 到后台换取 openId, sessionKey, unionId let opParams = {} _this.$http.post('', opParams, function (code_res) { //TODO:存储openId, sessionKey, unionId到本地缓存 }) } }) }
根据 getPhoneNumber 获取的初始加密值和 openId, sessionKey 获取手机号 后端
public JSONObject decodeWxAppPhoneService(String encrypted, String iv, String code) {
try{
// JSONObject json = JSONObject.fromObject(new UserInfoController().sendPost(WX_APPID, WX_SECRET, code, "authorization_code"));
// String jsonStr = EntityUtils.toString(response.getEntity());
// JSONObject jsonObject = JSON.parseObject(jsonStr);
JSONObject json = JSONObject.fromObject(code);
String sessionkey = json.getString("session_key");
// 解密
byte[] encrypData = Base64Utils.decodeFromString(encrypted);
byte[] ivData = Base64Utils.decodeFromString(iv);
byte[] sessionKey = Base64Utils.decodeFromString(sessionkey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKey, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String resultString = new String(cipher.doFinal(encrypData), "UTF-8");
JSONObject object = JSONObject.fromObject(resultString);
// 拿到手机号码
String phone = object.getString("phoneNumber");
// 返回手机号码
JSONObject returnObject = new JSONObject();
returnObject.put("phone", phone);
return returnObject;
} catch (Exception e) {
System.out.println("微信小程序手机号码解密异常,信息如下:");
e.printStackTrace();
}
return null;
}
前端
getPhoneNumber (e) {
//....
let _this = this
uni.login({
provider: 'weixin',
success: (res) => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
let opParams = {}
_this.$http.post('', opParams, function (code_res) {
//TODO:存储openId, sessionKey, unionId到本地缓存
let params = {
session_key: wx.getStorageSync('session_key'),
//为了让手机号码和用户的唯一标识身份的openId关联起来所以才传的openId
wxOpenid: wx.getStorageSync('openId'),
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
}
// 发送请求获取手机号
_this.$http.post('', params, function (code_res) {})
})
}
})
}
最终代码
ongetPhoneNumber(e) {
/*
1.获取微信小程序认证appId和secret
2.后端根据appId和secret,code(前端获取),后端调用
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
返回openId, sessionKey, unionId
3.前端拼接参数 encryptedData,iv,openId,sessionKey,后端调用微信小程序
"https://api.weixin.qq.com/wxa/business/getuserphonenumber" + 拼接参数,返回手机号,
4.前端存储手机号、根据手机号调用登录接口
*/
let _this = this
if (e.detail.errMsg == 'getPhoneNumber:fail:user deny') {
uni.showToast({
title: '您拒绝了授权,将不能正常使用小程序',
icon: 'error',
duration: 3000
})
} else {
// 调用 action ,请求登录接口
uni.login({
provider: 'weixin',
success: (res) => {
//获取到code
_this.wxCode = res.code
//请求登录接口
if (res.errMsg == 'login:ok') {
let params = {
code: _this.wxCode
}
console.log('res3 :>> ', res)
// 发送 res.code 到后台换取 openId, sessionKey, unionId
_this.$http.post('', params, function (code_res) {
wx.setStorageSync('openId', code_res.data.data.openid)
wx.setStorageSync('session_key', code_res.data.data.session_key)
wx.setStorageSync('unionId', code_res.data.data.wxUid)
// 获取手机号
let insertUserPhoneData = {
//足够解密手机号使用了start
session_key: wx.getStorageSync('session_key'),
encryptedData: e.detail.encryptedData,
iv: e.detail.iv,
//足够解密手机号使用了end
//为了让手机号码和用户的唯一标识身份的openId关联起来所以才传的openId
wxOpenid: wx.getStorageSync('openId'),
//这个learnerCode是业务需要,你们可以不要
learnerCode: wx.getStorageSync('learnerCode')
}
// 发送请求获取手机号
_this.$http.post('', insertUserPhoneData, function (phone_res) {
console.log('phone_res :>> ', phone_res)
let loginParams = {}
// TODO:具体登录接口发送
that.$http.post(
'',
loginParams,
function (res) {
if (res.code == 200) {
uni.showToast({
title: '登录成功',
icon: 'success',
mask: true
})
//获取到token 存入缓存。通过有无token来判断是否登录
uni.setStorageSync(
ACCESS_TOKEN,
res.data.data.access_token
)
}
},
function (err) {
uni.showToast({
icon: 'none',
title: err.msg
})
}
)
})
})
}
}
})
}
}