微信小程序获取用户手机号总结

微信小程序获取用户手机号总结(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>

③底部导航栏“我的”

在该页设置登录按钮,这也是大多数小程序采用的方法。
B站登录页
点击授权按钮并且同意之后会获得一大串的加密密文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.bouncycastlebcprov-jdk161.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
结果如下:
在这里插入图片描述

在这里插入图片描述


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

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部