项目中集成微信扫码登陆,绑定手机号功能

项目中集成微信扫码登陆,绑定手机号功能,第1张

项目中集成微信扫码登陆,绑定手机号功能

一、准备工作 微信开放平台 注册并申请资质

微信提供介绍的文档

https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

 使用

项目中新建模块

添加依赖,调用微信提供的接口用到httpClient

 
        
            org.apache.httpcomponents
            httpclient
        
        
            com.alibaba
            fastjson
        
    

模块配置文件添加

#固定,微信提供地址
wx.open.app_id=购买后微信返回的值
wx.open.app_secret=购买后微信返回的值
#回调地址
wx.open.redirect_url=http://购买设置的回调地址/api/user/wx/callback

创建工具类,读取配置文件中内容

@Component
//@PropertySource("classpath:application.properties")
public class ConstantPropertiesUtil implements InitializingBean {
    //读取配置文件并赋值
    @Value("${wx.open.app_id}")
    private String appId;
    @Value("${wx.open.app_secret}")
    private String appSecret;
    @Value("${wx.open.redirect_url}")
    private String redirectUrl;
    public static String WX_OPEN_APP_ID;
    public static String WX_OPEN_APP_SECRET;
    public static String WX_OPEN_REDIRECT_URL;
    @Override
    public void afterPropertiesSet() throws Exception {
        WX_OPEN_APP_ID = appId;
        WX_OPEN_APP_SECRET = appSecret;
        WX_OPEN_REDIRECT_URL = redirectUrl;
    }
}

控制层

@Controller
@RequestMapping("/api/user/wx")
public class WeixinApiController {
    //返回登陆二维码参数
    @GetMapping("getLoginParam")
    @ResponseBody
    public R genQrConnect(HttpSession session) throws UnsupportedEncodingException {
        String redirectUri = URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, "utf-8");
        Map map = new HashMap<>();
        map.put("appid", ConstantPropertiesUtil.WX_OPEN_APP_ID);
        map.put("redirectUri", redirectUri);
        map.put("scope", "snsapi_login");
        map.put("state", System.currentTimeMillis() + "");//System.currentTimeM
        return R.ok().data(map);
    }
}

vue中创建api/wx.js

import request from '@/utils/request'
const api_name = `/api/user/wx`
export default {
 getLoginParam() {
 return request({
 url: `${api_name}/getLoginParam`,
 method: `get`
 })
 }
}

修改layouts/myheader.vue文件,添加微信二维码登录逻辑

import wxApi from '@/api/yygh/wx'   引入js文件

使用dom方式引入微信提供的js文件

 mounted() {  //页面渲染之后执行
    // 注册全局登录事件对象
    window.loginEvent = new Vue();
    // 监听登录事件
    loginEvent.$on('loginDialogEvent', function () {
      document.getElementById("loginDialog").click();
    })
    // 触发事件,显示登录层:loginEvent.$emit('loginDialogEvent')
    //引入微信二维码需要js文件
    const script = document.createElement("script")
    script.type = 'text/javascript'
    script.src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"
    document.body.appendChild(script)
  },

页面绑定点击事件

weixinLogin() {
      this.dialogAtrr.showLoginType = 'weixin'

      //调用二维码生成接口,得到返回数据
      wxApi.getLoginParam().then(response => {
        var obj = new WxLogin({
            self_redirect:true,
            id:"weixinLogin", 
            appid: response.data.appid, // 公众号appid wx*******
            scope: response.data.scope, // 网页默认即可
            redirect_uri: response.data.redirectUri, // 授权成功后回调的url
            state: response.data.state, // 可设置为简单的随机数加session用来校验
            style: 'black', // 提供"black"、"white"可选。二维码的样式
            href: '' // 外部css文件url,需要https
        });
      })
    },

此时启动即可访问到二维码

扫码后流程

扫码后-同意-微信回应(调用微信管理后台配置回调地址)-返回code:临时票据,state:生成二维码传过去的值

拿着code值与id请求微信接口地址,微信再返回opeid与access_token,接受数据后在请求-得到扫码人信息

控制层添加回调方法

