admin管理员组

文章数量:1794759

Ruoyi

Ruoyi

  1. 在前端页面中引入 vue-qrcode 和 weixin-js-sdk 库,并使用以下代码生成二维码:

    <template><div id="qrcode"></div>
    </template>
    ​
    <script>
    import VueQrcode from 'vue-qrcode'
    import wx from 'weixin-js-sdk'
    ​
    export default {name: 'Qrcode',components: {VueQrcode,},data() {return {url: '',}},mounted() {this.generateQrcode()this.initWechat()},methods: {generateQrcode() {// 生成二维码const url = ''this.url = url},initWechat() {// 初始化微信 JS SDKconst url = window.location.href.split('#')[0]axios.get(`/api/wechat/jsApiConfig?url=${encodeURIComponent(url)}`).then(response => {const { data } = response.datawx.config({debug: false, // 开启调试模式appId: data.appId,timestamp: data.timestamp,nonceStr: data.nonceStr,signature: data.signature,jsApiList: ['scanQRCode'],})wx.ready(() => {// 监听扫描事件wx.scanQRCode({needResult: 1,scanType: ['qrCode', 'barCode'],success: (result) => {const { resultStr } = resultthis.handleScan(resultStr)},fail: (error) => {console.error(error)},})})}).catch(error => {console.error(error)})},handleScan(resultStr) {// 发送请求,获取 openidaxios.post('/api/wechat/authWithQrCode', { resultStr }).then(response => {const { code, msg, data } = response.dataif (code === 200) {// 已经登录,跳转到首页window.location.replace('/')} else if (code === 400) {// 未登录,跳转到绑定页面window.location.replace(`=wx123456789abcdef&redirect_uri=;response_type=code&scope=snsapi_userinfo&state=${data}&connect_redirect=1#wechat_redirect`)} else {alert(msg)}}).catch(error => {console.error(error)})},},
    }
    </script>

  2. 后端实现微信公众平台的认证、验证签名等操作,并且能够处理 /api/wechat/authWithQrCode 接口。

    @RestController
    @RequestMapping("/api/wechat")
    public class WechatController {
    ​@Autowiredprivate WxMpService wxMpService;
    ​@GetMapping("/jsApiConfig")public ResultEntity<WxJsapiSignature> jsApiConfig(@RequestParam String url) {try {WxJsapiSignature signature = wxMpService.createJsapiSignature(url);return ResultEntity.success(signature);} catch (WxMpException e) {e.printStackTrace();return ResultEntity.error("获取签名失败:" + e.getMessage());}}
    ​@PostMapping("/authWithQrCode")public ResultEntity<String> authWithQrCode(@RequestBody Map<String, String> params) {String resultStr = params.get("resultStr");try {// 校验请求是否合法,获取 openidWxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(resultStr);String openid = accessToken.getOpenId();
    ​// 查询数据库,判断该 openid 是否已经绑定过账户User user = userService.selectUserByOpenid(openid);if (user != null) {// 已经登录,返回登录信息String token = JwtUtils.generateToken(user);return ResultEntity.success(token);} else {// 未登录,返回绑定凭证String state = UUID.randomUUID().toString();redisService.set(state, openid, Duration.ofMinutes(5));return ResultEntity.error(400, "请先绑定账户", state);}} catch (WxErrorException e) {e.printStackTrace();return ResultEntity.error("请求微信接口失败:" + e.getMessage());}}
    }
  3. 绑定页面 /bindUser 显示用户绑定表单,并上传用户的 openid 和其他必填信息。

  4. 后端实现 /bindUser 接口,更新用户信息并返回自动登录信息。

    @RestController
    public class UserController {
    ​@Autowiredprivate UserService userService;
    ​@Autowiredprivate RedisService redisService;
    ​@PostMapping("/bindUser")public void bindUser(HttpServletRequest request, HttpServletResponse response) throws IOException {String code = request.getParameter("code");String state = request.getParameter("state");
    ​// 根据授权码获取 openidString openid = null;try {WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);openid = accessToken.getOpenId();} catch (WxErrorException e) {e.printStackTrace();response.sendRedirect("/error");return;}
    ​// 检查绑定凭证是否正确String storedOpenid = redisService.get(state);if (!openid.equals(storedOpenid)) {response.sendRedirect("/error");return;}
    ​// 处理用户绑定表单User user = userService.selectUserByOpenid(openid);if (user == null) {user = new User();user.setOpenid(openid);}user.setName(request.getParameter("name"));user.setGender(request.getParameter("gender"));user.setMobile(request.getParameter("mobile"));userService.saveOrUpdate(user);
    ​// 生成 token 并返回自动登录信息String token = JwtUtils.generateToken(user);response.sendRedirect(String.format("/autoLogin?token=%s", token));}
    }
  5. 自动登录页面 /autoLogin 接收 token 参数,将 token 存入 cookie 中,并重定向到首页。

    <template><div></div>
    </template>
    ​
    <script>
    import { setCookie } from '@/utils/cookie'
    ​
    export default {name: 'AutoLogin',props: {token: {type: String,required: true,},},mounted() {setCookie('token', this.token, 1)window.location.replace('/')},
    }
    </script>

本文标签: ruoyi