微信小程序获取手机号

559 阅读1分钟

微信小程序获取手机号码 官方文档  的介绍已经很详细了。但是当时获取手机号码还是出现了意外。当我得到 encryptedData 和 iv 之后就傻眼了。微信官方提供了多种编程语言的示例代码 。有PHP,Python, Node,c++。 唯独没有Java的示例代码。于是在此记录一下具体的方法。

  • 获取微信用户绑定的手机号,需先调用wx.login接口

  • 需要用户主动触发才能发起获取手机号接口,需用 button 组件的点击来触发。

  1. button 组件 open-type 的值设置为 getPhongeteNumber

    <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号码</button>
    
  2. 用户点击并同意之后,可以通过 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          })        }      })    }  },
    
  3. 服务端结合 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 "";
    }