微信小程序uniapp+java 获取用户手机号

uniapp+java 获取用户手机号

首先你的appid不能是个体,具体可以参照微信官方文档

  • 实现思路很简单

    1. 前端使用button的开放属性获取当前登录code和偏移量(iv)加密数据(encryptedData)
    2. 将获取到的数据回传到后台进行解密即可
  • 前端html

  • <button class="wechatlogin" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber"   type="primary">微信登录</button>
    
    
  • //js
    /* 获取用户手机 */
    			async getPhoneNumber(e) {
    				if (this.code.length == 0) {
    					this.getCode();
    				}
    				const res = await this.httpRequest({ //这是我自己封装的请求方法
    					url: '/user/getPhoneNumber',  //后端解析电话号码地址
    					method: 'POST',
    					data: { //解密电话需要的数据
    						'iv': e.detail.iv,   
    						'encryptedData': e.detail.encryptedData,
    						'code': this.code
    					}
    				})
    				console.log(res.data);
    				if(res.data.success){
    					uni.showToast({
    						title:'登录成功',
    						icon:'success'
    					});
    					uni.setStorageSync('token',res.data.data.token) 
    					setTimeout(()=>{
    						uni.switchTab({
    							url:'../main/main'
    						})
    					},1000)
    				}else{
    					uni.showToast({
    						title:'微信登录失败。请切换到手动登录',
    						icon:'none'
    					});
    				}
    			}
    
  • 后端,我用的是java实现

    1. 为了方便,我自己创建了一个bean用来接收前端传回的数据
    2. 根据前端传回来的数据去微信那边获取session_key和oppenid,当然对我们解密电话号码来说只有session_key是有用的
    3. 然后就是解密了,下面直接贴代码
  • 后端代码

    • javabean
  • //首先创建了一个bean来接收前端传回的数据
    @Data
    public class WeixinGetPhone {
        private String iv;
        private String code;
        private String encryptedData;
    }
    
    
    • 工具类(用于发起get请求,获取session_key和oppenId)
  • public class WeiXinGetSessionKeyUtil {
    
        private static final String appid = "XXX";
        private static final String AppSecret = "XXX";
    
    
        public static String getSessionKey(String code) {
            StringBuilder result = new StringBuilder();
            String GEt_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + AppSecret + "&js_code=" + code + "&grant_type=authorization_code";
            BufferedReader bufferedReader = null;
            try {
                URL url = new URL(GEt_URL);
                /*打开url之间的链接*/
                URLConnection urlConnection = url.openConnection();
                /*设置通用的请求属性*/
                urlConnection.setRequestProperty("accept", "*/*");
                urlConnection.setRequestProperty("connection", "Keep-Alive");
                urlConnection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                /*建立实际的链接*/
                urlConnection.connect();
                /*获取响应头*/
                Map<String, List<String>> map = urlConnection.getHeaderFields();
                for (String key : map.keySet()) {
                    System.out.println(key + "======>" + map.get(key));
                }
                //定义bufferReader输入流;来读取url响应
                bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    result.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("发送get请求出现异常" + e);
            } finally {
                try {
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(result.toString()); 
            //解密只需要用session_key,所以我这里直接返回session_key
            //json解析工具用的是阿里的fastjson
            JSONObject jsonObject = JSON.parseObject(result.toString());
            return jsonObject.getString("session_key");
        }
    }
    
    
    • 根据上一步拿到的session_key来解密手机号

    •  /*获取用户手机号码*/
      //这里面解密的代码我也是网上找的,后来准备贴一下原文链接,但是我清除了浏览器缓存之后找不到了,在这里就衷心的感谢哪位不知名的大神
          public String getPhoneNumber(String sessionKey, WeixinGetPhone weixinGetPhone) {
              String result = "";
              byte[] dataByte = new byte[0];
              byte[] keyByte = new byte[0];
              byte[] ivByte = new byte[0];
              try {
                  //草泥马,傻逼**,记得替换特殊字符。。。。
                  //这个替换字符特别重要,不写就报错。
                  String replace = URLEncoder.encode(weixinGetPhone.getEncryptedData(), "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
                  //我这里不知道为什么必须这样使用base64其他小伙伴如果报错的话把前面的包名去掉试试
                  dataByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace);
                  String replace2 = URLEncoder.encode(sessionKey, "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
                  keyByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace2);
                  String replace1 = URLEncoder.encode(weixinGetPhone.getIv(), "UTF-8").replace("%3D", "=").replace("%2F", "/").replace("%2B", "+");
                  ivByte = org.apache.commons.codec.binary.Base64.decodeBase64(replace1);
              } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
              }
              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/PKCS7Padding", "BC");
                  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 s = resultByte.toString();
                      result = new String(resultByte, "UTF-8");
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              //result就是解密后的数据,我这里只需要电话号码,所以进行了数据处理
              System.out.println("result" + result);
              JSONObject jsonObject = JSONObject.parseObject(result);
              return jsonObject.getString("phoneNumber");
      
          }
      
  • controller里面的方法

  • 
        @PostMapping("/getPhoneNumber")
        @ApiOperation("用户授权后获取用户手机号")
    //返回类型R为自己定义的全局返回对象
        public R getPhoneNumber(@RequestBody WeixinGetPhone weixinGetPhone) {
            //WeiXinGetSessionKeyUtil,由于发起get请求并解析数据得到session_key的代码会有点多,所以我抽成了一个工具类,上面有贴这个工具类
            //获取解密手机号需要的sessionkey
          String sessionKey = WeiXinGetSessionKeyUtil.getSessionKey(weixinGetPhone.getCode());
            //根据session_key和偏移量(iv)解密前端传回的加密数据
            //解密方法我也抽成了一个单独方法,上面也贴了
            String phoneNumber = getPhoneNumber(sessionKey, weixinGetPhone);
            System.out.println("用户手机号:"+phoneNumber);
            ...
        }
    
  • 到此获取用户手机号也就算是收工了

  • 附使用到的jar包

  •  <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.10</version>
        </dependency>
          <dependency>
            <groupId>org.codehaus.xfire</groupId>
            <artifactId>xfire-core</artifactId>
            <version>1.2.6</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk16</artifactId>
            <version>1.46</version>
        </dependency>
            <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.18</version>
        </dependency>
            <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值