当前位置: 首页>数据库>正文

若依与Uniapp之微信公众号免密登录

微信公众号免密登录

  • 1. 微信公众号官网文档
  • 2. 开发
    • 2.1 后端微信配置
      • 2.1.1 配置微信
      • 2.1.2 微信公众号接口参数配置
    • 2.2 免密登录
      • 2.2.1 Uniapp端默认页面bind.vue
      • 2.2.2 Uniapp端回调login登录页实现免密登录
      • 2.2.3 后端免密登录接口
      • 2.2.4 踩过的坑
    • 2.3 手动登录
      • 2.3.1 Uniapp端login登录页实现手动登录
      • 2.3.2 后端login接口
  • *******************************************************************************************

1. 微信公众号官网文档

微信公众号官网文档

微信网页开发文档

2. 开发

2.1 后端微信配置

2.1.1 配置微信

#微信公众号配置
wexin:
  #开发者ID
  appid: 保密
  #开发者密码
  secret: 保密
  #获取token的请求地址
  getTokenUrl: https://api.weixin.qq.com/sns/oauth2/access_token

2.1.2 微信公众号接口参数配置

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chery.common.constant.Constants;
import com.chery.common.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @description: 调用微信公众号接口参数配置
 * @date 2020-11-27
 */
@Component
@Slf4j
@ConfigurationProperties(prefix = "wexin")
public class EnterpriseWeXin {
    /**
     * 获取token url
     */
    private static String getTokenUrl;

    /**
     * 开发者ID
     */
    private static String appid;
    /**
     * 开发者密码
     */
    private static String secret;


    public static String getGetTokenUrl() {
        return getTokenUrl;
    }

    public void setGetTokenUrl(String getTokenUrl) {
        EnterpriseWeXin.getTokenUrl = getTokenUrl;
    }

    public static String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        EnterpriseWeXin.appid = appid;
    }

    public static String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        EnterpriseWeXin.secret = secret;
    }

    public static String getOpenId(String code) {
        String openid = "";
        try {
            String param = "appid=" + EnterpriseWeXin.getAppid() + "&secret=" + EnterpriseWeXin.getSecret() + "&code=" + code + "&grant_type=authorization_code";
            String resStr = HttpUtils.sendGet(EnterpriseWeXin.getGetTokenUrl(), param);
            if (StringUtils.isNotEmpty(resStr)) {
                JSONObject res = JSON.parseObject(resStr);
                if (res != null && res.containsKey(Constants.OPENID)) {
                    openid = res.getString(Constants.OPENID);
                }
            }
        } catch (Exception e) {
            log.error("微信公众号获取openid失败", e.getMessage());
        }
        return openid;
    }
}

2.2 免密登录

2.2.1 Uniapp端默认页面bind.vue

<template>
  <view>

  </view>
</template>

<script>
export default {
  onLoad(option) {
    //url提供给微信,然后微信将code传递到该url页面,我这边选的是登录页login.vue
    const url = "http%3A%2F%2Fyuhai.com%2Fpages%2Flogin%2Flogin";
    //发起微信请求,appid参数在公众号获取;scope有两种模式详情见文档
    window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?" +
        "appid=wx95a639d8025a505a&redirect_uri=" + url + "&scope=snsapi_base&response_type=code&state=STATE#wechat_redirect";
  },
  methods: {
    toLogin() {
      uni.reLaunch({
        url: '/pages/login/login',
      });
    }
  }
}
</script>

<style>

</style>

踩过的坑:

  1. 回调的url不要带#号,不然回调页面无法获取code
    若依与Uniapp之微信公众号免密登录,在这里插入图片描述,第1张
  2. 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
    什么是urlEncode 对链接进行处理?

打开谷歌浏览器的调试控制台
若依与Uniapp之微信公众号免密登录,在这里插入图片描述,第2张

控制台输入encodeURIComponent(‘url地址’),复制出返回的字符串即可,单引号别复制
若依与Uniapp之微信公众号免密登录,在这里插入图片描述,第3张

2.2.2 Uniapp端回调login登录页实现免密登录

若依与Uniapp之微信公众号免密登录,在这里插入图片描述,第4张

onLoad

  onLoad(option) {
    //获取回调code
    this.loginForm.code = option.code;
    //发起code登录
    this.wxLoginByCode()
  }

methods

    wxLoginByCode() {
      //发起微信免密登录
      this.$u.get('/wechat/login?code=' + this.loginForm.code).then(res => {
        if (res.code == 200 && res.token) {
          uni.setStorageSync('token', res.token)
          this.$u.get('/getInfo').then(res => {
            uni.dicParams.user = res.user
            uni.setStorageSync('user', res.user)
            uni.reLaunch({
              url: '/pages/index/index',
            });
          })
        } else {
          uni.showToast({
            icon: 'none',
            title: res.msg,
          });
        }
      }).catch(res => {
        uni.showToast({
          icon: 'none',
          title: res.msg,
        });
      })
    },

