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

微信提供介绍的文档

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

使用

项目中新建模块

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

 <dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency></dependencies>

模块配置文件添加

#固定,微信提供地址
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;@Overridepublic 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")@ResponseBodypublic R genQrConnect(HttpSession session) throws UnsupportedEncodingException {String redirectUri = URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, "utf-8");Map<String, Object> 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.currentTimeMreturn 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, // 授权成功后回调的urlstate: 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");//判断数据库是否存在openidUserInfo 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<String,String> 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 作为中转页面

<template><!-- header --><div>
</div><!-- footer -->
</template>
<script>
export default {data() {return {}},mounted() {//获取浏览器的值let token = this.$route.query.tokenlet name = this.$route.query.namelet openid = this.$route.query.openid// 调用父vue方法window.parent['loginCallback'](name, token, openid)}
}
</script>

在myheader.vue添加方法

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

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

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

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

 @Overridepublic Map<String, Object> 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<UserInfo> 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<String, Object> 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);//生成tokenString token = JwtHelper.createToken(userInfo.getId(), name);map.put("token", token);return map;}else {//openid不为空  绑定手机号//创建userInfo对象,用于存储最终数据UserInfo userInfoFinal = new UserInfo();//根据手机号查数据UserInfo userInfo = baseMapper.selectOne(new QueryWrapper<UserInfo>().eq("phone",phone));if (userInfo != null){//将数据库的数据封装到userinfofinalBeanUtils.copyProperties(userInfo,userInfoFinal);//将手机号删除baseMapper.delete(new QueryWrapper<UserInfo>().eq("phone",phone));}//根据openid查询微信信息QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();wrapper.eq("openid",openid);UserInfo userInfoWX = baseMapper.selectOne(wrapper);//将信息封装到userinfofinal中userInfoFinal.setOpenid(userInfoWX.getOpenid());userInfoFinal.setNickName(userInfoWX.getNickName());userInfoFinal.setId(userInfoWX.getId());if (userInfo == null){userInfoFinal.setPhone(phone);userInfoFinal.setStatus(userInfoWX.getStatus());}//修改手机号baseMapper.updateById(userInfoFinal);//校验是否被禁用if(userInfo.getStatus() == 0) {throw new YyghException(20001,"用户已经禁用");}//返回页面显示名称  登陆以后,若名称为空就在页面显示手机号Map<String, Object> 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);//生成tokenString token = JwtHelper.createToken(userInfo.getId(), name);map.put("token", token);return map;}}

流程总结

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

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

  1. 最最最详细的springboot项目中集成微信扫码登入功能.步骤代码超级详细(OAuth2)

    说到登录注册,就会想到先要注册一个用户名,在进行登入,但是现在大多数的网站都集成了微信登入,不需要注册,给你一个二维码,微信一扫直接登录.这确实是十分便捷的.所以我们会尽量在项目中实现这一功能.减少用 ...

  2. 微擎支付返回商户单号_一步一步教你在SpringBoot中集成微信扫码支付

    一:准备工作 使用微信支付需要先开通服务号,然后还要开通微信支付,最后还要配置一些开发参数,过程比较多. 申请服务号(企业) 开通微信支付 开发配置 具体准备工作请参考Spring Boot入门教程( ...

  3. VUE项目中的微信扫码登录

    微信扫码登录功能 首先了解微信扫码登录的流程和详解,详见微信扫码登录,这边仅是vue前端相关流程 一.创建微信登录按钮及方法,配置相关参数 1.创建微信登录按钮 <!--微信授权登录按钮--&g ...

  4. SpringBoot 2 集成微信扫码支付

    前言 该文主要是手把手教你如何在SpringBoot 中集成微信扫码支付,以及集成的过程需要注意的问题事项.另外需要感谢 vbirdbest 关于微信支付和支付宝支付相关包博客总结.因为文中很多地方参 ...

  5. 账号与微信绑定,微信扫码登陆

    今天完成了pc端微信相关功能的开发,主要是账号与微信绑定,微信扫码登陆. 流程,用户登陆后,在个人中心里有一个和微信绑定界面,用户使用微信扫描后,当前账号和微信账号绑定,可以用来微信扫描登陆. 在登陆 ...

  6. java实现PC网站实现微信扫码登陆

    近期,开发一个项目要求PC网站可以进行扫码登陆. 1.前期工作 需要先在微信开放平台进行注册(https://open.weixin.qq.com/),并认证一个网站应用. 点击查看按钮,我们需要记录 ...

  7. 第六天 黑马十次方 用户注册、用户登陆掌握js-cookie、微信扫码登陆、nuxt嵌套路由

    学习目标: ** 完成用户注册功能 完成用户登陆功能,掌握js-cookie的使用 完成微信扫码登陆的功能 完成用户中心嵌套布局,掌握nuxt嵌套路由的使用 ** 1 用户注册 1.1 页面构建 创建 ...

  8. Android 微信扫码登陆

    最近项目需求中有一个微信扫码登陆功能,即用手机微信扫码功能扫描终端二维码实现登陆的功能 随即打开微信开发者文档查看,不亏为官方,简洁明了,看得我是一脸懵逼,踩了N多坑,太不友好了,言归正传,希望对一些 ...

  9. 微信扫码登陆在chrome浏览器失败

    浏览器会提示:(新版本的浏览器会提示) Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://www. ...

  10. 微信扫码登陆在chrome浏览器被拦截

    浏览器会提示:(新版本的浏览器会提示) Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://www. ...

最新文章

  1. 加mp4文件后js失效_Jquery方法load之后导致js失效解决方法
  2. proj4经纬度bl转换xy_多种坐标系之间的转换之Proj.NET_转载
  3. Spring Boot-使用Spring Initializer快速创建Spring Boot项目
  4. Oracle数据库之SQL连接查询
  5. 面试官:如何写出让 CPU 跑得更快的代码?
  6. mysql 组合查询_MySQL组合查询教程
  7. JS针对图片加载及404处理
  8. 给postmessage加上callback方法
  9. java二维码生成代码_java快速开发平台功能特点之代码生成器
  10. ubuntu16.04 安装kicad5.1
  11. typedef struct LNode* list和struct LNode有什么区别?
  12. 改变人类命运的造人计划
  13. 最实用的上网网址一览表
  14. oracle+suspend+参数,oracle数据库的挂起(Suspending)和恢复(Resuming)
  15. 通过IMAP方式迁移U-Mail邮件到Exchange 2013之2008R2 AD搭建!
  16. 《网络黑白》一书所抄袭的文章列表
  17. 数据挖掘之监督学习篇
  18. python写手机脚本脱离电脑_在手机里编写python脚本控制手机
  19. 华为云面试指南—Rainbow
  20. hive partition简介

热门文章

  1. deepin有线网卡无法连接网络
  2. 用Python模拟QQ界面之QQ登录界面的奥秘
  3. 视频插帧论文阅读(一)——FLAVR
  4. R 实现层次分析法确定指标权重
  5. 多年录制游戏的心得分享
  6. 无人机影像的植被覆盖度、叶面积指数估算
  7. c++filt 命令
  8. 产品学习---互联网形势
  9. android微信支付跳转逻辑,Android对接微信支付
  10. kubeedge集群搭建