小程序官方文档中介绍:
获取微信用户绑定的手机号,需先调用wx.login接口。 因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。
注意:目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。具体可参考小程序API
使用方法 需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,可以通过 bindgetphonenumber 事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key 以及 app_id 进行解密获取手机号。
复制代码
在使用组件之前先调用login
App({
onLaunch: function () {
wx.login({
success: function (res) {
if (res.code) {
//发起网络请求
this.globalData.code = res.code;
console.log(res.code)
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
});
},
globalData: {}
})
复制代码
getPhoneNumber中将返回用户是否同意授权的数据,
const App = getApp();
Page({
getPhoneNumber(e) {
const { iv, encryptedData, errMsg } = e.detail;
if (errMsg === 'getPhoneNumber:ok') {
// 同意授权
wx.request({
url: '/GetPhone',
data: {
code: App.globalData.code,
iv,
encryptedData
},
success: (res) => {
console.log(res);
}
})
}
}
})
复制代码
后端需要根据前端传递的code,iv, encryptedData,结合小程序的appID,secret,先获取session_key,然后在进行电话号码解析。为了安全考虑,我们的appID和secret都是存放在后端的,所以获取session_key和电话解析都放后端进行了,前端只需调用接口即可。
获取session_key的地址
const APP_ID = '';
const SECRET = '';
const BASE_URL = 'https://api.weixin.qq.com';
const url = `${BASE_URL}/sns/jscode2session?appid=${APP_ID}&secret=${SECRET}&js_code=${res.code}&grant_type=authorization_code`;
复制代码
电话号码解析实例(java版)
import org.apache.shiro.codec.Base64;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
@Controller
public class GetPhone {
/*用户手机号解析*/
@RequestMapping("/getPhoneNumber")
@ResponseBody
public String getPhoneNumber(String encryptedData, String iv, String sessionKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
System.out.println(encryptedData + "-------" + iv + "-------" + sessionKey);
byte[] encData = http://www.wxapp-union.com/Base64.decode(encryptedData);
byte[] keyByte = Base64.decode(iv);
byte[] key = Base64.decode(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(keyByte);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);// 初始化
byte[] resultByte = cipher.doFinal(encData);
if (null != resultByte && resultByte.length > 0) {
String result = new String(resultByte, "UTF-8");
System.out.println(result);
return result;
}
return null;
}
复制代码
注意:在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态。
最后提醒大家,进入一个未知的小程序时,弹出用户授权询问框时,谨慎授权。如下图