微信小程序获取用户手机号总结
微信小程序获取用户手机号总结(java 解密)
- 前言
- 1.授权获取密文
- ①.首页设为授权页
- ②在登录页获取授权
- ③底部导航栏“我的”
- 2.获取密钥
- 3.解密
前言
公司最近开发一个程序,需求是要通过用户手机号去数据库获得CUSTOMERID,根据CUSTOMERID来进行下面的一系列操作。现总结一下经验:
1.授权获取密文
根据微信小程序官方文档的说明,要获取手机号加密密文必须通过button组件的bindgetphonenumber事件回调。因此根据需求不同可以有三种方式授权:
①.首页设为授权页
用户第一次进入小程序先让用户授权,不然无法跳转其他页面,取得CUSTOMERID后存入本地用户下次登录小程序无需再次授权。

②在登录页获取授权
在登录页设置两个button组件,后台JS的data里面添加布尔变量isLogin,默认为false,后台获得CUSTOMERID后在成功回调函数里面把isLogin设为true,这样两个button组件在授权前后就只会出现一个。
<button wx:if="{{isLogin}}" class="next-step" bindtap="login">下一步button>
<button wx:else class="next-step" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">授权button>
③底部导航栏“我的”
在该页设置登录按钮,这也是大多数小程序采用的方法。

点击授权按钮并且同意之后会获得一大串的加密密文encryptedData和加密算法的初始向量iv如下:
2.获取密钥
利用小程序提供的API中的wx.login方法来获取临时登录凭证 code,然后通过访问微信提供的接口地址来获取密钥session_key。
https://api.weixin.qq.com/sns/jscode2sessionappid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

PS:APPID和SECRET的获取链接,登录之后可以查看。
在相应位置填入参数,发送GET请求,成功后会返回session_key。代码如下:
wx.login({success: function (res) {wx.request({url: 'https://api.weixin.qq.com/sns/jscode2session?appid=wx9*****ff540c64e&secret=3fd147f9e24******738bb84fae30be&js_code=' + res.code + '&grant_type=authorization_code',success: function (res) {wx.setStorageSync('key', res.data.session_key)}})}
})
PS :并不推荐这样写,官方文档也说了不要把session_key传到前端,应该在自己的服务器中请求API地址,完成解密后返回手机号信息即可。

3.解密
解密需要一个依赖类,Maven如下:
org.bouncycastle bcprov-jdk16 1.46
把目前获取到的密文,密钥,初始向量传入后台。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.security.Security;
import java.util.Arrays;
import static org.bouncycastle.util.encoders.Base64.decode;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;@RestController
@RequestMapping("/user")
public class UserController {private static final String KEY_ALGORITHM = "AES";private static final String ALGORITHM_STR = "AES/CBC/PKCS7Padding";private static Key key;private static Cipher cipher;@RequestMapping("getPhoneNumber")public String getPhoneNumber(String encryptedData,String key,String iv) {String data = decryptData(encryptedData, key, iv);JSONObject jsonObject = JSON.parseObject(data);String phoneNumber = jsonObject.get("phoneNumber").toString();return phoneNumber;}public static String decryptData(String encryptDataB64, String sessionKeyB64, String ivB64) {return new String(decryptOfDiyIV(decode(encryptDataB64),decode(sessionKeyB64),decode(ivB64)));}/*** 解密方法** @param encryptedData 要解密的字符串* @param keyBytes 解密密钥* @param ivs 自定义对称解密算法初始向量 iv* @return 解密后的字节数组*/private static byte[] decryptOfDiyIV(byte[] encryptedData, byte[] keyBytes, byte[] ivs) {byte[] encryptedText = null;init(keyBytes);try {cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs));encryptedText = cipher.doFinal(encryptedData);} catch (Exception e) {e.printStackTrace();}return encryptedText;}}private static void init(byte[] keyBytes) {// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要int base = 16;if (keyBytes.length % base != 0) {int groups = keyBytes.length / base + (keyBytes.length % base != 0 ? 1 : 0);byte[] temp = new byte[groups * base];Arrays.fill(temp, (byte) 0);System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);keyBytes = temp;}// 初始化Security.addProvider(new BouncyCastleProvider());// 转化成JAVA的密钥格式key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);try {// 初始化ciphercipher = Cipher.getInstance(ALGORITHM_STR, "BC");} catch (Exception e) {e.printStackTrace();}}
PS:代码参考作者@名字叫孙冉
注意:根据上面的方法获得的解密data数据是json格式字符串,需要再转为JSON对象才能取到里面的phoneNumer
结果如下:


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
