{{wikiTitle}}
微信授权登录
目录:
一、功能概述
本模块实现微信多端授权登录(公众号、小程序、APP);
核心流程包括:OAuth2授权 → 用户身份识别 → 登录/注册分流 → 分销关系绑定 → Token签发。
以下是跨端登录的核心逻辑说明及扩展指导。
二、核心流程对比
| 端类型 | 授权方式 | 用户信息获取 | 注册信息存储 | 登录类型常量 |
|---|---|---|---|---|
| 公众号 | code换取openid | 调用getSnsUserInfo | Redis缓存待绑定数据 | THIRD_LOGIN_TOKEN_TYPE_PUBLIC |
| 小程序 | wx.login获取临时code | 前端传昵称/头像 | 需前端补全信息 | THIRD_LOGIN_TOKEN_TYPE_PROGRAM |
| APP(iOS/Android) | 客户端SDK授权返回openid | 客户端传递完整用户资料 | 直接携带资料缓存 | THIRD_LOGIN_TOKEN_TYPE_IOS_WX / ANDROID_WX |
三、关键代码说明
1.公共逻辑(所有端)
用户存在性检查
// 根据openid和类型查询绑定关系
UserToken userToken = userTokenService.getByOpenidAndType(openid, loginType);
if (userToken != null) {
// 登录逻辑:更新最后登录时间、处理分销关系
user.setLastLoginTime(now);
transactionTemplate.execute(...); // ⚠️ 注意事务边界
} else {
// 注册逻辑:缓存用户信息到Redis(key=MD5(openid))
redisUtil.set(key, JSON.toJSONString(request), 120L, TimeUnit.MINUTES);
}
统一规则:
Redis键设计:MD5(openid)避免明文暴露;
注册数据有效期:固定120分钟(可配置化建议见下文)。
2. 公众号登录 (weChatAuthorizeLogin)
1.OAuth2授权流程
// 步骤1: 通过code获取access_token和openid
WeChatOauthToken oauthToken = wechatNewService.getOauth2AccessToken(code);
// 步骤2: 用access_token拉取用户详细信息
WeChatAuthorizeLoginUserInfoVo userInfo =
wechatNewService.getSnsUserInfo(oauthToken.getAccessToken(), oauthToken.getOpenId());
依赖服务:
wechatNewService需实现微信API调用(如/sns/oauth2/access_token、/sns/userinfo);
错误处理:需捕获微信返回的errcode(如40029无效code)。
2.分销绑定逻辑
if (checkBingSpread(user, spreadUid, "old")) {
user.setSpreadUid(spreadUid);
userService.updateSpreadCountByUid(spreadUid, "add");
}
/**
* 检测能否绑定关系
*
* @param user 当前用户
* @param spreadUid 推广员Uid
* @param type 用户类型:new-新用户,old—老用户
* @return Boolean
* 1.判断分销功能是否启用
* 2.判断分销模式
* 3.根据不同的分销模式校验
* 4.指定分销,只有分销员才可以分销,需要spreadUid是推广员才可以绑定
* 5.人人分销,可以直接绑定
* *推广关系绑定,下级不能绑定自己的上级为下级,A->B->A(❌)
*/
public Boolean checkBingSpread(User user, Integer spreadUid, String type) {
if (ObjectUtil.isNull(spreadUid)) {
return false;
}
if (spreadUid <= 0 || user.getSpreadUid() > 0) {
return false;
}
if (ObjectUtil.isNotNull(user.getUid()) && user.getUid().equals(spreadUid)) {
return false;
}
// 判断分销功能是否启用
String isOpen = systemConfigService.getValueByKey(Constants.CONFIG_KEY_STORE_BROKERAGE_IS_OPEN);
if (StrUtil.isBlank(isOpen) || isOpen.equals("0")) {
return false;
}
if (type.equals("old")) {
// 判断分销关系绑定类型(所有、新用户)
String bindType = systemConfigService.getValueByKey(Constants.CONFIG_KEY_DISTRIBUTION_TYPE);
if (StrUtil.isBlank(bindType) || bindType.equals("1")) {
return false;
}
if (user.getSpreadUid().equals(spreadUid)) {
return false;
}
}
// 查询推广员
User spreadUser = getById(spreadUid);
if (ObjectUtil.isNull(spreadUser) || !spreadUser.getStatus()) {
return false;
}
// 指定分销不是推广员不绑定
if (!spreadUser.getIsPromoter()) {
return false;
}
// 下级不能绑定自己的上级为自己的下级
if (ObjectUtil.isNotNull(user.getUid()) && spreadUser.getSpreadUid().equals(user.getUid())) {
return false;
}
return true;
}
3. 小程序登录 (weChatAuthorizeProgramLogin)
1.前端数据依赖
// 必须参数校验
if (StrUtil.isBlank(request.getNickName()) && ...) {
loginResponse.setType("start"); // 要求前端补全信息
return loginResponse;
}
设计约束:
小程序首次登录需前端提交nickName、avatar等(微信静默授权不返回这些信息);
2.SessionKey管理
// 通过code获取session_key和openid(内部实现)
WeChatMiniAuthorizeVo response = wechatNewService.miniAuthCode(code);
依赖服务:
wechatNewService需实现微信API调用(/sns/jscode2session)
通过code、appId、appSecret 认证获取session_key和openid
4. APP登录 (appLogin)
1.客户端参数直传
// 直接从请求体获取用户资料
registerThirdUserRequest.setOpenId(request.getOpenId());
registerThirdUserRequest.setAvatar(request.getAvatarUrl());
registerThirdUserRequest.setSex(request.getGender());
2.多平台区分
if (request.getType().equals(Constants.USER_LOGIN_TYPE_IOS_WX)) {
userToken = userTokenService.getByOpenidAndType(openid, TYPE_IOS);
}
评论({{cateWiki.comment_num}})
{{commentWhere.order ? '评论从旧到新':'评论从新到旧'}}
{{cateWiki.page_view_num}}人看过该文档
评论(0)
{{commentWhere.order ? '评论从旧到新':'评论从新到旧'}}
1599人看过该文档
{{item.user ? item.user.nickname : ''}}
(自评)
{{item.content}}
{{item.create_time}}
删除
搜索结果
为您找到{{wikiCount}}条结果
{{item.page_view_num}}
{{item.like ? item.like.like_num : 0}}
{{item.comment ? item.comment.comment_num : 0}}
位置:
{{path.name}}
{{(i+1) == item.catalogue.path_data.length ? '':'/'}}