美文网首页程序员微信小程序开发
微信小程序如何获取用户手机号 ?

微信小程序如何获取用户手机号 ?

作者: JeenWang | 来源:发表于2020-03-09 11:00 被阅读0次

    微信小程序如何获取用户手机号 ?

    本篇文章将教会你,使用微信小程序快速、有效获取用户手机号的方法。
    微信小程序获取手机号,仅企业小程序支持,个人小程序账号暂不支持。

    1、小程序端调用 wx.login() 方法,获取 code 后,将 code 通过后台 api 接口传递到后台。

      /**
       * 获取openid、userToken
       */
      getServerUserInfo: function (e) {
        let that = this
        wx.login({
          success: function (res) {
            if (res.code) {
              wx.request({
                url: app.serverUrl + 'api/login/getUserInfo',
                data: {
                  code: res.code
                },
                header: {
                  'content-type': 'application/json'
                },
                success: function (e) {
                  that.setData({
                    userToken: e.data.userToken,
                  })
                }
              })
            }
          }
        })
      },
    

    2、后台 api 接口收到 code 后,调用微信接口 jscode2session , 换取 openid 、 session_key 、 unionid

    这里有三个知识点必须十分清楚:

    1)unionid : 同一用户 ,在同一开发平台下,多个应用 unionid 相同 。 不同应用下 openid 是不同的 , 若需要打通多个应用的用户体系 , unionid 是唯一的做法。

    2) session_key : 为应用安全,session_key 不应该直接传递到小程序端 , 正确的做法是将 session_key 存储在服务器端 。

    session_key 存储方式这里以 redis 为例进行讲解,调用 jscode2session 接口返回的数据有 openid 和 session_key , openid 是唯一的 , 因此 redis 存储的 key 可以为 openid 的 MD5 加密字符串 , value 为 session_key , 有效期可设置为 10 min(你认为的合适的有效期) , openid 的加密字符串作为 userToken 返回给小程序 , 这样我们在使用的时候 , 就可以通过 userToken 来换取 session_key 。

    3)session_key 有效期:微信平台不会告诉我们 session_key 准确的有效期 , 会有过期的情况出现 , 如何验证 session_key 的有效性呢 ? 在小程序端可以使用 wx.checkSession() 方法来验证 session_key 有效性 ,若 session_key 失效 ,则需要重新执行 wx.login() 方法 , 也就是从第一步开始重新执行 。

    这里使用 Java 语言编写 , 代码如下 :

        /**
         * 获取用户信息
         * @param request
         * @return
         */
        @RequestMapping("/getUserInfo")
        @ResponseBody
        private WxLoginResult getUserInfo(HttpServletRequest request) {
            String code = request.getParameter("code");
            WxLoginResult wxLoginResult = null;
            String urlStr = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
            try {
                URL url = new URL(urlStr);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.connect();
                BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
                String line;
                StringBuilder sb = new StringBuilder();
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                br.close();
                connection.disconnect();
                System.out.println(sb.toString());
                String result = sb.toString();
                wxLoginResult = new Gson().fromJson(result, WxLoginResult.class);
                String userToken = Md5Util.encode(wxLoginResult.getOpenid());
                wxLoginResult.setUserToken(userToken);
                redisCacheUtil.setCacheObject(userToken, wxLoginResult.getSession_key());
            } catch (Exception e) {
                e.printStackTrace();
            }
            wxLoginResult.setSession_key("");
            return wxLoginResult;
        }
    

    3、小程序端提交 code 调用后台 api 接口后 , 获取 api 接口返回的 userToken ,通过页面 button 点击调用后台接口 , 传递参数 userToken 、 iv 、 encryptedData 到后台进行数据解密,得到 phoneNumber

    1)页面设置

    <button class="btn"  open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">{{phoneNumber==null?'获取手机号':phoneNumber}}</button>
    

    2) 获取手机号 button 点击后将获取到 encryptedData 和 iv ,即可调用后台 api 接口获取手机号

    getPhoneNumber: function (e) {
        var that = this;
        if (e.detail.errMsg == "getPhoneNumber:ok") {
          wx.request({
            url: app.serverUrl+'/api/login/decodePhone',
            data: {
              encryptedData: e.detail.encryptedData,
              iv: e.detail.iv,
              userToken: that.data.userToken,
            },
            header: {
              'content-type': 'application/json' 
            },
            success: function (res) {
              that.setData({
                phoneNumber:res.data.phoneNumber
              })
            }
          })
        }
      },
    

    3) 后台 api 接口接收参数 : encryptedData 、 iv 、 userToken 解密出手机号 phoneNumber ,这里解密算法为 Java 语言编写 , 代码如下 :

        /**
         * 解密用户信息
         */
        public static String getUserInfo(String encryptedData, String sessionKey, String iv) {
            byte[] dataByte = Base64.decode(encryptedData);
            byte[] keyByte = Base64.decode(sessionKey);
            byte[] ivByte = Base64.decode(iv);
            try {
                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 result = new String(resultByte, "UTF-8");
                    return result;
                }
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidParameterSpecException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            } catch (NoSuchProviderException e) {
                e.printStackTrace();
            }
            return null;
        }
    

    总结:

    1) 解密 encryptedData 数据十分重要 , 我第一次做 encryptedData 解密的时候花了不少时间。

    2) session_key 的正确处理方式是服务器保存 , 将可以获取 session_key 的钥匙传递给小程序端 , 防止出现安全问题 。

    3) 小程序端发起获取用户手机号操作,必须使用 button 并设置 open-type="getPhoneNumber" ,并从 button 的绑定事件中获取所需信息 。

    以上就是微信小程序获取用户手机号的详细过程 , 你学会了吗 ? 如果你有任何疑问 , 欢迎加我个人微信 study2100 , 我会为你做进一步解答 。

    相关文章

      网友评论

        本文标题:微信小程序如何获取用户手机号 ?

        本文链接:https://www.haomeiwen.com/subject/ssmlvctx.html