@GetMapping("callback")
    public String callback(String code,String state){
        try {
        //拿着code和appid请求微信接口
        System.out.println("code:"+code);
        //第二步 拿着code和微信id和秘钥,请求微信固定地址 ,得到两个值
        //使用code和appid以及appscrect换取access_token
        // %s 占位符
        StringBuffer baseAccessTokenUrl = new StringBuffer()
                .append("https://api.weixin.qq.com/sns/oauth2/access_token")
                .append("?appid=%s")
                .append("&secret=%s")
                .append("&code=%s")
                .append("&grant_type=authorization_code");
        //像占位符中传参数
        String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                                ConstantPropertiesUtil.WX_OPEN_APP_ID,
                                ConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                                code);
        //使用httpClient发送请求
         String result = HttpClientUtils.get(accessTokenUrl);
         //拿着code值与id请求微信接口地址
         JSonObject jsonObject = JSONObject.parseObject(result);
         String access_token = jsonObject.getString("access_token");
         String openid = jsonObject.getString("openid");
         //判断数据库是否存在openid
         UserInfo userInfo =  userInfoService.findUserByOpenid(openid);
         if (userInfo == null){
             //opeid与access_token请求获取扫码人信息
             String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo"
                     +"?access_token=%s" +
                     "&openid=%s";
             String userInfoUrl = String.format(baseUserInfoUrl, access_token,openid);
             String userResult = HttpClientUtils.get(userInfoUrl);
             //获取扫码人昵称
             JSonObject userJson = JSONObject.parseObject(userResult);
             String nickname = userJson.getString("nickname");
             //加入数据库
             userInfo = new UserInfo();
             userInfo.setNickName(nickname);
             userInfo.setOpenid(openid);
             userInfo.setStatus(1);
             userInfoService.save(userInfo);
         }
        //返回登陆需要的数据
            Map map = new HashMap<>();
            String name = userInfo.getName();
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getNickName();
            }
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
            map.put("name", name);
            //判断userInfo是否有手机号,如果手机号为空,返回openid
            //如果手机号不为空,返回openid值是空字符串
            //前端判断:如果openid不为空,绑定手机号,如果openid为空,不需要绑定手机号
            if(StringUtils.isEmpty(userInfo.getPhone())) {
                map.put("openid", userInfo.getOpenid());
            }else {
                map.put("openid","");
            }
            //使用jwt生成token字符串
            String token = JwtHelper.createToken(userInfo.getId(), name);
            map.put("token", token);

            //跳转到前端中转页面
            return "redirect:http://localhost:3000/weixin/callback?token="
                    +map.get("token")+"&openid="+map.get("openid")
                    +"&name="+URLEncoder.encode(map.get("name"),"utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

vue中创建/pages/weixin/callback.vue 作为中转页面


在myheader.vue添加方法

 methods: {
    loginCallback(name, token, openid) {
 // 没绑定手机号跳转到绑定  有手机号登陆
    if(openid != '') {
    this.userInfo.openid = openid
    this.showLogin()
    } else {
    this.setcookies(name, token)
    }
    },

此时这个方法为私有的,页面调不到,在mounted() 中添加

    // 微信登录回调处理
    let self = this;
    window["loginCallback"] = (name,token, openid) => {
    self.loginCallback(name, token, openid);
    }

绑定手机号加入数据库,修改UserInfoServiceImpl

 @Override
    public Map login(LoginVo loginVo) {
            String phone = loginVo.getPhone();
            String code = loginVo.getCode();
            //校验参数
            if(StringUtils.isEmpty(phone) ||
                    StringUtils.isEmpty(code)) {
                throw new YyghException(20001,"数据为空");
            }
            //TODO 校验校验验证码
            String redisCode = (String) redisTemplate.opsForValue().get(phone);
            if (!code.equals(redisCode)){
                throw new YyghException(20001,"校验是失败");
            }
            //判断手机验证码登陆还是微信绑定手机号
        //获取页面传来的openid值
        String openid = loginVo.getOpenid();
            //判断openid不为空 绑定手机号
        if (StringUtils.isEmpty(openid)){
            //手机号已被使用
            QueryWrapper queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("phone", phone);
            //获取会员
            UserInfo userInfo = baseMapper.selectOne(queryWrapper);
            //注册
            if(null == userInfo) {
                userInfo = new UserInfo();
                userInfo.setName("");
                userInfo.setPhone(phone);
                userInfo.setStatus(1);
                this.save(userInfo);
            }
            //校验是否被禁用
            if(userInfo.getStatus() == 0) {
                throw new YyghException(20001,"用户已经禁用");
            }
            //返回页面显示名称  登陆以后,若名称为空就在页面显示手机号
            Map map = new HashMap<>();
            String name = userInfo.getName();
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getNickName();
            }
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
            map.put("name", name);
            //生成token
            String token = JwtHelper.createToken(userInfo.getId(), name);
            map.put("token", token);
            return map;
        }else {
            //openid不为空  绑定手机号
            //根据手机号查询数据库中信息,若有先删除
            baseMapper.delete(new QueryWrapper().eq("phone",phone));
            //根据openid查询微信信息
            QueryWrapper wrapper = new QueryWrapper<>();
            wrapper.eq("openid",openid);
            UserInfo userInfo = baseMapper.selectOne(wrapper);
            //设置绑定手机号
            userInfo.setPhone(phone);
            //修改手机号
            baseMapper.updateById(userInfo);
            //校验是否被禁用
            if(userInfo.getStatus() == 0) {
                throw new YyghException(20001,"用户已经禁用");
            }
            //返回页面显示名称  登陆以后,若名称为空就在页面显示手机号
            Map map = new HashMap<>();
            String name = userInfo.getName();
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getNickName();
            }
            if(StringUtils.isEmpty(name)) {
                name = userInfo.getPhone();
            }
            map.put("name", name);
            //生成token
            String token = JwtHelper.createToken(userInfo.getId(), name);
            map.put("token", token);
            return map;
        }
    }

流程总结:

扫码后回调方法,在方法中按微信规则,获取数据,若没绑定手机号自定义规则传到前端,前端跳转到中转页面,通过固定路由跳转到绑定页面,调用绑定手机号方法

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5718394.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存