目录
1、登录流程时序
1.1、wx.login(Object object)
1.1.1、功能描述
1.1.2、参数
1.1.3、object.success 回调函数
1.2、auth.code2Session
1.2.1、请求地址
1.2.2、请求参数
1.2.3、返回值
2、使用微信登录
2.1、小程序端js文件
2.2、云函数端js文件
3、获取手机号码
3.1、小程序端代码
3.2、云函数端js文件
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。详情查看:微信官方文档-小程序登录
1、登录流程时序
说明
- 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
- 调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 、 用户在微信开放平台帐号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台帐号) 和 会话密钥 session_key。
之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
注意事项
- 会话密钥
session_key
是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。 - 临时登录凭证 code 只能使用一次
1.1、wx.login(Object object)
1.1.1、功能描述
调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台帐号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台帐号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成
1.1.2、参数
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
timeout | number | 否 | 超时时间,单位ms | |
success | function | 否 | 接口调用成功的回调函数 | |
fail | function | 否 | 接口调用失败的回调函数 | |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
1.1.3、object.success 回调函数
属性 | 类型 | 说明 |
---|---|---|
code | string | 用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 auth.code2Session,使用 code 换取 openid、unionid、session_key 等信息 |
1.2、auth.code2Session
注意:这个作用于服务端,不要在客户端调用
登录凭证校验。通过 wx.login 接口获得临时登录凭证 code 后传到开发者服务器调用此接口完成登录流程
1.2.1、请求地址
GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
1.2.2、请求参数
属性 | 类型 | 默认值 | 必填 | 说明 |
---|---|---|---|---|
appid | string | 是 | 小程序 appId | |
secret | string | 是 | 小程序 appSecret | |
js_code | string | 是 | 登录时获取的 code | |
grant_type | string | 是 | 授权类型,此处只需填写 authorization_code |
1.2.3、返回值
属性 | 类型 | 说明 |
---|---|---|
openid | string | 用户唯一标识 |
session_key | string | 会话密钥 |
unionid | string | 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回,详见 UnionID 机制说明。 |
errcode | number | 错误码 |
errmsg | string | 错误信息 |
errcode 的合法值
值 | 说明 |
---|---|
-1 | 系统繁忙,此时请开发者稍候再试 |
0 | 请求成功 |
40029 | code 无效 |
45011 | 频率限制,每个用户每分钟100次 |
40226 | 高风险等级用户,小程序登录拦截 。风险等级详见用户安全解方案 |
我真的是晕倒了,如果你使用的是云开发自带的数据库来存储的话,其实你是不需要获取openid的行为的,但是我一开始不知道呀,弄着弄着发现其实这个是有的,所以就分了两个了,一个是获取微信头像、昵称和openid的,一个是使用自带的获取手机号码的
2、使用微信登录
工作步骤:
- wx.getUserProfile弹窗框体显示用户的头像和昵称
- 确定后wx.login获取code
- 发送命令到服务器获取openid以及账户信息
2.1、小程序端js文件
async getUserProfile(e) {wx.getUserProfile({desc: '用于获取用户个人信息',success: function (detail) {wx.login({success: res => {var code = res.code; //登录凭证wx.cloud.callFunction({name: "getCurrentUserInfo",data: {encryptedData: detail.encryptedData,iv: detail.iv,code: code,userInfo: detail.rawData}}).then(res => {console.log("res: ",res);var openid = res.result.openid;var status = res.result.status;var phone = res.result.phone;console.log("openid: ",openid);console.log("status: ",status);console.log("phone: ",phone);console.log("nickName: ",detail.userInfo.nickName);if(phone==undefined){console.log("需要绑定手机号");}else{console.log("授权成功");}}).catch(res => {console.log("res3: ",res);})}});},fail: function () {wx.showModal({content: '取消授权将会影响相关服务,您确定取消授权吗?',success (res) {if (res.confirm) {wx.showToast({title: '已取消授权',duration: 1500})} else if (res.cancel) {this.getUserProfile()}}})}})}
2.2、云函数端js文件
cloud.init({env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
// 云函数入口函数
let user_id;
let user_uid;
exports.main = async (event, context) => {const wxContext = cloud.getWXContext()let code = event.code;//获取小程序传来的codelet encryptedData = event.encryptedData;//获取小程序传来的encryptedDatalet iv = event.iv;//获取小程序传来的ivlet userInfo = JSON.parse(event.userInfo) //获取个人信息let appid = "xxxxxxxxx";//自己小程序后台管理的appid,可登录小程序后台查看let secret = "xxxxxxxxx";//小程序后台管理的secret,可登录小程序后台查看let grant_type = "authorization_code";// 授权(必填)默认值let url = "https://api.weixin.qq.com/sns/jscode2session?grant_type="+grant_type+"&appid="+appid+"&secret="+secret+"&js_code="+code;const stat = await new Promise((resolve, reject) => {request(url, (err, response, body) => {if (!err && response.statusCode == 200) {let _data = JSON.parse(body)let UserCount = 0;user_id = _data.openiduser_uid = _data.unioniddb.collection('Account').where({user_id: _data.openid // 填入当前用户 openid}).count().then(res => {UserCount = res.total;if(UserCount == 0){/* 插入当前列表 */db.collection('Account').add({data: {user_id: _data.openid,nickName: userInfo.nickName,avatarUrl: userInfo.avatarUrl,gender: userInfo.gender,phone: ''}}).then(res => {resolve("Insert success!");}).catch(res => {reject("Insert fail!");})}else if(UserCount == 1){/* 更新当前列表 */db.collection('Account').where({user_id: _data.openid // 填入当前用户 openid}).update({data: {nickName: userInfo.nickName,avatarUrl: userInfo.avatarUrl,gender: userInfo.gender}}).then(res => {resolve("Update success!");}).catch(res => {reject("Update fail!");})}else if(UserCount > 1){/* 删除所有此id的并且重新添加 */db.collection('Account').where({user_id: _data.openid // 填入当前用户 openid}).remove().then(res => {db.collection('Account').add({data: {user_id: _data.openid,nickName: userInfo.nickName,avatarUrl: userInfo.avatarUrl,gender: userInfo.gender,phone: ''}})resolve("Remove and insert success!");}).catch(res => {reject("Remove fail!");})}})}})})const CurrentPhoneObject = await db.collection('Account').where({user_id: user_id // 填入当前用户 openid}).get()const CurrentPhone = CurrentPhoneObject.data[0].phoneconsole.log("CurrentPhone: ",CurrentPhone);console.log("stat: ",stat);console.log("user_id: ",user_id);console.log("user_uid: ",user_uid);return {status: stat,CurrentPhone: CurrentPhone,openid: user_id,unionid: user_uid}
}
3、获取手机号码
因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。另外,新版本接口不再需要提前调用wx.login
进行登录。
<button type="primary" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
3.1、小程序端代码
async getPhoneNumber(res) {console.log(res)const errMsg = res.detail.errMsgif (errMsg != "getPhoneNumber:ok"){wx.showToast({title: '授权失败',icon: 'error'})return}const cloudId = res.detail.cloudIDconst cloudIdList = [cloudId]wx.showLoading({title: '获取中',mask: true})const cloudFunRes = await wx.cloud.callFunction({name: "getPhoneNumber",data: {cloudIdList}})console.log("cloudFunRes: ",cloudFunRes)const jsonStr = cloudFunRes.result.dataList[0].jsonconst jsonData = JSON.parse(jsonStr)const phoneNumber = jsonData.data.phoneNumberconsole.log(phoneNumber)this.setData({userPhone: phoneNumber})wx.hideLoading({success: (res) => {},})},
3.2、云函数端js文件
const cloud = require('wx-server-sdk')cloud.init({env: cloud.DYNAMIC_CURRENT_ENV
})// 云函数入口函数
exports.main = async (event) => {const wxContext = cloud.getWXContext()const openid = wxContext.OPENIDconst appid = wxContext.APPIDconst unionid = wxContext.UNIONIDconst enc = wxContext.ENVconst cloudIdList = event.cloudIdListtry {const result = await cloud.openapi.cloudbase.getOpenData({openid: openid,cloudidList: cloudIdList})const jsonStr = result.dataList[0].jsonconst jsonData = JSON.parse(jsonStr)const phoneNumber = jsonData.data.phoneNumberconsole.log("phoneNumber: ",phoneNumber)return result} catch (err) {return err}
}
主要代码来自博主:https://blog.csdn.net/yancy_peng/article/details/121308428