小程序中获取用户手机号

在使用小程序的时候,经常会遇到获取手机号的提示框,不给手机号就不让访问,比如下面这个:

这种情况还经常发生在饭店点餐的时候,原先纸质的菜单直接被一个二维码取代,用户扫码后首先就要获取你的手机号你才能点餐。 不得不说小程序获取用户手机号是非常的便捷,今天这篇文章就来学习下小程序获取手机号的流程。

说明:小程序获取手机号功能不是谁都可以用的,必须是非个人账号,而且还要认证过的哦

功能拆分

大事化小,我们先把整个流程拆分下:

  1. wx.login()用户认证,获取session_key用于后面数据解密
  2. 点击获取用户手机号,弹出微信授权界面
  3. 点击允许按钮,获取到加密的用户信息
  4. 通过session_key解密上面的加密信息,最终得到用户的手机号

流程图大致如下:

457

下面就按上面的步骤一步一步来开发,下面所用的代码是UniAPP[1]代码,后端接口为PHP代码。

用户认证

小程序文档[2]中开头就指明需要wx.login()这一步,所以这一步绝对不能跳过:

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
onload(){  
uni.checkSession({
success() {
// 认证有效
},
// 之前的认证失效
fail() {
uni.login({
success(res) {
console.log(res)
// 微信登录成功 已拿到code
if (res.code) {
uni.request({
url: `https://abc.com/getSessionKey?code=${res.code}`,
method: 'GET',
success (resp) {
// 换取成功后 可以讲下面的数据存入storage
this.openid = resp.data.openid //openid 用户唯一标识
this.unionid = resp.data.unionid //unionid 开放平台唯一标识
this.session_key = resp.data.session_key //session_key 会话密钥
uni.setStorageSync('openid', resp.data.openid)
uni.setStorageSync('unionid', resp.data.unionid)
uni.setStorageSync('session_key', resp.data.session_key)
}
})
}
}
})
}
});
}

调用login前,先可以checkSession一下,如果过期了再更新session_key,减少网络请求。

PHP接口相对简单很多:

1
2
3
4
5
6
7
8
9
10
$appid = 'xxxx';
$secret = 'xxxx';

$js_code = $_GET['code'];

// 接口地址
$url = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$secret}&js_code={$js_code}&grant_type=authorization_code";

// 发送curl请求获取数据
// ...

有两个注意点:

  1. 如果请求 jscode2session 接口失败,你需要的再小程序后台【request合法域名】中添加接口域名
  2. unionid并不是每个账号都会返回,必须要绑定同一个开放平台后[3]才会有

触发点击按钮事件

创建一个按钮:

1
<button type="default" open-type="getPhoneNumber" @getphonenumber="getPhoneNumberCallback">手机号</button>

创建对应的回掉函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
methods: {
getPhoneNumberCallback (r) {
if(e.detail.errMsg=="getPhoneNumber:fail user deny"){//用户决绝授权
} else {
//允许授权
console.log(r.detail.encryptedData)
r.detail.encryptedData //加密的用户信息
r.detail.iv //加密算法的初始向量 时要用到
uni.request({
url: 'https://abc.com/decode',
data: {
session_key: uni.getStorageSync('session_key'),
encryptedData: r.detail.encryptedData,
iv: r.detail.iv
},
success (resp) {
// todo
}
})
}
},
}

回掉函数中可以拿到加密过后的用户数据:

11110

接下来就是解密数据了。

数据解密

看很多文章说直接在小程序端解密数据,方法是可行的,而且不用写后端接口,但是小程序可以被反编译,造成appidsecret的泄漏,安全性很低,所以我建议还是后端解密。

详细的解密步骤可以参看官方文档[4],这里只贴一张官方的图:

签名校验以及数据加解密涉及用户的会话密钥 session_key。 开发者应该事先通过wx.login 登录流程获取会话密钥 session_key 并保存在服务器。为了数据不被篡改,开发者不应该把 session_key 传到小程序客户端等服务器外的环境。

解密数据步骤如下:

  1. 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
  2. 对称解密的目标密文为 Base64_Decode(encryptedData)。
  3. 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
  4. 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。

微信官方提供了多种编程语言的示例代码[5],我们直接下载后使用,这里以PHP为例:

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
<?php

include_once "wxBizDataCrypt.php";


$appid = 'wx4f4bc4dec97d474b';
$sessionKey = 'tiihtNczf5v6AKRyjwEUhQ==';

$encryptedData="CiyLU1Aw2KjvrjMdj8YKliAjtP4gsMZM
QmRzooG2xrDcvSnxIMXFufNstNGTyaGS
9uT5geRa0W4oTOb1WT7fJlAC+oNPdbB+
3hVbJSRgv+4lGOETKUQz6OYStslQ142d
NCuabNPGBzlooOmB231qMM85d2/fV6Ch
evvXvQP8Hkue1poOFtnEtpyxVLW1zAo6
/1Xx1COxFvrc2d7UL/lmHInNlxuacJXw
u0fjpXfz/YqYzBIBzD6WUfTIF9GRHpOn
/Hz7saL8xz+W//FRAUid1OksQaQx4CMs
8LOddcQhULW4ucetDf96JcR3g0gfRK4P
C7E/r7Z6xNrXd2UIeorGj5Ef7b1pJAYB
6Y5anaHqZ9J6nKEBvB4DnNLIVWSgARns
/8wR2SiRS7MNACwTyrGvt9ts8p12PKFd
lqYTopNHR1Vf7XjfhQlVsAJdNiKdYmYV
oKlaRv85IfVunYzO0IKXsyl7JCUjCpoG
20f0a04COwfneQAGGwd5oa+T8yO5hzuy
Db/XcxxmK01EpqOyuxINew==";

$iv = 'r7BXXKkLb8qrSNn05n0qiA==';

$pc = new WXBizDataCrypt($appid, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data );

if ($errCode == 0) {
// 解密成功,返回数据
print($data . "\n");
} else {
print($errCode . "\n");
}

最后,通过一顿操作后成功拿到数据交给前端处理。


参考:

  1. UniApp:https://uniapp.dcloud.io

  2. 小程序文档:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

  3. UnionId机制:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/union-id.html

  4. 小程序开放数据解密:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html

  5. 小程序解密示例代码:https://res.wx.qq.com/wxdoc/dist/assets/media/aes-sample.eae1f364.zip