2.2.3 后端免密登录接口

    /**
     * 微信免密登录
     *
     * @param code
     * @param state
     * @return
     */
    @GetMapping("/wechat/login")
    public AjaxResult wechatLogin(@RequestParam("code") String code) {
        AjaxResult ajax = AjaxResult.success();
        if (StrUtil.isEmpty(code)) {
            return AjaxResult.error("code不存在");
        }
        // 生成令牌
        String token = loginService.loginWx(code);
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }
    /**
     * 微信免密登录
     *
     * @param code
     * @return
     */
    public String loginWx(String code) {
        String openId = EnterpriseWeXin.getOpenId(code);
        redisCache.setCacheObject(CacheConstants.WEI_XIN_CODE_OPEN_ID_KEY + code, openId, 5, TimeUnit.MINUTES);
        //处理企业微信登录
        LoginUser loginUser = null;
        //校验openId
        SysUser user = userService.getUserByOpenId(openId);
        if (StringUtils.isNotNull(user)) {
            loginUser = new LoginUser(user, permissionService.getMenuPermission(user));
            recordLoginInfo(loginUser.getUser());
            // 生成token
            return tokenService.createToken(loginUser);
        } else {
            throw new ServiceException("未绑定账号,请手动登录!");
        }
    }

2.2.4 踩过的坑

  1. 为什么免密登录获取到openid需要缓存在redis五分钟?
    官网文档:用户同意授权,获取code
    若依与Uniapp之微信公众号免密登录,在这里插入图片描述,第5张
    如果不缓存并且用户还没绑定到系统,此时用户手动登录时获取不到openid,导致用户系统账号不会和微信openid绑定

  2. 开放匿名微信登录接口

.antMatchers("/wechat/login").permitAll()

不要放在

.antMatchers("/login","/wechat/login", "/captchaImage").anonymous()

2.3 手动登录

用户第一次登录系统,未绑定系统账户时使用的功能
实现用户登录和用户绑定业务需求

2.3.1 Uniapp端login登录页实现手动登录

methods
基本不用动,在请求/login请求时添加code: this.loginForm.code参数

    login() {
      if (this.loginForm.userName == 0) {
        uni.showToast({
          icon: 'none',
          title: '用户名不能为空'
        });
        return;
      }
      if (this.loginForm.password.length == 0) {
        uni.showToast({
          icon: 'none',
          title: '密码不能为空'
        });
        return;
      }
      this.$u.post('/login', {
        username: this.loginForm.userName,
        password: this.loginForm.password,
        code: this.loginForm.code
      }).then(res => {
        if (res.code == 200) {
          if (this.loginForm.rememberPsw) { //用户勾选“记住密码”
            console.log("记住密码")
            uni.setStorageSync('userName', this.loginForm.userName);
            uni.setStorageSync('password', this.loginForm.password);
          } else { //用户没有勾选“记住密码”
            console.log("没有记住密码")
            uni.removeStorageSync('userName');
            uni.removeStorageSync('password');
            this.loginForm.userName = "";
            this.loginForm.password = "";
          }
          uni.setStorageSync('token', res.token)
          this.$u.get('/getInfo').then(res => {
            uni.dicParams.user = res.user
            uni.setStorageSync('user', res.user)
            uni.reLaunch({
              url: '/pages/index/index',
            });
          })
        } else {
          uni.showToast({
            icon: 'none',
            title: res.msg,
          });
        }
      }).catch(res => {
        uni.showToast({
          icon: 'none',
          title: res.msg,
        });
      })
    }

2.3.2 后端login接口

    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        Long userId = null;
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getUuid());

        //账号绑定微信openid
        if (StringUtils.isNotEmpty(token) && StringUtils.isNotEmpty(loginBody.getCode())) {
            String code = loginBody.getCode();
            String userName = loginBody.getUsername();
            CompletableFuture.runAsync(() -> {
            	//无法请求微信获取openId,所以从缓存获取
                String openId = redisCache.getCacheObject(CacheConstants.WEI_XIN_CODE_OPEN_ID_KEY + code);
                if (StringUtils.isEmpty(openId)) {
                    log.error("用户: {}绑定微信失败!", userName);
                } else {
                	//根据userName更新openId
                    userService.updateOpenIdByUserName(openId, userName);
                    log.info("用户:{}绑定微信成功!", userName);
                }
            }, threadPoolExecutor);
        }
        
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

*******************************************************************************************


https://www.xamrdz.com/database/6c21977000.html

相关文章: