准备

如不了解第三方登录流程,建议先大概了解一下,在来看看代码。
说明: 由于开放平台无测试号测试,所以只能上开放平台进行配置信息。公众平台的测试号并不能给开放平台使用。

微信开放平台地址:https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN

配置步骤如下:

1、创建web应用

当创建成功的时候会有appidappsecret,下面代码需要用到。
创建好之后需要设置回调域 ,就是当扫码通过之后会调用该域内的地址,地址在下面代码种配置。

2、注意!!!
1、设置回调域的时候,前面不能加上http://等协议。只需要配置域名即可,如baidu.com,spring.io等。填写成http://spring.io/是错误的
2、域名不能加端口号

代码

<一> 获取二维码

  /*** 跳转至微信登录界面*/// Result 定义的类,返回给前端的信息@ApiOperation(value = "网站-微信扫码登录路径", notes = "网站-微信扫码登录路径")@GetMapping(value = "/web/wxLoginPage")public Result webWxKfLoginPage() throws Exception {String url = WeChatLoginUtil.webWxKfLoginPage();return Result.Builder.newBuilder(AppTipStatusEmum.SUCCESS_STATUS.getCode(), AppTipMsgEnum.SELECT_SUCCESS.getText()).setMessage("获取二维码成功!").setData(url).build();}

涉及的WeChatLoginUtil类如下:

