• 微信小程序之微信授权登入及授权的流程讲解


    目录

    一.流程讲解

    1.1.图解:

     2.2.讲解

    二.官方登入

    wxLogin

    参数了解 :

    代码

    三.数据交互授权登入

    3.1.前端代码

    3.2.后端代码

            好啦今天就到这里了,希望能帮到你哦!!!


    一.流程讲解

    1.1.图解:

     2.2.讲解

    这张图片是关于微信小程序授权登录流程图。流程图展示了使用微信官方提供的登录能力来获取用户身份标识的过程。下面是对流程图中的一些关键步骤的解释:

    1. 小程序通过微信官方提供的登录能力获取微信提供的用户身份标识,以便在小程序内建立用户体系。

    2. 开发者需要在小程序中调用wx.login()方法来获取一个临时的code,该code是一个临时的字符串,再通过wx.request() 发起网络请求,将 code 传给后台服务端。

    3. 开发者服务器通过发送code及AppID(小程序ID)和AppSecret(小程序密钥)[ 后面发送的ID对于微信接口服务来说是唯一标识 ]调用微信接口服务(Wechat Http Api),以获取session_keyopenid等信息。session_key指的是当前的登录请求,是一次会话的标识。

    4. 开发者服务器将session_key和openid ( 微信接口转过来的openid对于3微信小程序来说是授权的唯一标识 ) 等用户信息与自定义登录态关联起来,返回自定义登录态给小程序。

    5. 小程序在后续的业务请求中,可以携带自定义登录态来向开发者服务器发起请求,以获取业务数据。

    6. 开发者服务器通过验证自定义登录态,返回相应的业务数据给小程序。


    微信小程序授权登录的流程包括小程序端调用wx.login()方法获取临时code,开发者服务器通过code+AppID+AppSecret获取session_key和openid等信息,并将其与自定义登录态关联起来,最后小程序可以使用自定义登录态来向开发者服务器发起业务请求。

    二.官方登入

    在官方文档中,有通过授权登入的方法及代码,我这里将其复制到项目中,进行一个演示。

    其中有两个方法,有分别不同的用户体验及安全问题。以下就给大家演示:

    • wxLogin

    调用接口获取登录凭证(code)。通过凭证进而换取用户登录态信息,包括用户在当前小程序的唯一标识(openid)、微信开放平台账号下的唯一标识(unionid,若当前小程序已绑定到微信开放平台账号)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。

    参数了解 :

    属性类型默认值必填说明最低版本
    timeoutnumber超时时间,单位ms1.9.90
    successfunction接口调用成功的回调函数
    failfunction接口调用失败的回调函数
    completefunction

    接口调用结束的回调函数(调用成功、失败都会执

    codestring用户登录凭证(有效期五分钟)。开发者需要在开发者服务器后台调用 code2Session,使用 code 换取 openid、unionid、session_key 等信息

    演示效果 : 

    • 代码

    index.wxml

    1. <!--pages/index/index.wxml-->
    2. <view>
    3. <button wx:if="{{canIUseGetUserProfile}}" type="primary" class="wx-login-btn" bindtap="getUserProfile">微信直接登录1</button>
    4. <button wx:else open-type="getUserInfo" type="primary" class="wx-login-btn" bindgetuserinfo="wxLogin">微信直接登录2</button>
    5. <image mode="scaleToFill" src="{{userInfo.avatarUrl}}" />
    6. <text>昵称:{{userInfo.nickName}}</text>
    7. </view>

    index.js

    1. // pages/index/index.js
    2. Page({
    3. data: {
    4. userInfo: {},
    5. canIUseGetUserProfile: true,
    6. },
    7. onLoad() {
    8. // if (wx.getUserProfile) {
    9. // this.setData({
    10. // canIUseGetUserProfile: true
    11. // })
    12. // }
    13. },
    14. getUserProfile(e) {
    15. console.log('getUserProfile')
    16. // 推荐使用 wx.getUserProfile 获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
    17. // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
    18. wx.getUserProfile({
    19. desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
    20. success: (res) => {
    21. console.log(res);
    22. this.setData({
    23. userInfo: res.userInfo,
    24. hasUserInfo: true
    25. })
    26. }
    27. })
    28. },
    29. wxLogin: function(e) {
    30. // debugger
    31. console.log('wxLogin')
    32. console.log(e.detail.userInfo);
    33. this.setData({
    34. userInfo: e.detail.userInfo
    35. })
    36. if (e.detail.userInfo == undefined) {
    37. app.globalData.hasLogin = false;
    38. util.showErrorToast('微信登录失败');
    39. return;
    40. }
    41. },
    42. /**
    43. * 生命周期函数--监听页面初次渲染完成
    44. */
    45. onReady() {
    46. },
    47. /**
    48. * 生命周期函数--监听页面显示
    49. */
    50. onShow() {
    51. },
    52. /**
    53. * 生命周期函数--监听页面隐藏
    54. */
    55. onHide() {
    56. },
    57. /**
    58. * 生命周期函数--监听页面卸载
    59. */
    60. onUnload() {
    61. },
    62. /**
    63. * 页面相关事件处理函数--监听用户下拉动作
    64. */
    65. onPullDownRefresh() {
    66. },
    67. /**
    68. * 页面上拉触底事件的处理函数
    69. */
    70. onReachBottom() {
    71. },
    72. /**
    73. * 用户点击右上角分享
    74. */
    75. onShareAppMessage() {
    76. }
    77. })

    js文件中 canIUseGetUserProfile 属性值为 : true时,就是wx.getUserProfile方法,当为false,就是wxLogin方法。

    三.数据交互授权登入

    以下代码是基于我的博客进行的续写 :微信小程序开发之后台数据交互及wxs应用

    3.1.前端代码

    在项目中编写 api.js 文件中的请求访问地址

    1. // 以下是业务服务器API地址
    2. // 本机开发API地址
    3. var WxApiRoot = 'http://localhost:8080/oapro/wx/';
    4. // 测试环境部署api地址
    5. // var WxApiRoot = 'http://192.168.191.1:8080/oapro/wx/';
    6. // 线上平台api地址
    7. //var WxApiRoot = 'https://www.oa-mini.com/demo/wx/';
    8. module.exports = {
    9. IndexUrl: WxApiRoot + 'home/index', //首页数据接口
    10. SwiperImgs: WxApiRoot+'swiperImgs',
    11. MettingInfos: WxApiRoot+'meeting/list',
    12. AuthLoginByWeixin: WxApiRoot + 'auth/login_by_weixin', //微信登录
    13. UserIndex: WxApiRoot + 'user/index', //个人页面用户相关信息
    14. AuthLogout: WxApiRoot + 'auth/logout', //账号登出
    15. AuthBindPhone: WxApiRoot + 'auth/bindPhone' //绑定微信手机号
    16. };

    注意 :   需要对应后台的请求地址之后进行数据的访问。

    个人中心

    在个人中心页面的 index.wxml 文件中进行编写:

    1. <view class="page-container">
    2. <view class="user-info-container">
    3. <view class="user-info" bindtap="goLogin">
    4. <image class="user-img" mode="scaleToFill" src="{{userInfo.avatarUrl}}" />
    5. <text class="user-info-name">{{userInfo.nickName}}</text>
    6. </view>
    7. <image class="user-update" src="/static/tabBar/component.png" bindtap='goPages' data-url='/pages/ucenter/user/user'/>
    8. </view>
    9. <view class="boundary" />
    10. <view class="cells-container">
    11. <view class="cell-wrap">
    12. <image class="cell-icon" src="/static/tabBar/sdk.png" />
    13. <text class="cell-text">我主持的会议</text>
    14. <view class="cell-right">
    15. <view class="cell-list-num">{{metting_pubs}}</view>
    16. <view class="cell-arrow"></view>
    17. </view>
    18. </view>
    19. <view class="cell-wrap">
    20. <image class="cell-icon" src="/static/tabBar/sdk.png" />
    21. <text class="cell-text">我参与的会议</text>
    22. <view class="cell-right">
    23. <view class="cell-list-num">{{metting_joins}}</view>
    24. <view class="cell-arrow"></view>
    25. </view>
    26. </view>
    27. </view>
    28. <view class="boundary" />
    29. <view class="cells-container">
    30. <view class="cell-wrap">
    31. <image class="cell-icon" src="/static/tabBar/sdk.png" />
    32. <text class="cell-text">我发布的投票</text>
    33. <view class="cell-right">
    34. <view class="cell-list-num">1</view>
    35. <view class="cell-arrow"></view>
    36. </view>
    37. </view>
    38. <view class="cell-wrap">
    39. <image class="cell-icon" src="/static/tabBar/sdk.png" />
    40. <text class="cell-text">我参与的投票</text>
    41. <view class="cell-right">
    42. <view class="cell-list-num">10</view>
    43. <view class="cell-arrow"></view>
    44. </view>
    45. </view>
    46. </view>
    47. <view class="boundary" />
    48. <view class="cells-container">
    49. <view class="cell-wrap">
    50. <image class="cell-icon" src="/static/tabBar/template.png" />
    51. <text class="cell-text">消息</text>
    52. <view class="cell-right">
    53. <view class="cell-list-num"></view>
    54. <view class="cell-arrow"></view>
    55. </view>
    56. </view>
    57. <view class="cell-wrap">
    58. <image class="cell-icon" src="/static/tabBar/component.png" />
    59. <text class="cell-text">设置</text>
    60. <view class="cell-right">
    61. <view class="cell-list-num"></view>
    62. <view class="cell-arrow"></view>
    63. </view>
    64. </view>
    65. </view>
    66. </view>

    在 index.js 中编写数据请求及方法

    1. // pages/ucenter/index/index.js
    2. var util = require('../../../utils/util.js');
    3. var api = require('../../../config/api.js');
    4. const app = getApp();
    5. Page({
    6. /**
    7. * 页面的初始数据
    8. */
    9. data: {
    10. userInfo: {
    11. nickName: '点击登录',
    12. avatarUrl: '/static/images/avatar.png'
    13. },
    14. hasLogin: false,
    15. metting_pubs: '',
    16. metting_joins: ''
    17. },
    18. /**
    19. * 生命周期函数--监听页面加载
    20. */
    21. onLoad(options) {
    22. },
    23. /**
    24. * 生命周期函数--监听页面显示
    25. */
    26. onShow() {
    27. this.getUserInfo();
    28. },
    29. getUserInfo() {
    30. // console.log('ucenter.index.app.globalData.hasLogin='+app.globalData.hasLogin)
    31. //获取用户的登录信息
    32. if (app.globalData.hasLogin) {
    33. let userInfo = wx.getStorageSync('userInfo');
    34. this.setData({
    35. userInfo: userInfo,
    36. hasLogin: true
    37. });
    38. //查询个人统计信息
    39. util.request(api.UserIndex).then(res => {
    40. if (res.errno === 0) {
    41. this.setData({
    42. metting_pubs: res.data.metting_pubs,
    43. metting_joins: res.data.metting_joins
    44. });
    45. }
    46. });
    47. }
    48. },
    49. goLogin() {
    50. if (!this.data.hasLogin) {
    51. wx.navigateTo({
    52. url: "/pages/auth/login/login"
    53. });
    54. }
    55. },
    56. /**
    57. * 页面跳转
    58. */
    59. goPages: function (e) {
    60. if (this.data.hasLogin) {
    61. wx.navigateTo({
    62. url: e.currentTarget.dataset.url
    63. });
    64. } else {
    65. wx.navigateTo({
    66. url: "/pages/auth/login/login"
    67. });
    68. };
    69. }
    70. })

    创建一个用户登入后的设置页面为 : user

    user.wxml

    1. <!--pages/ucenter/user/user.wxml-->
    2. <form bindsubmit="formSubmit">
    3. <view class='personal-data'>
    4. <view class='list'>
    5. <view class='item acea-row row-between-wrapper'>
    6. <view>头像</view>
    7. <view class='pictrue'>
    8. <image src='{{userInfo.avatarUrl}}'></image>
    9. </view>
    10. </view>
    11. <view class='item acea-row row-between-wrapper'>
    12. <view>名字</view>
    13. <view class='input'><input type='text' disabled='true' name='nickname' value='{{userInfo.nickName}}'></input></view>
    14. </view>
    15. <view class='item acea-row row-between-wrapper'>
    16. <view>手机号码</view>
    17. <button name='phone' class='phoneW' value='{{userInfo.phone}}' wx:if="{{!userInfo.phone}}" bindgetphonenumber="getPhoneNumber" hover-class='none' open-type='getPhoneNumber'>
    18. 点击获取
    19. </button>
    20. <view class='input acea-row row-between-wrapper' wx:else>
    21. <input type='text' disabled='true' name='phone' value='{{userInfo.phone}}' class='id'></input>
    22. <text class='iconfont icon-suozi'></text>
    23. </view>
    24. </view>
    25. <view class='item acea-row row-between-wrapper'>
    26. <view>ID号</view>
    27. <view class='input acea-row row-between-wrapper'>
    28. <input type='text' value='1000{{userInfo.userId}}' disabled='true' class='id'></input>
    29. <text class='iconfont icon-suozi'></text>
    30. </view>
    31. </view>
    32. </view>
    33. <button class='modifyBnt' bindtap="exitLogin">退 出</button>
    34. </view>
    35. </form>

    user.wxss

    1. @import '/static/font/iconfont.wxss';
    2. .personal-data .list {
    3. margin-top: 15rpx;
    4. background-color: #fff;
    5. }
    6. .personal-data .list .item {
    7. padding: 30rpx 30rpx 30rpx 0;
    8. border-bottom: 1rpx solid #f2f2f2;
    9. margin-left: 30rpx;
    10. font-size: 32rpx;
    11. color: #282828;
    12. }
    13. .personal-data .list .item .phone {
    14. background-color: #85c43f;
    15. width: 160rpx;
    16. height: 56rpx;
    17. font-size: 24rpx;
    18. color: #fff;
    19. line-height: 56rpx;
    20. border-radius: 32rpx
    21. }
    22. .personal-data .list .item .pictrue {
    23. width: 88rpx;
    24. height: 88rpx;
    25. }
    26. .personal-data .list .item .pictrue image {
    27. width: 100%;
    28. height: 100%;
    29. border-radius: 50%;
    30. }
    31. .personal-data .list .item .input {
    32. width: 415rpx;
    33. text-align: right;
    34. color: #868686;
    35. }
    36. .personal-data .list .item .input .id {
    37. width: 365rpx;
    38. }
    39. .personal-data .list .item .input .iconfont {
    40. font-size: 35rpx;
    41. }
    42. .personal-data .modifyBnt {
    43. /* background-color: #85c43f; */
    44. /* background: linear-gradient(to left right, #85c43f, #fefefd); */
    45. background: radial-gradient(circle at 50%,#85c43f,#CDDC39);
    46. font-size: 32rpx;
    47. color: #fff;
    48. width: 690rpx;
    49. height: 90rpx;
    50. border-radius: 50rpx;
    51. display: flex;
    52. justify-content: center;
    53. align-items: center;
    54. line-height: 90rpx;
    55. margin: 76rpx auto 0 auto;
    56. }
    57. .acea-row{display:flex;flex-wrap:wrap;}
    58. .acea-row.row-top{align-items:flex-start;}
    59. .acea-row.row-middle{align-items:center;}
    60. .acea-row.row-bottom{align-items:flex-end;}
    61. .acea-row.row-left{justify-content:flex-start;}
    62. .acea-row.row-center{justify-content:center;}
    63. .acea-row.row-right{justify-content:flex-end;}
    64. .acea-row.row-between{justify-content:space-between;}
    65. .acea-row.row-around{justify-content:space-around;}
    66. .acea-row.row-column{flex-direction:column;}
    67. .acea-row.row-column-between{flex-direction:column;justify-content:space-between;}
    68. .acea-row.row-column-around{flex-direction:column;justify-content:space-around;}
    69. .acea-row.row-center-wrapper{align-items:center;justify-content:center;}
    70. .acea-row.row-between-wrapper{align-items:center;justify-content:space-between;}
    71. view, image, text, navigator {
    72. box-sizing: border-box;
    73. padding: 0;
    74. margin: 0;
    75. }

    user.js

    1. var util = require('../../../utils/util.js');
    2. var api = require('../../../config/api.js');
    3. var user = require('../../../utils/user.js');
    4. var app = getApp();
    5. Page({
    6. /**
    7. * 页面的初始数据
    8. */
    9. data: {
    10. userInfo: {},
    11. hasLogin: false,
    12. userSharedUrl: ''
    13. },
    14. /**
    15. * 生命周期函数--监听页面加载
    16. */
    17. onLoad: function (options) {
    18. },
    19. onShow: function () {
    20. let that = this;
    21. //获取用户的登录信息
    22. let userInfo = wx.getStorageSync('userInfo');
    23. this.setData({
    24. userInfo: userInfo,
    25. hasLogin: true
    26. });
    27. },
    28. getPhoneNumber: function (e) {
    29. console.log(e);
    30. let that = this;
    31. if (e.detail.errMsg !== "getPhoneNumber:ok") {
    32. // 拒绝授权
    33. return;
    34. }
    35. if (!this.data.hasLogin) {
    36. wx.showToast({
    37. title: '绑定失败:请先登录',
    38. icon: 'none',
    39. duration: 2000
    40. });
    41. return;
    42. }
    43. util.request(api.AuthBindPhone, {
    44. iv: e.detail.iv,
    45. encryptedData: e.detail.encryptedData
    46. }, 'POST').then(function (res) {
    47. if (res.errno === 0) {
    48. let userInfo = wx.getStorageSync('userInfo');
    49. userInfo.phone = res.data.phone;//设置手机号码
    50. wx.setStorageSync('userInfo', userInfo);
    51. that.setData({
    52. userInfo: userInfo,
    53. hasLogin: true
    54. });
    55. wx.showToast({
    56. title: '绑定手机号码成功',
    57. icon: 'success',
    58. duration: 2000
    59. });
    60. }
    61. });
    62. },
    63. exitLogin: function () {
    64. wx.showModal({
    65. title: '',
    66. confirmColor: '#b4282d',
    67. content: '退出登录?',
    68. success: function (res) {
    69. if (!res.confirm) {
    70. return;
    71. }
    72. util.request(api.AuthLogout, {}, 'POST');
    73. app.globalData.hasLogin = false;
    74. wx.removeStorageSync('token');
    75. wx.removeStorageSync('userInfo');
    76. wx.reLaunch({
    77. url: '/pages/index/index'
    78. });
    79. }
    80. })
    81. }
    82. })

    3.2.后端代码

    在后台编写的控制器,来进行出来前端的请求及数据处理并且反馈带前端

    WxAuthController : 

    1. package com.junlinyi.ssm.wxcontroller;
    2. /**
    3. * @Autho donkee
    4. * @Since 2022/6/27
    5. */
    6. import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
    7. import com.alibaba.fastjson.JSONObject;
    8. import com.junlinyi.ssm.annotation.LoginUser;
    9. import com.junlinyi.ssm.model.UserInfo;
    10. import com.junlinyi.ssm.model.WxLoginInfo;
    11. import com.junlinyi.ssm.model.WxUser;
    12. import com.junlinyi.ssm.service.UserToken;
    13. import com.junlinyi.ssm.service.UserTokenManager;
    14. import com.junlinyi.ssm.service.WxUserService;
    15. import com.junlinyi.ssm.util.JacksonUtil;
    16. import com.junlinyi.ssm.util.ResponseUtil;
    17. import com.junlinyi.ssm.util.UserTypeEnum;
    18. import lombok.extern.slf4j.Slf4j;
    19. import org.springframework.beans.factory.annotation.Autowired;
    20. import org.springframework.util.StringUtils;
    21. import org.springframework.web.bind.annotation.PostMapping;
    22. import org.springframework.web.bind.annotation.RequestBody;
    23. import org.springframework.web.bind.annotation.RequestMapping;
    24. import org.springframework.web.bind.annotation.RestController;
    25. import cn.binarywang.wx.miniapp.api.WxMaService;
    26. import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
    27. import javax.servlet.http.HttpServletRequest;
    28. import java.text.DateFormat;
    29. import java.text.SimpleDateFormat;
    30. import java.util.Date;
    31. import java.util.HashMap;
    32. import java.util.Map;
    33. /**
    34. * 鉴权服务
    35. */
    36. @Slf4j
    37. @RestController
    38. @RequestMapping("/wx/auth")
    39. public class WxAuthController {
    40. @Autowired
    41. private WxMaService wxService;
    42. @Autowired
    43. private WxUserService userService;
    44. /**
    45. * 微信登录
    46. *
    47. * @param wxLoginInfo
    48. * 请求内容,{ code: xxx, userInfo: xxx }
    49. * @param request
    50. * 请求对象
    51. * @return 登录结果
    52. */
    53. @PostMapping("login_by_weixin")
    54. public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {
    55. //客户端需携带code与userInfo信息
    56. String code = wxLoginInfo.getCode();
    57. UserInfo userInfo = wxLoginInfo.getUserInfo();
    58. if (code == null || userInfo == null) {
    59. return ResponseUtil.badArgument();
    60. }
    61. //调用微信sdk获取openId及sessionKey
    62. String sessionKey = null;
    63. String openId = null;
    64. try {
    65. long beginTime = System.currentTimeMillis();
    66. //
    67. WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);
    68. // Thread.sleep(6000);
    69. long endTime = System.currentTimeMillis();
    70. log.info("响应时间:{}",(endTime-beginTime));
    71. sessionKey = result.getSessionKey();//session id
    72. openId = result.getOpenid();//用户唯一标识 OpenID
    73. } catch (Exception e) {
    74. e.printStackTrace();
    75. }
    76. if (sessionKey == null || openId == null) {
    77. log.error("微信登录,调用官方接口失败:{}", code);
    78. return ResponseUtil.fail();
    79. }else{
    80. log.info("openId={},sessionKey={}",openId,sessionKey);
    81. }
    82. //根据openId查询wx_user表
    83. //如果不存在,初始化wx_user,并保存到数据库中
    84. //如果存在,更新最后登录时间
    85. WxUser user = userService.queryByOid(openId);
    86. if (user == null) {
    87. user = new WxUser();
    88. user.setUsername(openId);
    89. user.setPassword(openId);
    90. user.setWeixinOpenid(openId);
    91. user.setAvatar(userInfo.getAvatarUrl());
    92. user.setNickname(userInfo.getNickName());
    93. user.setGender(userInfo.getGender());
    94. user.setUserLevel((byte) 0);
    95. user.setStatus((byte) 0);
    96. user.setLastLoginTime(new Date());
    97. user.setLastLoginIp(IpUtil.client(request));
    98. user.setShareUserId(1);
    99. userService.add(user);
    100. } else {
    101. user.setLastLoginTime(new Date());
    102. user.setLastLoginIp(IpUtil.client(request));
    103. if (userService.updateById(user) == 0) {
    104. log.error("修改失败:{}", user);
    105. return ResponseUtil.updatedDataFailed();
    106. }
    107. }
    108. // token
    109. UserToken userToken = null;
    110. try {
    111. userToken = UserTokenManager.generateToken(user.getId());
    112. } catch (Exception e) {
    113. log.error("微信登录失败,生成token失败:{}", user.getId());
    114. e.printStackTrace();
    115. return ResponseUtil.fail();
    116. }
    117. userToken.setSessionKey(sessionKey);
    118. log.info("SessionKey={}",UserTokenManager.getSessionKey(user.getId()));
    119. Map<Object, Object> result = new HashMap<Object, Object>();
    120. result.put("token", userToken.getToken());
    121. result.put("tokenExpire", userToken.getExpireTime().toString());
    122. userInfo.setUserId(user.getId());
    123. if (!StringUtils.isEmpty(user.getMobile())) {// 手机号存在则设置
    124. userInfo.setPhone(user.getMobile());
    125. }
    126. try {
    127. DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    128. String registerDate = df.format(user.getAddTime() != null ? user.getAddTime() : new Date());
    129. userInfo.setRegisterDate(registerDate);
    130. userInfo.setStatus(user.getStatus());
    131. userInfo.setUserLevel(user.getUserLevel());// 用户层级
    132. userInfo.setUserLevelDesc(UserTypeEnum.getInstance(user.getUserLevel()).getDesc());// 用户层级描述
    133. } catch (Exception e) {
    134. log.error("微信登录:设置用户指定信息出错:"+e.getMessage());
    135. e.printStackTrace();
    136. }
    137. result.put("userInfo", userInfo);
    138. log.info("【请求结束】微信登录,响应结果:{}", JSONObject.toJSONString(result));
    139. return ResponseUtil.ok(result);
    140. }
    141. /**
    142. * 绑定手机号码
    143. *
    144. * @param userId
    145. * @param body
    146. * @return
    147. */
    148. @PostMapping("bindPhone")
    149. public Object bindPhone(@LoginUser Integer userId, @RequestBody String body) {
    150. log.info("【请求开始】绑定手机号码,请求参数,body:{}", body);
    151. String sessionKey = UserTokenManager.getSessionKey(userId);
    152. String encryptedData = JacksonUtil.parseString(body, "encryptedData");
    153. String iv = JacksonUtil.parseString(body, "iv");
    154. WxMaPhoneNumberInfo phoneNumberInfo = null;
    155. try {
    156. phoneNumberInfo = this.wxService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
    157. } catch (Exception e) {
    158. log.error("绑定手机号码失败,获取微信绑定的手机号码出错:{}", body);
    159. e.printStackTrace();
    160. return ResponseUtil.fail();
    161. }
    162. String phone = phoneNumberInfo.getPhoneNumber();
    163. WxUser user = userService.selectByPrimaryKey(userId);
    164. user.setMobile(phone);
    165. if (userService.updateById(user) == 0) {
    166. log.error("绑定手机号码,更新用户信息出错,id:{}", user.getId());
    167. return ResponseUtil.updatedDataFailed();
    168. }
    169. Map<Object, Object> data = new HashMap<Object, Object>();
    170. data.put("phone", phone);
    171. log.info("【请求结束】绑定手机号码,响应结果:{}", JSONObject.toJSONString(data));
    172. return ResponseUtil.ok(data);
    173. }
    174. /**
    175. * 注销登录
    176. */
    177. @PostMapping("logout")
    178. public Object logout(@LoginUser Integer userId) {
    179. log.info("【请求开始】注销登录,请求参数,userId:{}", userId);
    180. if (userId == null) {
    181. return ResponseUtil.unlogin();
    182. }
    183. try {
    184. UserTokenManager.removeToken(userId);
    185. } catch (Exception e) {
    186. log.error("注销登录出错:userId:{}", userId);
    187. e.printStackTrace();
    188. return ResponseUtil.fail();
    189. }
    190. log.info("【请求结束】注销登录成功!");
    191. return ResponseUtil.ok();
    192. }
    193. }

    在 application.yml 文件中进行配置后台的数据库及微信小程序的AppID(小程序ID)及AppSecret(小程序密钥),来帮助访问微信的接口服务。

    1. server:
    2. port: 8080 #指服器端口号
    3. servlet:
    4. context-path: /oapro
    5. spring:
    6. datasource:
    7. #type连接池类型 DBCP,C3P0,Hikari,Druid,默认为Hikari
    8. type: com.zaxxer.hikari.HikariDataSource
    9. driver-class-name: com.mysql.jdbc.Driver
    10. url: jdbc:mysql://localhost:3306/mybatis_oapro?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    11. username: root
    12. password: 123456
    13. mybatis:
    14. mapper-locations: classpath*:mapper/*.xml #指定mapper文件位置
    15. type-aliases-package: com.CloudJun.ssm.model #指定自动生成别名所在包
    16. logging:
    17. level:
    18. root: info
    19. org.springframework: info
    20. org.mybatis: ERROR
    21. com.CloudJun.ssm.mapper: debug
    22. oa:
    23. wx:
    24. app-id: # 这里填写AppID(小程序ID)
    25. app-secret: # 这里填写AppSecret(小程序密钥)
    26. msgDataFormat: JSON

    最后后台开启服务,在前端进行数据访问及微信授权登入

    效果 : 

                                            

            好啦今天就到这里了,希望能帮到你哦!!!

  • 相关阅读:
    【机器学习可解释性】3.部分依赖图
    双重主要上市是反垄断之后,阿里求变的序曲?
    【高校科研前沿】东北地理所孙敬轩博士为一作在《中国科学:地球科学(中英文版)》发文:气候变化下东北地区农业绿水安全风险评估
    MySql相关时间处理的函数
    运动酒店,如何“奇袭”文旅产业精准蓝海赛道——缤跃酒店
    flutter开发实战-Universal Links配置及flutter微信分享实现
    Vue中Class绑定和style绑定的方式
    Win11怎么在右键菜单添加一键关机选项
    7.9lvs集群
    维格云轮播组件入门教程
  • 原文地址:https://blog.csdn.net/m0_74915426/article/details/134001316