微信小程序中针对微信基础库新旧不同版本获取用户手机号的方法

简介: 微信小程序中针对微信基础库新旧不同版本获取用户手机号的方法

1.下面是微信官方关于获取手机号的文档链接

获取手机号 | 微信开放文档微信开发者平台文档

2.微信基础库版本2.21.2以上时,即新版本库无需提前调用wx.login();旧版本必须先调用wx.login();

我的业务场景是为了微信授权一键登录,我这里做个新旧版本的兼容处理。

3.官方的代码示例,不能直接 CV 使用,下面粘上我个人亲测可用的示例代码

3.1先来一个触发按钮

<button type="primary" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号码</button>

3.2如果微信基础库版本是旧版本( 2.21.2 以下)时,需要先调用wx.login()获取session_key 参数,之后调用getPhoneNumber 函数,此函数直接返回加密字符串,需要页面解密即可得到用户手机号。

此处附上解密工具js文件

WXBizDataCrypt.js文件内容如下:

    var crypto = require('crypto')
     
    function WXBizDataCrypt(appId, sessionKey) {
      this.appId = appId
      this.sessionKey = sessionKey
    }
     
    WXBizDataCrypt.prototype.decryptData = function (encryptedData, iv) {
      // base64 decode
      var sessionKey = new Buffer(this.sessionKey, 'base64')
      encryptedData = new Buffer(encryptedData, 'base64')
      iv = new Buffer(iv, 'base64')
     
      try {
         // 解密
        var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv)
        // 设置自动 padding 为 true,删除填充补位
        decipher.setAutoPadding(true)
        var decoded = decipher.update(encryptedData, 'binary', 'utf8')
        decoded += decipher.final('utf8')
        
        decoded = JSON.parse(decoded)
     
      } catch (err) {
        throw new Error('Illegal Buffer')
      }
     
      if (decoded.watermark.appid !== this.appId) {
        throw new Error('Illegal Buffer')
      }
     
      return decoded
    }
     
    module.exports = WXBizDataCrypt

使用页面需要引入一下,路劲写成自己的,我的是放到根目录下的common文件夹下:

import WXBizDataCrypt from "@/common/WXBizDataCrypt.js";

3.3按钮绑定的函数 getPhoneNumber

    //微信的login方法
    wxAuthLogin(){
              wx.login({
                success:(res) => {
                  if (res.code) {
                    //发起网络请求
                    //此处请求自己的后台服务,并将输入参数 res.code 传给后台以获取输出参数wxopenid和session_key的值
                  } else {
                      console.log("微信登录失败:"+res.errMsg);
                  }
                },
                fail(res){
                    console.log(res.errMsg);
                }
              });
          },
    //获取手机号
    getPhoneNumber (e) {
              if(e.detail.errMsg == 'getPhoneNumber:fail user deny'){//拒绝获取手机号
                   console.log("授权失败,用户已拒绝!");
                   //拒绝后可以根据自己的实际场景添加业务逻辑
              }else{//同意获取手机号
                  //此处Common.isExist 是我自定义的判断是否为空的函数,您可以修改为自己的判断非空的方法
                  if(Common.isExist(e.detail.code)){//如果存在code值,则当前环境为新版本
                     //此处根据入参 e.detail.code 请求后台接口,即可得到用户的手机号
                      
                  }else{//微信基础库版本为旧版本
                      //解密方法,第一个参数为小程序的appid,第二个为调用wx.login()并请求后台之后返回的session_key
                      var pc = new WXBizDataCrypt("wx69e6361f588acbe5", this.sessionKey);
                      var data = pc.decryptData(e.detail.encryptedData , e.detail.iv);
                      console.log("解密后的手机号:"+data.purePhoneNumber);
                  }
              }
          }

4.平台差异说明,真机预览如下,会提示你的小程序名称申请,微信开发者工具中预览效果有所不一样,只要能调用成功即可。

bcdce4540dbc485695d750102128d93e.jpg

5.后台服务接口