import com.uwa.mall.user.module.enums.ThirdPartyLoginEnum;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;public class WeChatLoginUtil {// ===============================================web方式==================================================// 网页方式登录(scope=snsapi_login)public static String webWxKfLoginPage() throws Exception {// 防止csrf攻击(跨站请求伪造攻击)String state = UUID.randomUUID().toString().replaceAll("-", "");// 存入redis。 CacheUtil为封装redis的工具类CacheUtil.set(ThirdPartyLoginEnum.WeChatEnum.WeChatKFState.getCode() + state, "ok", Integer.valueOf(ThirdPartyLoginEnum.WeChatEnum.WeChatKFStateTime.getCode()));// 普通微信三方地址String url = ThirdPartyLoginEnum.WeChatEnum.AppUrl.getCode() + "appid=" + ThirdPartyLoginEnum.WeChatEnum.AppID.getCode() + "&redirect_uri=" + ThirdPartyLoginEnum.WeChatEnum.RedirectUri.getCode()+ "&response_type=code&scope=snsapi_login&state=" + state + "#wechat_redirect";return url;}/*** 通过code获取token** @return*/public static Map getAccessToken(String code, String appid, String secret) throws Exception {// 构建请求数据Map t = new HashMap();t.put("appid", appid);t.put("secret", secret);t.put("code", code);t.put("grant_type", "authorization_code");// 调用httpclient处理请求得到返回json数据String returnJson = HttpClientUtil.httpGet(ThirdPartyLoginEnum.WeChatEnum.AccessTokenUri.getCode(), t);Map token = JsonUtil.fromJson(returnJson, Map.class);return token;}/*** 刷新token处理** @return*/public static Map refreshToken(String appid, String refresh_token) throws Exception {// 构建请求参数Map m = new HashMap();m.put("appid", appid);m.put("grant_type", "refresh_token");m.put("refresh_token", refresh_token);String s = HttpClientUtil.httpGet(ThirdPartyLoginEnum.WeChatEnum.UrlRefresh.getCode(), m);// 调用httpclient发出请求Map refreshToken = JsonUtil.fromJson(s, Map.class);return refreshToken;}/*** 通过token获取用户信息* * @param token* @return*/public static String getUserInfo(Map token) throws Exception {// 构建请求数据Map u = new HashMap();u.put("access_token", token.get("access_token"));u.put("openid", token.get("openid"));u.put("lang", "zh_CN");// 调用httpclient处理请求得到用户信息json数据String userinfo = HttpClientUtil.httpGet(ThirdPartyLoginEnum.WeChatEnum.UrlUserInfo.getCode(), u);return userinfo;}// ===============================================公众号方式==================================================// 公众号方式登录(scope=snsapi_base)public static String publicWxKfLoginPage() {String state = UUID.randomUUID().toString().replaceAll("-", "");CacheUtil.set(ThirdPartyLoginEnum.PublicWeChatEnum.WeChatKFState.getCode() + state, "ok", Integer.valueOf(ThirdPartyLoginEnum.PublicWeChatEnum.WeChatKFStateTime.getCode()));String url = ThirdPartyLoginEnum.PublicWeChatEnum.AppUrl.getCode() + "appid=" + ThirdPartyLoginEnum.PublicWeChatEnum.AppID.getCode() + "&redirect_uri="+ ThirdPartyLoginEnum.PublicWeChatEnum.RedirectUri.getCode() + "&response_type=code&scope=snsapi_userinfo&state=" + state + "#wechat_redirect";return url;}// 公众号 通过code获取tokenpublic static Map getAccessTokenByPublic(String code, String appid, String secret) throws Exception {// 构建请求数据Map t = new HashMap();t.put("appid", appid);t.put("secret", secret);t.put("code", code);t.put("grant_type", "authorization_code");// 调用httpclient处理请求得到返回json数据String returnJson = HttpClientUtil.httpGet(ThirdPartyLoginEnum.PublicWeChatEnum.AccessTokenUri.getCode(), t);Map token = JsonUtil.fromJson(returnJson, Map.class);return token;}public static Map refreshTokenByPublic(String appid, String refresh_token) throws Exception {// 构建请求参数Map m = new HashMap();m.put("appid", appid);m.put("grant_type", "refresh_token");m.put("refresh_token", refresh_token);String s = HttpClientUtil.httpGet(ThirdPartyLoginEnum.PublicWeChatEnum.UrlRefresh.getCode(), m);// 调用httpclient发出请求Map refreshToken = JsonUtil.fromJson(s, Map.class);return refreshToken;}public static String getUserInfoByPublic(Map token) throws Exception {// 构建请求数据Map u = new HashMap();u.put("access_token", token.get("access_token"));u.put("openid", token.get("openid"));u.put("lang", "zh_CN");// 调用httpclient处理请求得到用户信息json数据String userinfo = HttpClientUtil.httpGet(ThirdPartyLoginEnum.PublicWeChatEnum.UrlUserInfo.getCode(), u);return userinfo;}}

涉及的ThirdPartyLoginEnum枚举接口类如下:

// 第三方登录方式
public interface ThirdPartyLoginEnum {// 网页微信登录方式enum WeChatEnum {AppID("xxx.....xxx","微信开发平台的AppID"),AppSecret("xxx.....xxx","微信开发平台的AppSecret"),AppUrl("https://open.weixin.qq.com/connect/qrconnect?","微信第三方地址"),RedirectUri("http://www.ycj.com/login/wxLogin","登录成功的回调地址"),  //这里的域名和前面配置的域名必须一致,且不能加端口号AccessTokenUri("https://api.weixin.qq.com/sns/oauth2/access_token","获取access_token的地址"),UrlRefresh("https://api.weixin.qq.com/sns/oauth2/refresh_token","刷新获取微信token"),UrlUserInfo("https://api.weixin.qq.com/sns/userinfo","获取用户信息"),WeChatKFState("wechat-kf-state","redis的key"),WeChatKFStateTime("300","redis的key的过期时间(秒)");private String code;private String msg;WeChatEnum(String c, String m) {this.code = c;this.msg = m;}public String getCode() {return code;}public String getMsg() {return msg;}}// 公众号微信登录方式(移动端)enum PublicWeChatEnum {AppID("xxx.....xxx","微信公众平台的AppID"),AppSecret("xxx.....xxx","微信公众平台的AppSecret"),AppUrl("https://open.weixin.qq.com/connect/oauth2/authorize?","微信第三方地址"),RedirectUri("http://activate.navicat.com/mall/user/api/loginAndRegister/public/wxLoginCallback","登录成功的回调地址"),  //这里的域名和公众平台(不是本文的)配置的域名必须一致,且不能加端口号AccessTokenUri("https://api.weixin.qq.com/sns/oauth2/access_token","获取access_token的地址"),UrlRefresh("https://api.weixin.qq.com/sns/oauth2/refresh_token","刷新获取微信token"),UrlUserInfo("https://api.weixin.qq.com/sns/userinfo","获取用户信息"),WeChatKFState("wechat-kf2-state","redis的key"),WeChatKFStateTime("300","redis的key的过期时间(秒)");private String code;private String msg;PublicWeChatEnum(String c, String m) {this.code = c;this.msg = m;}public String getCode() {return code;}public String getMsg() {return msg;}}enum CacheParamEnum{WXOpenID("WX_OpenID_","redis的key"),WXOpenIDTime("300","redis的key的过期时间(秒)");private String code;private String msg;CacheParamEnum(String c, String m) {this.code = c;this.msg = m;}public String getCode() {return code;}public String getMsg() {return msg;}}}

<二>扫码登录回调

  // type有web和public两种类型,本文是开放平台,{type}使用的是web@ApiOperation(value = "微信登录回调", notes = "微信登录回调")@GetMapping("/{type}/wxLoginCallback")public Result wxLoginCallback(@PathVariable("type") String type, @RequestParam(name = "code") String code, @RequestParam(name = "state", required = false) String state) throws Exception {return thirdLoginService.wxLoginCallback(code, state, type);}

涉及的thirdLoginService.wxLoginCallback接口代码如下:

  // 微信登录回调@Override@Transactional(rollbackFor = Exception.class)public Result wxLoginCallback(String code, String state, String type) throws Exception {AssertException.isNull(code, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:code is empty,请重新登录!");AssertException.isNull(state, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:state is empty,请重新登录!");Map userMap = null;int regType = RegisterTypeEnum.WX_WEB.getCode();  //枚举:web类型是开放平台,public是公众平台if ("web".equals(type)) {userMap = thirdGetUserInfoService.wxGetUserInfo(code, state);  //获取用户信息} else if ("public".equals(type)) {regType = RegisterTypeEnum.WX_MP.getCode();userMap = thirdGetUserInfoService.wxPublicGetUserInfo(code, state);  //获取用户信息} else {AssertException.assertException(AppTipMsgEnum.LOGIN_FAIL.getCode(), "回调类型错误!");}AssertException.isNullObject(userMap, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败,请重新登录!");AssertException.assertException(userMap.get("errcode") != null, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:" + userMap.get("errmsg") + ",请重新登录!");AssertException.isNullObject(userMap.get("openid"), AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:openid为空!,请重新登录!");// 以下是你自己的代码逻辑操作......// 以下是你自己的代码逻辑操作......// 以下是你自己的代码逻辑操作......return Result.Builder.newBuilder(AppTipStatusEmum.SUCCESS_STATUS.getCode(), AppTipMsgEnum.SUCCESS.getText()).setData(objectMap).build();}

涉及的thirdGetUserInfoService类的代码如下:

@Service("thirdGetUserInfoService")
public class ThirdGetUserInfoServiceImpl implements ThirdGetUserInfoService {// 微信web方式获取用户信息@Overridepublic Map wxGetUserInfo(String code, String state) throws Exception {AssertException.isNull(code, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:code is empty,请重新登录!");AssertException.isNull(state, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:state is empty,请重新登录!");// 判断state是否合法String stateStr = CacheUtil.get(ThirdPartyLoginEnum.WeChatEnum.WeChatKFState.getCode() + state);AssertException.assertException(StringUtils.isEmpty(code) || StringUtils.isEmpty(state) || StringUtils.isBlank(stateStr), AppTipMsgEnum.PARAM_NOT_NULL.getCode(), "非法操作,请重新登录!");// 用户授权后的code换取tokenMap t_token = WeChatLoginUtil.getAccessToken(code, ThirdPartyLoginEnum.WeChatEnum.AppID.getCode(), ThirdPartyLoginEnum.WeChatEnum.AppSecret.getCode());// 判断是否成功获取到了tokenAssertException.isNullObject(t_token, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败,请重新登录!");AssertException.assertException(t_token.get("errcode") != null, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:" + t_token.get("errmsg") + ",请重新登录!");AssertException.assertException(StringUtils.isEmpty((String) t_token.get("access_token")) || StringUtils.isEmpty((String) t_token.get("openid")), AppTipMsgEnum.PARAM_NOT_NULL.getCode(),"access_token拉取失败,请重新登录!");// 刷新accesstokenMap refreshToken = WeChatLoginUtil.refreshToken(ThirdPartyLoginEnum.WeChatEnum.AppID.getCode(), (String) t_token.get("refresh_token"));AssertException.isNullObject(refreshToken, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败,请重新登录!");AssertException.assertException(refreshToken.get("errcode") != null, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:" + refreshToken.get("errmsg") + ",请重新登录!");// 使用token交换获取用户信息String userInfo = WeChatLoginUtil.getUserInfo(refreshToken);return JsonUtil.fromJson(userInfo, Map.class);}// 微信公众号方式获取用户信息@Overridepublic Map wxPublicGetUserInfo(String code, String state) throws Exception {AssertException.isNull(code, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:code is empty,请重新登录!");AssertException.isNull(state, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:state is empty,请重新登录!");// 判断state是否合法String stateStr = CacheUtil.get(ThirdPartyLoginEnum.PublicWeChatEnum.WeChatKFState.getCode() + state);AssertException.assertException(StringUtils.isEmpty(code) || StringUtils.isEmpty(state) || StringUtils.isBlank(stateStr), AppTipMsgEnum.PARAM_NOT_NULL.getCode(), "非法操作,请重新登录!");// 用户授权后的code换取tokenMap t_token = WeChatLoginUtil.getAccessTokenByPublic(code, ThirdPartyLoginEnum.PublicWeChatEnum.AppID.getCode(), ThirdPartyLoginEnum.PublicWeChatEnum.AppSecret.getCode());// 判断是否成功获取到了tokenAssertException.isNullObject(t_token, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败,请重新登录!");AssertException.assertException(t_token.get("errcode") != null, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:" + t_token.get("errmsg") + ",请重新登录!");AssertException.assertException(StringUtils.isEmpty((String) t_token.get("access_token")) || StringUtils.isEmpty((String) t_token.get("openid")), AppTipMsgEnum.PARAM_NOT_NULL.getCode(),"access_token拉取失败,请重新登录!");// 刷新accesstokenMap refreshToken = WeChatLoginUtil.refreshTokenByPublic(ThirdPartyLoginEnum.PublicWeChatEnum.AppID.getCode(), (String) t_token.get("refresh_token"));AssertException.isNullObject(refreshToken, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败,请重新登录!");AssertException.assertException(refreshToken.get("errcode") != null, AppTipMsgEnum.LOGIN_FAIL.getCode(), "登录失败:" + refreshToken.get("errmsg") + ",请重新登录!");// 使用token交换获取用户信息String userInfo = WeChatLoginUtil.getUserInfoByPublic(refreshToken);return JsonUtil.fromJson(userInfo, Map.class);}
}

至此代码就算完成了,不足之处欢迎指教
由于框架用不明白,不想去理解,感觉配置太麻烦了,花那个时间去研究框架,我都写完了。

公众平台的登录请看另一篇:公众平台–扫描微信二维码,关注后自动登录

开放平台–扫描微信二维码登录相关推荐

  1. java微信二维码登录

    1.注册 微信开放平台:https://open.weixin.qq.com 2.邮箱激活 3.完善开发者资料 4.开发者资质认证 准备营业执照,1-2个工作日审批.300元 5.创建网站应用 提交审 ...

  2. 【微信开放平台】微信第三方扫码登录(亲测可用)

    开放平台需要企业认证才能注册,正好这次公司提供了一个账号,调通以后,就顺便写一篇博客吧. 公众平台与开放平台的区别 微信开放平台 主要面对移动应用/网站应用开发者,为其提供微信登录.分享.支付等相关权 ...

  3. 微信二维码登录实现思路

    在电脑上使用微信时,你可能已经发现微信不提供传统的账号密码登陆,取而代之的是通过扫描二维码进行登陆.今天就要研究下次登陆方式微信时如何实现的? 1.每次用户打开PC端登陆请求,系统返回一个唯一的uid ...

  4. 手机扫描网页二维码登录实现原理分析

    阅读本文大概需要 5 分钟. 相信我们每个人经历过这样的场景: 手机扫码登录 PC 版微信,通过二维码扫描登录,笔记本上的微信就和手机微信同步登录了.这样免去输入繁琐的账号密码,确定方便得很. 对于这 ...

  5. 微信小程序 扫描微信二维码 传递参数授权

    首先 先用微信小程序扫一扫 看二维码的参数是什么 然后 扫描二维码的参数是  scene=u_127 这个就是小程序二维码的参数 能够在 页面里拿到 扫描微信小程序授权的结果 可以进行编译 能够在on ...

  6. 最近在用uniapp做一款app软件,兼容在小程序中可以通过扫描微信二维码获取参数

    功能描述 该接口用于获取小程序码,适用于需要的码数量极多的业务场景.通过该接口生成的小程序码,永久有效,数量暂无限. 注意事项 如果调用成功,会直接返回图片二进制内容,如果请求失败,会返回 JSON ...

  7. C# winform 实现微信二维码登录、第三方登录(已实现、附源码)

    前言 应上级要求,在项目登录的时候实现第三方登录.很荣幸我接到了这个任务,但是我之前完全都没接触到.开发周期是三天,对于我们这种小白完全是从零开始.最后成功的实现这个功能固然重要,但是这个探索的过程才 ...

  8. Android安卓开发集成微信第三方扫描二维码登录-超级无敌具详细

    Android安卓开发中集成微信二维码登录的步骤: 写在前面的: 该教程使用AS作为演示,使用ecplise请参照微信官方文档下载相应jar等所需参考文档和资源.在最后,我会附上这个Activity的 ...

  9. Day212.OAuth2、微信二维码登入注册功能、用户登录信息前后端供、讲师列表前后端 -谷粒学院

    谷粒学院 OAuth2的使用场景 一.OAuth2解决什么问题 1.OAuth2提出的背景 照片拥有者想要在云冲印服务上打印照片,云冲印服务需要访问云存储服务上的资源 2.图例 资源拥有者:照片拥有者 ...

最新文章

  1. PHP中self和static的区别,php中self与static的区别
  2. 新浪微博瘫痪,有人开心有人哭
  3. C语言中的位运算符主要有哪些?逻辑右移与算术右移的区别?
  4. wxWidgets:使用 Open Watcom 编译的 WxWidgets 的 DLL 版本
  5. 布式缓存系统Memcached简介与实践
  6. php apache配置测试端口,详解安装配置Windows版apache服务器及压力测试
  7. 全连接条件随机场_深圳机场在国内机场中率先推出全流程“行李门到门”服务...
  8. 【Go学习笔记2】go语言中的基本数据类型和包的介绍(一)
  9. axios 与 Vuex的使用
  10. 云计算的思想领袖:与橡树岭国家实验室云计算研究员Rob Gillen的谈话
  11. python进阶之装饰器之5把装饰器作用到类和静态方法上
  12. 几种常见单例的写法和问题
  13. 数美黑产研究院|揭秘黑产非法盗爬访问与非法占座“抢票”行径
  14. usc2_今天发布:与USC合作的新游戏设计课程
  15. android 测试开发概述
  16. 智能优化算法:分类、特点和未来
  17. can和could的用法_can和could的区别和用法
  18. 五线谱上的Linux旋律
  19. csdn邻家割草_如何维护割草机,使其永远持续(几乎)
  20. Unity倒计时动画

热门文章

  1. 转特权:NIOS2下的SDHC调试
  2. 连平县新视界-连平2018年公开招聘教职员66人
  3. C++知识点(持续更新)
  4. DHTML动态样式的作用
  5. 关于我为什么跨考计算机研究生以及对未来的思考
  6. 英文字母间距非常大的问题
  7. 《刻意练习》读书心得 驳斥1万小时定律、有目的的练习、自我实现的预言、走出舒适区
  8. 深度学习环境安装之显卡驱动程序安装
  9. ActiveMQ学习笔记(二十三)Comsumer高级特性2
  10. 苏州VS上海:城市化的二个阶段