🥳🥳Welcome Huihui's Code World ! !🥳🥳 接下来看看由辉辉所写的关于小程序的相关操作吧 目录 🥳🥳Welc
🥳🥳Welcome Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于小程序的相关操作吧
目录
🥳🥳Welcome Huihui's Code World ! !🥳🥳
我们在使用微信中的小程序时,都会要我们进行授权,例如下面这样
那么这样的用户授权时怎么实现的呢,这一篇主要就是讲解用户授权登录的流程!!!
图片说明:
客户端调用 wx.login() 获取 临时登录凭证code,通过 wx.request() 发起网络请求,将 code 传给服务端
2、服务端使用 code + appid + appsecret 向微信换取 (调用 auth.code2Session 接口)用户唯一标识openid 和 会话密钥session_key
3、服务端自定义 登录状态token(与openid、session_key关联)返回客户端
4、客户端将 登录状态token 存入 缓存storage(推荐使用 wx.setStorageSync(‘key’, ‘value’) 同步存储)
5、客户端wx.request() 发起请求时,携带登录状态token (推荐使用 wx.getStorageSync(‘key’) 同步获取)
6、服务端通过 登录状态token 查询到对应 openid 和 session_key
7、验证成功后,返回业务数据给客户端
其中有两种方法,第一种方法是点击登录之后便直接获取了用户的个人信息,而第二种会询问用户是否同意授权,这样的话,会更具安全性
1.wx.login
这个方法主要用于获取用户的登录凭证(code)。在用户进入小程序时,前端会调用wx.login来获取这个code,然后将这个code发送给后台服务器。后台服务器再向微信发送请求,通过这个code来获取用户的唯一标识(openid)以及本次登录的会话密钥(session_key)。之后,后台服务器将这两个信息传回前台,用于自定义登录状态和用户唯一标识
2.wx.getUserProfile
这个方法主要用于获取用户的更多详细信息,如昵称、头像等。在使用这个方法之前,需要先调用wx.authorize接口来发起授权请求,请求用户授权提供这些信息。如果用户同意授权,就可以通过调用wx.getUserProfile方法来获取这些详细信息
3.代码
WXML
昵称:{{userInfo.nickName}} js
// pages/index/index.jsPage({ data: { userInfo: {}, canIUseGetUserProfile: false, }, onLoad() { // if (wx.getUserProfile) { // this.setData({ // canIUseGetUserProfile: true // }) // } }, getUserProfile(e) { console.log('getUserProfile') // 推荐使用 wx.getUserProfile 获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认 // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗 wx.getUserProfile({ desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 success: (res) => { console.log(res); this.setData({ userInfo: res.userInfo, hasUserInfo: true }) } }) }, wxLogin: function(e) { debugger console.log('wxLogin') console.log(e.detail.userInfo); this.setData({ userInfo: e.detail.userInfo }) if (e.detail.userInfo == undefined) { app.globalData.hasLogin = false; util.showErrorToast('微信登录失败'); return; } }, onReady() { }, onShow() { }, onHide() { }, onUnload() { }, onPullDownRefresh() { }, onReachBottom() { }, onShareAppMessage() { }})
用户授权登录后,后台便会保存用户的信息
前期准备
①准备数据接口
②密钥以及appid
后端代码
package com.zking.SSM.wxcontroller;import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;import com.alibaba.fastJSON.JSONObject;import com.zking.ssm.annotation.LoginUser;import com.zking.ssm.model.UserInfo;import com.zking.ssm.model.WxLoginInfo;import com.zking.ssm.model.WxUser;import com.zking.ssm.service.UserToken;import com.zking.ssm.service.UserTokenManager;import com.zking.ssm.service.WxUserService;import com.zking.ssm.util.JacksonUtil;import com.zking.ssm.util.ResponseUtil;import com.zking.ssm.util.UserTypeEnum;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.StringUtils;import org.springframework.WEB.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import cn.binarywang.wx.miniapp.api.WxMaService;import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;import javax.servlet.Http.httpservletRequest;import java.text.DateFORMat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;@Slf4j@RestController@RequestMapping("/wx/auth")public class WxAuthController { @Autowired private WxMaService wxService; @Autowired private WxUserService userService; @PostMapping("login_by_weixin") public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) { //客户端需携带code与userInfo信息 String code = wxLoginInfo.getCode(); UserInfo userInfo = wxLoginInfo.getUserInfo(); if (code == null || userInfo == null) { return ResponseUtil.badArgument(); } //调用微信sdk获取openId及sessionKey String sessionKey = null; String openId = null; try { long beginTime = System.currentTimeMillis(); // WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);// Thread.sleep(6000); long endTime = System.currentTimeMillis(); log.info("响应时间:{}",(endTime-beginTime)); sessionKey = result.getSessionKey();//session id openId = result.getOpenid();//用户唯一标识 OpenID } catch (Exception e) { e.printStackTrace(); } if (sessionKey == null || openId == null) { log.error("微信登录,调用官方接口失败:{}", code); return ResponseUtil.fail(); }else{ log.info("openId={},sessionKey={}",openId,sessionKey); } //根据openId查询wx_user表 //如果不存在,初始化wx_user,并保存到数据库中 //如果存在,更新最后登录时间 WxUser user = userService.queryByOid(openId); if (user == null) { user = new WxUser(); user.setUsername(openId); user.setPassword(openId); user.setWeixinOpenid(openId); user.setAvatar(userInfo.getAvatarUrl()); user.setNickname(userInfo.getNickName()); user.setGender(userInfo.getGender()); user.setUserLevel((byte) 0); user.setStatus((byte) 0); user.setLastLoginTime(new Date()); user.setLastLoginIp(IpUtil.client(request)); user.setShareUserId(1); userService.add(user); } else { user.setLastLoginTime(new Date()); user.setLastLoginIp(IpUtil.client(request)); if (userService.updateById(user) == 0) { log.error("修改失败:{}", user); return ResponseUtil.updatedDataFailed(); } } // token UserToken userToken = null; try { userToken = UserTokenManager.generateToken(user.getId()); } catch (Exception e) { log.error("微信登录失败,生成token失败:{}", user.getId()); e.printStackTrace(); return ResponseUtil.fail(); } userToken.setSessionKey(sessionKey); log.info("SessionKey={}",UserTokenManager.getSessionKey(user.getId())); Map
WXML
JS
// pages/auth/login/login.jsvar util = require('../../../utils/util.js');var user = require('../../../utils/user.js');const app = getApp();Page({ data: { canIUseGetUserProfile: false, // 用于向前兼容 lock:false }, onLoad: function(options) { // 页面初始化 options为页面跳转所带来的参数 // 页面渲染完成 if (wx.getUserProfile) { this.setData({ canIUseGetUserProfile: true }) } //console.log('login.onLoad.canIUseGetUserProfile='+this.data.canIUseGetUserProfile) }, onReady() { }, onShow() { }, getUserProfile(e) { console.log('getUserProfile'); // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认 // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗 wx.getUserProfile({ desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写 success: (res) => { //console.log(res); user.checkLogin().catch(() => { user.loginByWeixin(res.userInfo).then(res => { app.globalData.hasLogin = true; wx.navigateBack({ delta: 1 }) }).catch((err) => { app.globalData.hasLogin = false; if(err.errMsg=="request:fail timeout"){ util.showErrorToast('微信登录超时'); }else{ util.showErrorToast('微信登录失败'); } this.setData({ lock:false }) }); }); }, fail: (res) => { app.globalData.hasLogin = false; console.log(res); util.showErrorToast('微信登录失败'); } }); }, wxLogin: function(e) { console.log('wxLogin'); if (e.detail.userInfo == undefined) { app.globalData.hasLogin = false; util.showErrorToast('微信登录失败'); return; } user.checkLogin().catch(() => { user.loginByWeixin(e.detail.userInfo).then(res => { app.globalData.hasLogin = true; wx.navigateBack({ delta: 1 }) }).catch((err) => { app.globalData.hasLogin = false; if(err.errMsg=="request:fail timeout"){ util.showErrorToast('微信登录超时'); }else{ util.showErrorToast('微信登录失败'); } }); }); }, accountLogin() { console.log('开发中....') }})
utils/user.js【封装的代码块】
const util = require('../utils/util.js');const api = require('../config/api.js');function checkSession() { return new Promise(function(resolve, reject) { wx.checkSession({ success: function() { resolve(true); }, fail: function() { reject(false); } }) });}function login() { return new Promise(function(resolve, reject) { wx.login({ success: function(res) { if (res.code) { resolve(res); } else { reject(res); } }, fail: function(err) { reject(err); } }); });}function loginByWeixin(userInfo) { return new Promise(function(resolve, reject) { return login().then((res) => { //登录远程服务器 util.request(api.AuthLoginByWeixin, { code: res.code, userInfo: userInfo }, 'POST').then(res => { if (res.errno === 0) { //存储用户信息 wx.setStorageSync('userInfo', res.data.userInfo); wx.setStorageSync('token', res.data.token); resolve(res); } else { reject(res); } }).catch((err) => { reject(err); }); }).catch((err) => { reject(err); }) });}function checkLogin() { return new Promise(function(resolve, reject) { if (wx.getStorageSync('userInfo') && wx.getStorageSync('token')) { checkSession().then(() => { resolve(true); }).catch(() => { reject(false); }); } else { reject(false); } });}module.exports = { loginByWeixin, checkLogin,};
手机号授权登录的流程与用户信息授权登录流程是一样的,只不过向微信调用的接口有所不同
后端代码
package com.zking.ssm.wxcontroller;import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;import com.alibaba.fastjson.JSONObject;import com.zking.ssm.annotation.LoginUser;import com.zking.ssm.model.UserInfo;import com.zking.ssm.model.WxLoginInfo;import com.zking.ssm.model.WxUser;import com.zking.ssm.service.UserToken;import com.zking.ssm.service.UserTokenManager;import com.zking.ssm.service.WxUserService;import com.zking.ssm.util.JacksonUtil;import com.zking.ssm.util.ResponseUtil;import com.zking.ssm.util.UserTypeEnum;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import cn.binarywang.wx.miniapp.api.WxMaService;import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;import javax.servlet.http.HttpServletRequest;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;@Slf4j@RestController@RequestMapping("/wx/auth")public class WxAuthController { @PostMapping("bindPhone") public Object bindPhone(@LoginUser Integer userId, @RequestBody String body) { log.info("【请求开始】绑定手机号码,请求参数,body:{}", body); String sessionKey = UserTokenManager.getSessionKey(userId); String encryptedData = JacksonUtil.parseString(body, "encryptedData"); String iv = JacksonUtil.parseString(body, "iv"); WxMaPhoneNumberInfo phoneNumberInfo = null; try { phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv); } catch (Exception e) { log.error("绑定手机号码失败,获取微信绑定的手机号码出错:{}", body); e.printStackTrace(); return ResponseUtil.fail(); } String phone = phoneNumberInfo.getPhoneNumber(); WxUser user = userService.selectByPrimaryKey(userId); user.setMobile(phone); if (userService.updateById(user) == 0) { log.error("绑定手机号码,更新用户信息出错,id:{}", user.getId()); return ResponseUtil.updatedDataFailed(); } Map
data = new HashMap (); data.put("phone", phone); log.info("【请求结束】绑定手机号码,响应结果:{}", JSONObject.toJSONString(data)); return ResponseUtil.ok(data); } }} WXML
JS
var util = require('../../../utils/util.js');var api = require('../../../config/api.js');var user = require('../../../utils/user.js');var app = getApp();Page({ data: { userInfo: {}, hasLogin: false, userSharedUrl: '' }, onLoad: function (options) { }, onShow: function () { let that = this; //获取用户的登录信息 let userInfo = wx.getStorageSync('userInfo'); this.setData({ userInfo: userInfo, hasLogin: true }); }, getPhoneNumber: function (e) { console.log(e); let that = this; if (e.detail.errMsg !== "getPhoneNumber:ok") { // 拒绝授权 return; } if (!this.data.hasLogin) { wx.showToast({ title: '绑定失败:请先登录', icon: 'none', duration: 2000 }); return; } util.request(api.AuthBindPhone, { iv: e.detail.iv, encryptedData: e.detail.encryptedData }, 'POST').then(function (res) { if (res.errno === 0) { let userInfo = wx.getStorageSync('userInfo'); userInfo.phone = res.data.phone;//设置手机号码 wx.setStorageSync('userInfo', userInfo); that.setData({ userInfo: userInfo, hasLogin: true }); wx.showToast({ title: '绑定手机号码成功', icon: 'success', duration: 2000 }); } }); }, exitLogin: function () { wx.showModal({ title: '', confirmColor: '#b4282d', content: '退出登录?', success: function (res) { if (!res.confirm) { return; } util.request(api.AuthLoGout, {}, 'POST'); app.globalData.hasLogin = false; wx.removeStorageSync('token'); wx.removeStorageSync('userInfo'); wx.reLaunch({ url: '/pages/index/index' }); } }) }})
1.效果预览
2.代码演示
vote/list.wxml
你好,我是模态框 {{item.name}} vote/list.wxss
.vote-button { display: flex; flex-direction: row; flex-wrap: wrap; }.myvotes { padding-top: 50px; padding-left: 5px; height: 430rpx; width: 360rpx; display: flex; flex-direction: column;}.myimg{ display: flex; justify-content: center;}.myview{}.vote-icon { margin: 5px; width: 320rpx; height: 300rpx; border-radius:25px; border: 10px solid rgb(247, 198, 66);}.img-title{ width: 32px; height: 32px;}.vote-label { font-weight: 800; font-family: YouYuan; width: 350rpx; padding-left: 65px; }.info-title{ display: flex; align-items: center; margin-left:65px ; width: 300px; border-radius:25px; border: 2px solid rgb(247, 198, 66);}.vote-add { margin-left: 340px; margin-top: 35px; width: 120rpx; height: 120rpx;}.hidden { display: none;}.title-view { background-color: beige; font-weight: 700; padding-left: 7px;}.info-title { padding: 5px 5px 10px 5px; border-top: 1px solid rgb(129, 129, 127);}.info-text { height: 100px; padding: 5px 5px 10px 5px; border-top: 1px solid rgb(129, 129, 127);}.image { padding-left: 55px; display: flex; align-items: center;}.time { border-top: 1px solid rgb(129, 129, 127); padding: 5px 0px 5px 0px; display: flex; align-items: center;}.image-container { padding-left: 60px;}.info-sousuo { margin-left: 85px; padding-left: 20px; border-radius: 25px; border: 4px solid rgb(214, 214, 98); width: 250px;}.section{ color: #aaa; display: flex; justify-content: center;}.list-info { margin-top: 10px; color: #aaa;}.list-num { color: #e40909; font-weight: 700;}.join { padding: 0px 0px 0px 10px; color: #aaa;}.state { margin: 0px 6px 0px 6px; border: 1px solid #93b9ff; color: #93b9ff;}.list-tag { padding: 3px 0px 10px 0px; display: flex; align-items: center;}.list-title { display: flex; justify-content: space-between; color: #333; font-weight: 900;}.yyy{ display: flex; align-items: center;}.list-img{ height: 300rpx; width: 90%; border-radius: 50rpx; margin: 5px 5px 5px 20px;}.centered { display: flex; justify-content: center; }.video-img { width: 100px; height: 100px;}.list { border-bottom: 1px solid #6b6e74; padding: 10px;}.mobi-text { font-weight: 700; padding: 15px;}.mobi-icon { border-left: 5px solid #e40909;}.mobi-title { background-color: rgba(158, 158, 142, 0.678); margin: 10px 0px 10px 0px;}.swiper-item { height: 300rpx; width: 100%; border-radius: 10rpx;}.userinfo { display: flex; flex-direction: column; align-items: center; color: #aaa;}.userinfo-avatar { overflow: hidden; width: 128rpx; height: 128rpx; margin: 20rpx; border-radius: 50%;}.usermotto { margin-top: 200px;}.filx{ display: flex; align-items: center;}.container { padding: 20px;}.modal-container { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #fff; width: 80%; max-height: 80%; overflow-y: auto; padding: 20px;}.mask { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5);}button { display: block; margin-top: 10px;}.content { margin-top: 10px; border: 1px solid #ccc; padding: 10px;}
vote/list.js
// pages/vote/list/list.jsPage({ addvote: function () { console.log(111) wx.navigateTo ({ url: '/pages/vote/addvote/addvote' // 跳转到目标页面的路径 }) }, data: { myvotelist:[ {index:1, name:'投票统计',img:'../../../static/vote/totaldata-active.png'}, {index:3, name:'历史投票',img:'../../../static/vote/voterecords-active.png'}, {index:2, name:'赞成人数',img:'../../../static/vote/yes-active.png'}, {index:3, name:'反对人数',img:'../../../static/vote/no-active.png'}, ], modalVisible: false, // 模态框是否可见 }, // 点击事件,显示模态框 showModal(e) { this.setData({ modalVisible: true }); }, onLoad(options) { }, onReady() { }, onShow() { }, onHide() { }, onUnload() { }, onPullDownRefresh() { }, onReachBottom() { }, onShareAppMessage() { }})
vote/addvote.wxml
vote/addvote.wxss
.container { padding: 20rpx;}button { margin-top: 60px; background-color: rgb(247, 198, 66); color: #fff; padding: 10rpx 20rpx; border-radius: 4rpx; text-align: center;} .title { font-size: 30rpx; font-weight: bold; margin-bottom: 10rpx;}
vote/addvote.js
Page({ many: function () { console.log(111) wx.navigateTo ({ url: '/pages/vote/many/many' // 跳转到目标页面的路径 }) }, data: { radioOptions: ['选项1', '选项2', '选项3'], checkboxOptions: ['选项A', '选项B', '选项C'], voteTitle: '', voteDescription: '', selectedRadioIndex: -1, selectedCheckboxIndexes: [] }, onTitleInput(e) { this.setData({ voteTitle: e.detail.value }); }, onDescriptionInput(e) { this.setData({ voteDescription: e.detail.value }); }, onRadiochange(e) { this.setData({ selectedRadioIndex: e.detail.value }); }, onCheckboxChange(e) { this.setData({ selectedCheckboxIndexes: e.detail.value }); }, submitVote() { // 获取投票的标题、描述以及选择的选项 const { voteTitle, voteDescription, selectedRadioIndex, selectedCheckboxIndexes } = this.data; // TODO: 处理提交投票逻辑,可以发送请求给服务器等 // 打印投票结果 console.log('投票标题:', voteTitle); console.log('投票描述:', voteDescription); console.log('单选投票选项:', selectedRadioIndex); console.log('多选投票选项:', selectedCheckboxIndexes); }, data: { }, onLoad(options) { }, onReady() { }, onShow() { }, onHide() { }, onUnload() { }, onPullDownRefresh() { }, onReachBottom() { }, onShareAppMessage() { }})
vote/many.wxml
{title}}" disabled /> --> 添加选项 vote/many.wxss
.container { display: flex; flex-direction: column; align-items: center;} .title{ height: 200px; font-weight: bolder; font-size: 70rpx; margin-left: 20px; margin-top: -160px; margin-bottom: -50px;}.line { width: 100%; height: 1px; background-color: #ccc;}.info{height: 70px;width:380px;}.select{ display: flex;flex-direction: row;align-self: start;}.select-add {margin-left: 15px; margin-top: 15px; width: 50rpx; height: 50rpx;}.select-content{ margin-top: 10px; margin-left: 7px; display: flex; align-items: center;}.vote-content { width: 200rpx; height: 30rpx; margin-top: 17px; margin-left: 7px; display: flex; align-items: center;}.scroll-container { height: 500rpx; }.submit-button {margin-top: 20px; width: 200rpx; height: 60rpx; background-color: rgb(241, 189, 46);}
vote/many.js
const app = getApp()const api = require("../../../config/api.js")const util = require("../../../utils/util")Page({ data: { inputList: [], voteTitle: '' }, // 显示输入框 showInput: function () { const length = this.data.inputList.length; const newInputList = [...this.data.inputList]; newInputList.push({ value: '' }); this.setData({ inputList: newInputList }); }, // 输入框内容改变 inputChange: function (event) { const index = event.currentTarget.dataset.index; const value = event.detail.value; const newInputList = [...this.data.inputList]; newInputList[index].value = value; this.setData({ inputList: newInputList }); }, // 删除输入框 hideInput: function (event) { const index = event.currentTarget.dataset.index; const newInputList = [...this.data.inputList]; newInputList.splice(index, 1); this.setData({ inputList: newInputList }); }, // 投票标题改变 titleChange: function (event) { const value = event.detail.value; this.setData({ voteTitle: value }); }, // 提交投票 submitVote: function () { // 获取投票标题和选项内容 const title = this.data.voteTitle; const options = this.data.inputList.map(item => item.value); // 打印标题和选项 console.log('投票标题:', title); console.log('投票选项:', options); let data = { title: title, options: options, }; util.request(api.VoteADD, data, 'POST').then(res => { console.log(res) // 清空投票标题和选项内容 this.setData({ voteTitle: '', inputList: [] }); }) }, onLoad(options) { }, onReady() { }, onShow() { }, onHide() { }, onUnload() { }, onPullDownRefresh() { }, onReachBottom() { }, onShareAppMessage() { }})
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊
来源地址:https://blog.csdn.net/m0_74315688/article/details/133963086
--结束END--
本文标题: 【微信小程序开发】小程序微信用户授权登录(用户信息&手机号)
本文链接: https://www.lsjlt.com/news/458468.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0