5.1 wx.login()请求的后台接口,代码示例如下,此处传入前端wx.login()获取到的code

    private static final String appid = "wx****************";
    private static final String secret = "7b****************e98bb6";
     
    public static ReturnData getOpenIdAndSessionKey(String code) {
            if(StringUtil.isEmpty(code)){
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取openid失败,参数code为空!");
            }
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&grant_type=authorization_code";
            url += "&js_code="+code;
            try {
                CloseableHttpResponse response = HttpClients.createDefault().execute(new HttpGet(url));
                String ret = EntityUtils.toString(response.getEntity());
                JSONObject jsonObject = JSON.parseObject(ret);
                if(StringUtil.isNotEmpty(jsonObject.getString("openid"))){
                    return new ReturnData(ReturnCode.SUCCESS.getCode(), ret, ReturnCode.SUCCESS.getMessage());
                }
                if("0".equals(jsonObject.getString("errcode"))){
                    return new ReturnData(ReturnCode.SUCCESS.getCode(), ret, ReturnCode.SUCCESS.getMessage());
                }
                logger.error("微信小程序获取openid错误:{}", jsonObject.getString("errmsg"));
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取openid错误");
                
            } catch (ClientProtocolException e) {
                logger.error("微信小程序获取openid异常,ClientProtocolException:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取openid异常:ClientProtocolException");
            } catch(IOException e){
                logger.error("微信小程序获取openid异常,IOException:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取openid异常:IOException");
            } catch(Exception e){
                logger.error("微信小程序获取openid异常,Exception:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取openid异常:Exception");
            }
        }
        public static String getValueByKey(String ret,String key) {
            JSONObject jsonObject = JSON.parseObject(ret);
            return jsonObject.getString(key);
        }

5.2新版本获取手机号的后台接口代码示例:

    public static ReturnData getAccessToken() {
            String url = "https://api.weixin.qq.com/cgi-bin/token?appid="+appid+"&secret="+secret+"&grant_type=client_credential";
            try {
                CloseableHttpResponse response = HttpClients.createDefault().execute(new HttpGet(url));
                String ret = EntityUtils.toString(response.getEntity());
                JSONObject jsonObject = JSON.parseObject(ret);
                if(StringUtil.isNotEmpty(jsonObject.getString("access_token"))) {
                    return new ReturnData(ReturnCode.SUCCESS.getCode(), jsonObject.getString("access_token"), ReturnCode.SUCCESS.getMessage());
                }
                if("0".equals(jsonObject.getString("errcode"))){
                    return new ReturnData(ReturnCode.SUCCESS.getCode(), jsonObject.getString("access_token"), ReturnCode.SUCCESS.getMessage());
                }
                logger.error("微信小程序获取access_token错误:{}", jsonObject.getString("errmsg"));
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取access_token错误");
            } catch (ClientProtocolException e) {
                logger.error("微信小程序获取access_token异常,ClientProtocolException:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取access_token异常:ClientProtocolException");
            } catch(IOException e){
                logger.error("微信小程序获取access_token异常,IOException:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取access_token异常:IOException");
            } catch(Exception e){
                logger.error("微信小程序获取access_token异常,Exception:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取access_token异常:Exception");
            }
        }
        
        public static ReturnData getPhone(String code) {
            if(StringUtil.isEmpty(code)){
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取手机号失败,参数code为空!");
            }
            ReturnData returnData = getAccessToken();
            if(!ReturnCode.SUCCESS.getCode().equals(returnData.getCode())){
                return returnData;
            }
            String access_token = returnData.getResult();
            String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+access_token;
            try {
                JSONObject param=new JSONObject();
                param.put("code", code);
                String ret = HttpClientUtil.sendHttpPost2(url, param.toJSONString());
                JSONObject jsonObject = JSON.parseObject(ret);
                if("0".equals(jsonObject.getString("errcode"))){
                    jsonObject = jsonObject.getJSONObject("phone_info");
                    return new ReturnData(ReturnCode.SUCCESS.getCode(), jsonObject.getString("purePhoneNumber"), ReturnCode.SUCCESS.getMessage());
                }
                logger.error("微信小程序获取手机号错误:{}", jsonObject.getString("errmsg"));
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取手机号错误");
            } catch (ClientProtocolException e) {
                logger.error("微信小程序获取手机号异常,ClientProtocolException:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取手机号异常:ClientProtocolException");
            } catch(IOException e){
                logger.error("微信小程序获取手机号异常,IOException:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取手机号异常:IOException");
            } catch(Exception e){
                logger.error("微信小程序获取手机号异常,Exception:{}", e);
                return new ReturnData(ReturnCode.FAIL.getCode(), "微信小程序获取手机号异常:Exception");
            }
        }

