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

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

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 程序员,致力于向全栈发展的全能程序员。有想跟作者交朋友的可以关注我公众号,获取我的联系方式,我们可以一起学习,一起进步,业余时间可以一起娱乐娱乐,哈哈^_^。

相关文章
|
2月前
|
JSON 小程序 JavaScript
uni-app开发微信小程序的报错[渲染层错误]排查及解决
uni-app开发微信小程序的报错[渲染层错误]排查及解决
738 7
|
2月前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
770 1
|
2月前
|
存储 JSON 小程序
微信小程序入门之新建并认识小程序结构
微信小程序入门之新建并认识小程序结构
63 1
ly~
|
3月前
|
存储 供应链 小程序
除了微信小程序,PHP 还可以用于开发哪些类型的小程序?
除了微信小程序,PHP 还可用于开发多种类型的小程序,包括支付宝小程序、百度智能小程序、抖音小程序、企业内部小程序及行业特定小程序。在电商、生活服务、资讯、工具、娱乐、营销等领域,PHP 能有效管理商品信息、订单处理、支付接口、内容抓取、复杂计算、游戏数据、活动规则等多种业务。同时,在企业内部,PHP 可提升工作效率,实现审批流程、文件共享、生产计划等功能;在医疗和教育等行业,PHP 能管理患者信息、在线问诊、课程资源、成绩查询等重要数据。
ly~
89 6
|
4月前
|
小程序
|
2月前
|
缓存 小程序 索引
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
261 1
|
2月前
|
小程序 JavaScript API
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
这篇文章介绍了如何在uni-app和微信小程序中实现将图片保存到用户手机相册的功能。
1133 0
微信小程序开发之:保存图片到手机,使用uni-app 开发小程序;还有微信原生保存图片到手机
|
2月前
|
JavaScript 小程序 开发者
uni-app开发实战:利用Vue混入(mixin)实现微信小程序全局分享功能,一键发送给朋友、分享到朋友圈、复制链接
uni-app开发实战:利用Vue混入(mixin)实现微信小程序全局分享功能,一键发送给朋友、分享到朋友圈、复制链接
516 0
|
2月前
|
小程序
uni-app开发微信小程序使用onPullDownRefresh(下拉刷新)总结
uni-app开发微信小程序使用onPullDownRefresh(下拉刷新)总结
692 0
|
2月前
|
小程序 前端开发 数据可视化
微信商城小程序WeiMall
微信商城小程序WeiMall
39 0

热门文章

最新文章