文章目录

  • 一、前言
  • 二、前端代码wxml
  • 三、前端代码js
  • 四、后端java
  • 五、程序流程
  • 六、参考

一、前言

微信小程序开发笔记——导读

  • 大部分微信小程序开发者都会有这样的需求:获取小程序用户的手机号码
  • 但是,因为小程序用户的手机号码属于重要信息,为了安全,所以需要如下一系列较为复杂的方法和步骤。
  • 我前期主要通过小程序云的方法获取用户手机号码,后面因为微信政策变更,小程序云不再提供免费版本,最低每月也要收费19元
  • 所以,我才转用方法二和方法三。否则方法一小程序云的方法是最简单的。

微信小程序开发笔记 进阶篇④——getPhoneNumber 获取用户手机号码(小程序云)
微信小程序开发笔记 进阶篇⑤——getPhoneNumber 获取用户手机号码(基础库 2.21.2 之前)
微信小程序开发笔记 进阶篇⑥——getPhoneNumber 获取用户手机号码(基础库 2.21.2 之后)

  • 首先确保基础库版本在2.21.2之前

二、前端代码wxml

  • 必须要有这个button,并且用户点击了,才能有下一步
<button type="default" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" class="weui-vcode-btn" wx:else>获取手机号</button>

三、前端代码js

  • 定义一个code全局变量
var code = ""
  • 该界面onShow的时候,调用wx.login函数获取code
  • 这边这里有个风险,这个code存在有效期,到你用的时候可能会过期

onShow() {        wx.login({success: function (res) {console.log("wx.login success", res)if (res.code) {    code = res.code} else {_this.showToast('失败!' + res.errMsg)}},fail: function (res) {console.log('wx.login fail' + res)}})
},
  • bindgetphonenumber="getPhoneNumber"按钮的回调函数
getPhoneNumber(e) {var _this = thisconsole.log("getPhoneNumber", e)keyueliSdk.getPhoneNumber({code: code,encryptedData: e.detail.encryptedData,iv: e.detail.iv,appId: app.globalData.appId,},(res) => {console.log("getPhoneNumber", "success", res)_this.setData({mobile: res.data.data.phoneNumber})},(res) => {console.log("getPhoneNumber", "fail", res)})
},
  • keyueliSdk.js接口工具类
