前言
小程序内可以直接通过授权获取用户微信号绑定的手机号码或用户添加的其他手机号码,这样可以使得小程序在进行账户的身份可控上又提高了一步,那么应该如何来获取手机号码呢?这篇文章就和大家一起来研究一下。
前提
值得注意的是,如果您要获取手机号码首先要满足如下要求:
注意:目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。 - 微信开发平台
正文
获取授权信息
首先,我们需要使用button
组件,其open-type
的值要设置为getPhoneNumber
,可参考button · 小程序,然后绑定bindgetphonenumber
的回调函数,在用户点击按钮,弹起的授权框允许授权之后回调函数内会返回一个event的对象,在其对象的detail下分别存在两个值(可参考《获取手机号 · 小程序》):
参数 | 类型 | 说明 |
---|---|---|
encryptedData | String | 包括敏感数据在内的完整用户信息的加密数据 |
iv | String | 加密算法的初始向量 |
接下来我们要模拟一次登录,调用wx.login
,然后再授权成功的回调中获取授权code值,接着将上述的encryptedData
与iv
一并传送至服务端,接下来就开始进行服务端解密过程。
服务端解密
服务端接收到encryptedData
、iv
与code
值之后,进行微信授权登录一次,接口可参考:《code2Session · 小程序》,然后我们需要获取返回值中的session_key
字段,即为会话秘钥。
在微信《开放数据校验与解密 · 小程序》中提供了多种编程语言的示例代码,但是就是没有Java的,不知道是不是微信团队从来不写Java ,于是我们就自己实现了一个
WXBizDataCrypt
,具体实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | public class WXBizDataCrypt { private String appid; private String sessionKey; public WXBizDataCrypt(String appid, String sessionKey) { this.appid = appid; this.sessionKey = sessionKey; } public JSONObject decryptData(String encryptedData, String iv) throws Exception{ byte[] dataByte = Base64.decodeBase64(encryptedData); // 加密秘钥 byte[] keyByte = Base64.decodeBase64(this.sessionKey); // 偏移量 byte[] ivByte = Base64.decodeBase64(iv); try { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keyByte.length % base != 0) { int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0); byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyByte, 0, temp, 0, keyByte.length); keyByte = temp; } // 初始化 // 初始化 Security.addProvider(new BouncyCastleProvider()); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 byte[] resultByte = cipher.doFinal(dataByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, "UTF-8"); return JSONObject.parseObject(result); } } catch (Exception e) { e.printStackTrace(); } return null; } } |
首先我们需要创建WXBizDataCrypt
的实体,传入小程序的appid
与我们获取的session_key
,然后再调用decryptData
方法传入encryptedData
与iv
即可进行解密,如果返回的值为NULL或抛出异常则为解密失败,解密成功之后可以获取返回对象的countryCode
以及purePhoneNumber
组成完整的含区号的手机号码。
后记
在微信开放的相关开放接口中,对于用户的隐私数据这一块处理都是需要效验解密的,当然这一点也是为了数据安全,不过不得不吐槽有时候官方的文档真的是写的让人摸不着头脑,比如微信支付中的timestamp
与timeStamp
2019年07月03日 上午11:35 11楼
前台小程序给我 sessionKey encryptedData iv 为什么不能解析一直报null
2019年07月08日 下午4:07 1层
@梵高先生 什么错误呢
2019年05月24日 下午10:11 12楼
把全部代码附在里面多好呀!
2019年06月26日 上午9:48 1层
@小小太阳 哈哈哈 因为有部分是业务代码 所以不方便贴出来
2019年05月07日 下午11:15 13楼
这个号码数据小程序运营的人能看到吗?如果能看到那我得换一个手机号码绑定微信了。
2019年05月08日 上午8:17 1层
@奶爸de笔记 只要你授权就可以看得到
2019年04月11日 下午11:10 14楼
文章不错非常喜欢,支持
2019年04月07日 下午11:00 15楼
文章不错非常喜欢
2019年03月30日 下午3:31 16楼
写的很好,很喜欢
2019年04月01日 上午9:07 1层
@文娱帝国 thanks