微信小程序获取手机号码 官方文档 的介绍已经很详细了。但是当时获取手机号码还是出现了意外。当我得到 encryptedData 和 iv 之后就傻眼了。微信官方提供了多种编程语言的示例代码 。有PHP,Python, Node,c++。 唯独没有Java的示例代码。于是在此记录一下具体的方法。
-
将 button 组件
open-type的值设置为getPhongeteNumber<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号码</button> -
用户点击并同意之后,可以通过
bindgetphonenumber事件回调获取到微信服务器返回的加密数据getPhoneNumber: function (e) { var that = this if (e.detail.errMsg == 'getPhoneNumber:fail user deny') { wx.showModal({ title: '提示', showCancel: false, content: '未授权', success: function (res) { // 用户点击取消 } }) } else { wx.showModal({ title: '提示', showCancel: false, content: '授权成功', success: function (res) { that.setData({ encryptedData: e.detail.encryptedData, // 返回的加密数据 iv: e.detail.iv }) } }) } }, -
服务端结合
session_key以及app_id进行解密获取手机号。public String getPhoneNumber(String encryptedData, String iv) { String session_key; // 获取到sessionKey // 对称解密的目标密文 byte[] encryptedByte = Base64.decode(encryptedData); // 对称解密秘钥 byte[] sessionKeyByte = Base64.decode(session_key); // 对称解密算法初始向量 byte[] ivByte = Base64.decode(iv); try { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (sessionKeyByte.length % base != 0) { int groups = sessionKeyByte.length / base + (sessionKeyByte.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(sessionKeyByte, 0, temp, 0, sessionKeyByte.length); sessionKeyByte = temp; } // 初始化 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec spec = new SecretKeySpec(sessionKeyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 byte[] resultByte = cipher.doFinal(encryptedByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, "UTF-8"); JSONObject parseObject = JSONObject.parseObject(result); return parseObject.getString("phoneNumber"); } } catch (Exception e) { e.printStackTrace(); } return ""; }