前言:
小程序+egg来实现获取用户手机号
思路分析:
小程序
获取用户信息,把用户的登录的code给后端来获得openid+session_key把获取的手机号信息给后端,后端接口解析后存库或者返回前端后端egg
实现拿到前端的code,然后走微信后端来获取openid+session_key 给前端返回去实现拿到前端参数手机号,然后解析存库或者返回前端具体操作:
前端-小程序:
1、app.js方法里面加入登录方法(或者你的登录点击按钮)
http.loginFun是封装的请求后台方法
// 登录 wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId let str = { js_code:res.code } http.loginFun(str).then((res)=>{ this.globalData.openid = res.openid this.globalData.session_key = res.session_key }).catch(err=>{ console.log(err); }) } })
app.js中globalData: { userInfo: null, openid: '', session_key: ''},
2、授权获取用户手机号,并将手机号发给后端(个人小程序无法成功调起手机授权弹框)
页面 index.wxml
<button open-type="getPhoneNumber" bindgetphonenumber="onPropPhone" > 授权手机号 </button>
这里是正常的手机号授权弹框,点击确定以后的返回数据
注意:
session_key是我们登录或者获取用户信息可以拿到的,但是iv+encryptedData 必须是点击手机号授权弹框以后才可以拿到,个人小程序这两个信息是拿不到的
let globalData = app.globalData let str = { session_key: globalData.session_key, iv:e.detail.iv, encryptedData:e.detail.encryptedData, // session_key:'', // iv:'w1Q7E***************Jw', // encryptedData:'RVHjAaCrJOFH2I****************', } http.loginPhone(str).then((res)=>{ console.log('获取用户手机号:'); console.log(res); }).catch(err=>{ console.log(err); })
后端-egg:
1、安装插件
npm i crypto --save
2、引入js配置文件,app/extend/ WXBizDataCrypt.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
3、新建微信接口方法 ,app/controller/wxApi/index.js
引入配置文件与微信小程序配置:
const WXBizDataCrypt = require('../../extend/WXBizDataCrypt');// 小程序的配置// 岩读const wxConfig = { appid: 'wx6a52********4e', secret: '91586*************5db9ccf43',}
方法1源码: this.ctx.curl 是可以获取外部地址 更多信息点我
async wxOpenid() { const { ctx } = this; const { js_code } = ctx.request.body; const { data } = await this.ctx.curl('https://api.weixin.qq.com/sns/jscode2session', { method: 'GET', rejectUnauthorized: false, data: { appid: wxConfig.appid, // 你的小程序的APPID secret: wxConfig.secret, // 你的小程序的secret, js_code, // wx.login 登录成功后的code }, dataType: 'json', }) this.ctx.body = data; }
方法2源码:注意一点,个人小程序是 没有权限拿到手机号的,解析返回肯定是失败
async wxCryptPhone() { const { ctx } = this; const { session_key, iv, encryptedData } = ctx.request.body; const pc = new WXBizDataCrypt(wxConfig.appid, session_key); // 获取到微信用户的手机号码 const { phoneNumber } = pc.decryptData(encryptedData, iv); // 如果获取失败 if (!phoneNumber) { this.ctx.body = { code: 500, message: '获取手机号码失败', mobile: '', params: { session_key, iv, encryptedData, }, } } else { // 如果获取成功 直接加入到数据库 返回手机号 和 token给微信端 this.ctx.body = { mobile: phoneNumber, code: 200, params: { session_key, iv, encryptedData, } } } }