//获取用户手机号码
const getPhoneNumber = (data, success, fail) => {console.log("getPhoneNumber", data)request(endpoint + "/v1/app/user/getPhoneNumber", {// 'content-type': 'application/x-www-form-urlencoded''content-type': 'application/json'},data,"POST",success, fail)
}module.exports = {getPhoneNumber: getPhoneNumber,
}

四、后端java

  • controller.java
@ApiOperation("查询用户手机号码")
@PostMapping("/getPhoneNumber")
public AjaxResult getPhoneNumber(@ApiParam() @RequestBody AppCode appCode)
{log.info(appCode.toString());return AjaxResult.success(loginService.getPhoneNumber(appCode));
}
  • loginService.java
public JSONObject getPhoneNumber(AppCode appCode){if(!WXUtils.checkAppId(appCode.getAppId())){log.error("appId异常: "+ appCode.toString());throw new CustomException("AppId 异常");}JSONObject codeData = WXUtils.codeAnalysis(appCode.getCode(), appCode.getAppId());if(ObjectUtil.isNull(codeData)){log.error("code异常: "+ appCode.toString());throw new CustomException("code 异常");}String sessionKey = codeData.getString("session_key");String openId = codeData.getString("openid");String unionId = codeData.getString("unionid");JSONObject decryptObject = WXUtils.decrypt(appCode.getAppId(), appCode.getEncryptedData(), sessionKey, appCode.getIv());if(ObjectUtil.isNull(decryptObject)){log.error("encryptedData异常: "+ appCode.toString());throw new CustomException("encryptedData 异常");}log.info(decryptObject.toJSONString());return decryptObject;
}
  • WXUtils.java
/*** 解密数据* @return* @throws Exception*/
public static JSONObject decrypt(String appId, String encryptedData, String sessionKey, String iv){try {byte[] resultByte = AESUtils.decrypt(Base64.decodeBase64(encryptedData),Base64.decodeBase64(sessionKey),Base64.decodeBase64(iv));if(null != resultByte && resultByte.length > 0){String result = new String(WxPKCS7Encoder.decode(resultByte));JSONObject jsonObject = JSONObject.parseObject(result);String decryptAppId = jsonObject.getJSONObject("watermark").getString("appid");if(!appId.equals(decryptAppId)){return null;}return jsonObject;}} catch (Exception e) {e.printStackTrace();}return null;
}/*** 获取session_key* @return* @throws Exception*/
public static JSONObject codeAnalysis(String code, String appId) {try {String objectStr = HttpUtil.get(String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",appId, getAppSecret(appId), code));log.info(objectStr);JSONObject jsonObject = JSON.parseObject(objectStr);return jsonObject;}catch (Exception e){e.printStackTrace();log.error("微信code解析异常", e.getMessage());}return null;
}
  • AESUtils.java
/*** AES解密** @param content*            密文* @return* @throws InvalidAlgorithmParameterException* @throws NoSuchProviderException*/
public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {initialize();try {Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");Key sKeySpec = new SecretKeySpec(keyByte, "AES");cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化byte[] result = cipher.doFinal(content);return result;} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (NoSuchPaddingException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (IllegalBlockSizeException e) {e.printStackTrace();} catch (BadPaddingException e) {e.printStackTrace();} catch (NoSuchProviderException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;
}

五、程序流程

#mermaid-svg-U4UV6bJAN0p8Brq6 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 .error-icon{fill:#552222;}#mermaid-svg-U4UV6bJAN0p8Brq6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U4UV6bJAN0p8Brq6 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-U4UV6bJAN0p8Brq6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U4UV6bJAN0p8Brq6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U4UV6bJAN0p8Brq6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U4UV6bJAN0p8Brq6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U4UV6bJAN0p8Brq6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U4UV6bJAN0p8Brq6 .marker.cross{stroke:#333333;}#mermaid-svg-U4UV6bJAN0p8Brq6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U4UV6bJAN0p8Brq6 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-U4UV6bJAN0p8Brq6 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-U4UV6bJAN0p8Brq6 .actor-line{stroke:grey;}#mermaid-svg-U4UV6bJAN0p8Brq6 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 .sequenceNumber{fill:white;}#mermaid-svg-U4UV6bJAN0p8Brq6 #sequencenumber{fill:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 .messageText{fill:#333;stroke:#333;}#mermaid-svg-U4UV6bJAN0p8Brq6 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-U4UV6bJAN0p8Brq6 .labelText,#mermaid-svg-U4UV6bJAN0p8Brq6 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-U4UV6bJAN0p8Brq6 .loopText,#mermaid-svg-U4UV6bJAN0p8Brq6 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-U4UV6bJAN0p8Brq6 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-U4UV6bJAN0p8Brq6 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-U4UV6bJAN0p8Brq6 .noteText,#mermaid-svg-U4UV6bJAN0p8Brq6 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-U4UV6bJAN0p8Brq6 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-U4UV6bJAN0p8Brq6 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-U4UV6bJAN0p8Brq6 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-U4UV6bJAN0p8Brq6 .actorPopupMenu{position:absolute;}#mermaid-svg-U4UV6bJAN0p8Brq6 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-U4UV6bJAN0p8Brq6 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-U4UV6bJAN0p8Brq6 .actor-man circle,#mermaid-svg-U4UV6bJAN0p8Brq6 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-U4UV6bJAN0p8Brq6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 注册界面 后端服务器 onShow函数,wx.login获取用户code 按钮点击,getPhoneNumber获取encryptedData和iv https post请求,code/encryptedData/iv/appId等4个参数 拿code和appId通过auth.code2Session获取session_key 密文:Base64_Decode(encryptedData) 秘钥:Base64_Decode(session_key) 初始向量:Base64_Decode(iv) AES-128-CBC 解密,返回phoneNumber 注册界面 后端服务器

六、参考

  • auth.code2Session
  • 开放数据校验与解密
  • 高端帖:手机号解密失败?扫盲帖+解决方案

觉得好,就一键三连呗(点赞+收藏+关注)

微信小程序开发笔记 进阶篇⑤——getPhoneNumber 获取用户手机号码(基础库 2.21.2 之前)相关推荐

  1. 微信小程序开发笔记 进阶篇④——getPhoneNumber 获取用户手机号码(小程序云)

    文章目录 一.前言 二.前端代码wxml 三.前端代码js 四.云函数 五.程序流程 一.前言 微信小程序开发笔记--导读 大部分微信小程序开发者都会有这样的需求:获取小程序用户的手机号码. 但是,因 ...

  2. 微信小程序开发笔记 进阶篇⑥——getPhoneNumber 获取用户手机号码(基础库 2.21.2 之后)

    文章目录 一.前言 二.前端代码wxml 三.前端代码js 四.后端java 五.程序流程 六.参考 一.前言 微信小程序开发笔记--导读 大部分微信小程序开发者都会有这样的需求:获取小程序用户的手机 ...

  3. 微信小程序开发笔记 进阶篇③——onfire.js事件订阅和发布在微信小程序中的使用

    文章目录 一.前言 二.onfire.js介绍 三.API介绍 四.实例应用 五.onfire源码 六.实例源码 一.前言 微信小程序开发笔记--导读 二.onfire.js介绍 一个简单实用的事件订 ...

  4. 微信小程序开发笔记 进阶篇④——基于iconfont快速实现icon图标显示

    文章目录 一.iconfont素材网 二.iconfont项目设置 三.微信小程序项目配置 四.全部源码 一.iconfont素材网 进入iconfont素材网 挑选想要的素材,加入购物车 点击右上角 ...

  5. 微信小程序开发笔记 进阶篇②——多个微信小程序一个用户体系,同一个UnionID

    目录 微信开放平台绑定小程序 微信小程序login和getUserInfo 后台请求auth.code2Session 后台解密开放数据 微信开放平台绑定小程序 微信官方文档:UnionID 机制说明 ...

  6. 微信小程序开发笔记 支付篇②——微信小程序通过小程序云实现微信支付功能

    文章目录 一.前言 二.开通微信支付 2.1 关联商户号 2.2 添加商户号 2.3 管理员授权 三.云函数开发 3.1 新建云函数 3.2 云函数代码 3.3 云函数上传并部署 四.小程序调用 4. ...

  7. 微信小程序开发笔记 支付篇④——基于微信支付SDK实现Java后端接口使用

    文章目录 一.前文 二.微信支付 Java SDK 三.示例 一.前文 微信小程序开发笔记--导读 微信支付-SDK与DEMO下载 先看README.md 二.微信支付 Java SDK 对微信支付开 ...

  8. 微信小程序开发笔记 支付篇③——微信支付JSAPI下单和微信小程序调起支付(V2版本)

    文章目录 一.前文 二.流程图 三.SpringBoot接口实现 2.1 微信调起支付所需数据 2.2 下单接口 2.3 支付回调接口 三.微信小程序实现 3.1 JSAP统一下单 3.2 小程序调起 ...

  9. 微信小程序开发笔记(1.1)滚动选择器picker的使用

    微信小程序开发笔记(1.1)滚动选择器picker的使用 前言 滚动选择器picker 普通选择器 多列选择器 时间选择器 日期选择器 省市区选择器 前言 最近被拉来做小程序,因为时间比较赶,其他方面 ...

最新文章

  1. 李国杰院士等:未来移动通信系统中的通信与计算融合
  2. java代码块执行顺序_Java笔记 | Java代码块执行顺序测试
  3. 利用grep命令查找文件内容
  4. Apache 安全配置方法
  5. [高光谱] Hyperspectral-Classification Pytorch 数据集的读取、划分、加载
  6. 在内容也中寻找母板页中的控件
  7. 黑客攻击行为特征分析 反攻击技术综合性分析报告
  8. 【技术贴】自己制作支持QQ空间背景音乐的链接教程||QQ免费空间音乐外链自己上传制作教程...
  9. 强化学习基本概念及方法分类
  10. 主机MTU值和Docker MTU值不一致导致Harbor无法推送问题
  11. Java:反射的常用用法,
  12. 大神李沐被曝离职,投身大模型创业!网友:希望不要耽误他解读论文
  13. 马士兵mca课程java学习笔记
  14. 数学之美!~(02)十位伟大的数学家!
  15. adobe pdf 合并文件后提示“无法提取嵌入的字体”问题解决方法
  16. 射频功放OIP3,IIP3,IM3,IMD3几个指标的具体计算
  17. 开始自学SAP以及学习路线
  18. 高校计算机课程期末考试试卷分析,《计算机应用基础》期末试卷分析.doc
  19. 【OpenCV】透视变换应用——实现鸟瞰图与贴图
  20. 解决跨域问题:Access to XMLHttpRequest at ‘file:///G:/ZKJW_workspac

热门文章

  1. 第十三届蓝桥杯大赛软件赛决赛(C/C++ 大学B组)
  2. PS初学者实例教程——图层样式的学习[斜面和浮雕]
  3. 纸质文档转成电子档,30秒即可快速搞定(亲测有效)!
  4. 计算机科学中宏一般指,在EXCEL中工具里面的宏是什么意思、有什么用途?
  5. 【分布式】分布式系统概述
  6. 英语中什么是开音节,什么是闭音节
  7. 中国二线城市有哪些比较知名的芯片设计企业
  8. 打印机服务器纸张属性不显示,为什么我的打印机能在打印机服务器属性里设置自定义纸张大小,却无法? 爱问知识人...
  9. edius7下载地址(需要注册会员的)
  10. 计算机启动应用程序的方法,怎么启动Windows应用程序