上面获取手机号的方法内用到一个HttpClientUtil.sendHttpPost2 方法的代码如下:

        /**
         * 向指定 URL 发送POST方法的请求(参数不带名称)
         */
        public static String sendHttpPost2(String url, String param) throws IOException {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                conn.setConnectTimeout(10000);
                conn.setReadTimeout(300000);
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
                // out = new PrintWriter(conn.getOutputStream());
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            }
            // 使用finally块来关闭输出流、输入流
            finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return result;
        }

6.到此一个完整的微信小程序获取用户手机号的完整实战案例就结束了,如有错误还请各位大佬能指正。欢迎评论区留言咨询或者讨论。


题外话:欢迎大家微信搜索#民谣嗑学家 ,关注我的个人公众号,我是一名爱代码,爱民谣,爱生活的业余吉他爱好者的Java 程序员,致力于向全栈发展的全能程序员。有想跟作者交朋友的可以关注我公众号,获取我的联系方式,我们可以一起学习,一起进步,业余时间可以一起娱乐娱乐,哈哈^_^。

相关文章
|
21天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的校园水电费管理微信小程序的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的校园水电费管理微信小程序的详细设计和实现
41 0
|
2月前
|
存储 小程序 JavaScript
【微信小程序】-- 自定义组件 -- 数据、方法和属性(三十三)
【微信小程序】-- 自定义组件 -- 数据、方法和属性(三十三)
|
2月前
|
移动开发 小程序 API
微信外部浏览器或短信链接唤起微信小程序的解决方案
微信外部浏览器或短信链接唤起微信小程序的解决方案
167 1
|
3月前
|
小程序
微信小程序中识别HTML标签的方法
微信小程序中识别HTML标签的方法
|
2月前
|
小程序 前端开发 程序员
微信小程序开发入门教程-小程序账号注册及开通
微信小程序开发入门教程-小程序账号注册及开通
|
11天前
|
移动开发 小程序 安全
使用阿里云短信+微信短链接跳转微信小程序
此内容是关于使用阿里云短信带传递参数的微信短链接跳转到微信小程序。首先,需要准备微信开发者工具和一个已认证的小程序。接着,开通云开发并配置云开发权限。然后,配置H5静态网页,包括设置云开发权限和处理不同设备的跳转方式。最后,上传云函数并修改其权限,获取微信短信链接,配置短链接参数,并开通阿里云短信服务以进行测试验证。整个过程涉及到了微信开发者工具、云开发、H5页面配置、云函数的创建和部署以及阿里云短信服务的开通和使用等步骤。
37 0
|
21天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的微信课堂助手小程序的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的微信课堂助手小程序的详细设计和实现
55 3
|
21天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的微信阅读网站小程序的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的微信阅读网站小程序的详细设计和实现
43 2
|
21天前
|
小程序 JavaScript Java
基于SpringBoot+Vue+uniapp微信小程序的校园防疫微信小程序的详细设计和实现
基于SpringBoot+Vue+uniapp微信小程序的校园防疫微信小程序的详细设计和实现
28 0
|
1月前
|
小程序 数据库
【微信小程序7】云开发中实时聊天系统的实现方法
【微信小程序7】云开发中实时聊天系统的实现方法
23 0

热门文章

最新文章