💡 一则也许对你有用的小广告 🏆
欢迎飞飞程序员 ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 1v1 提问 / Java 学习路线 / PHP 学习路线 / 学习打卡 / 社群讨论
- 正在进行中的项目:《FFBlog知识付费博客项目》 正在持续更新中,基于 Spring Boot 3.x + JDK 21...,[**点击查看**] ;
- 《从零开发:FFBlog知识付费博客项目(全栈开发)》 演示链接: https://ffblog.ffcxy.com/ ;
截止目前, 飞飞 正在疯狂爆肝实战项目,后续还会上新更多项目,目标是将所学知识开发成项目并且分享给大家,如知识付费系统, Ai系统, CMS系统,在线商城系统,等等 ,欢迎点击围观
1. 微信登录API概览
微信登录主要涉及以下4个核心API:
| API | 作用 | 请求方式 |
| 授权页面URL | 引导用户跳转到微信授权页面 | GET |
| 通过code获取access_token | 使用授权码获取访问令牌 | GET |
| 获取用户信息 | 使用access_token获取用户基本信息 | GET |
| 刷新access_token | 刷新访问令牌的有效期 | GET |
2. 各个API详细说明
2.1 授权页面URL
作用:生成微信授权页面的URL,引导用户进行授权
API地址:
https://open.weixin.qq.com/connect/qrconnect
参数说明:
public class WeChatAuthParams {
private String appid; // 应用唯一标识
private String redirect_uri; // 授权后重定向的回调链接地址
private String response_type; // 返回类型,固定为"code"
private String scope; // 应用授权作用域
private String state; // 防CSRF攻击的随机参数
}
参数详解:
appid:微信开放平台应用的AppID
redirect_uri:必须经过URL编码,且域名必须与微信开放平台配置的一致
scope:
snsapi_login:网站应用微信登录
snsapi_userinfo:获取用户个人信息
state:推荐使用UUID,用于防止CSRF攻击
示例URL:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect
2.2 通过code获取access_token
作用:使用授权临时票据(code)换取调用凭证(access_token)
API地址:
https://api.weixin.qq.com/sns/oauth2/access_token
请求参数:
public class AccessTokenRequest {
private String appid; // 应用唯一标识
private String secret; // 应用密钥AppSecret
private String code; // 授权码
private String grant_type; // 授权类型,固定为"authorization_code"
}
响应数据:
{
"access_token": "ACCESS_TOKEN",
"expires_in": 7200,
"refresh_token": "REFRESH_TOKEN",
"openid": "OPENID",
"scope": "SCOPE",
"unionid": "UNIONID"
}
字段说明:
access_token:接口调用凭证,有效期2小时
expires_in:access_token接口调用凭证超时时间,单位(秒)
refresh_token:用户刷新access_token
openid:授权用户唯一标识
scope:用户授权的作用域
unionid:当且仅当该网站应用已获得该用户的userinfo授权时才会出现
2.3 获取用户信息
作用:获取授权用户的个人信息
API地址:
https://api.weixin.qq.com/sns/userinfo
请求参数:
public class UserInfoRequest {
private String access_token; // 调用凭证
private String openid; // 普通用户的标识,对当前开发者帐号唯一
private String lang; // 返回国家地区语言版本,zh_CN 简体
}
响应数据:
{
"openid": "OPENID",
"nickname": "NICKNAME",
"sex": 1,
"province": "PROVINCE",
"city": "CITY",
"country": "COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege": ["PRIVILEGE1", "PRIVILEGE2"],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
字段说明:
openid:普通用户的标识,对当前开发者帐号唯一
nickname:用户昵称
sex:用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province:用户个人资料填写的省份
city:普通用户个人资料填写的城市
country:国家,如中国为CN
headimgurl:用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege:用户特权信息,json数组,如微信沃卡用户为(chinaunicom)
unionid:用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的
2.4 刷新access_token
作用:由于access_token有效期较短,refresh_token拥有较长的有效期,可用于刷新access_token
API地址:
https://api.weixin.qq.com/sns/oauth2/refresh_token
请求参数:
public class RefreshTokenRequest {
private String appid; // 应用唯一标识
private String grant_type; // 填refresh_token
private String refresh_token; // 填写通过access_token获取到的refresh_token参数
}
响应数据:与获取access_token接口返回相同
3. API使用完整流程
3.1 时序图
sequenceDiagram
participant User as 用户
participant Front as 前端
participant Back as 后端
participant WeChat as 微信服务器
User->>Front: 点击微信登录
Front->>Back: 请求微信登录URL
Back->>Front: 返回微信授权URL
Front->>WeChat: 跳转到微信授权页面
User->>WeChat: 在微信页面授权
WeChat->>Front: 重定向到回调URL(带code和state)
Front->>Back: 发送code和state
Back->>WeChat: 使用code请求access_token
WeChat->>Back: 返回access_token和openid
Back->>WeChat: 使用access_token请求用户信息
WeChat->>Back: 返回用户信息
Back->>Back: 处理用户登录/注册
Back->>Front: 返回登录结果和token
Front->>User: 登录成功
3.2 详细步骤
步骤1:生成授权URL
public String generateWeChatAuthUrl(String state) {
return "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=" + appId +
"&redirect_uri=" + URLEncoder.encode(redirectUri, "UTF-8") +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=" + state +
"#wechat_redirect";
}
步骤2:处理微信回调
public LoginResult handleWeChatCallback(String code, String state) {
// 1. 验证state参数
if (!stateService.validateState(state)) {
throw new WeChatAuthException("Invalid state parameter");
}
// 2. 获取access_token
WeChatAccessToken accessToken = getAccessToken(code);
// 3. 获取用户信息
WeChatUserInfo userInfo = getUserInfo(accessToken.getAccessToken(),
accessToken.getOpenid());
// 4. 处理业务逻辑
return processLogin(userInfo);
}
步骤3:获取access_token实现
private WeChatAccessToken getAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=" + appId +
"&secret=" + appSecret +
"&code=" + code +
"&grant_type=authorization_code";
String response = httpClient.get(url);
WeChatAccessToken token = jsonUtil.parseObject(response, WeChatAccessToken.class);
if (token.getErrcode() != null) {
throw new WeChatAuthException("获取access_token失败: " + token.getErrmsg());
}
return token;
}
步骤4:获取用户信息实现
private WeChatUserInfo getUserInfo(String accessToken, String openId) {
String url = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=" + accessToken +
"&openid=" + openId;
String response = httpClient.get(url);
WeChatUserInfo userInfo = jsonUtil.parseObject(response, WeChatUserInfo.class);
if (userInfo.getErrcode() != null) {
throw new WeChatAuthException("获取用户信息失败: " + userInfo.getErrmsg());
}
return userInfo;
}
4. 错误处理
4.1 常见错误码
| 错误码 | 说明 | 解决方案 |
| 40029 | code无效 | 检查code是否已使用或过期 |
| 40163 | code已被使用 | code只能使用一次,需要重新授权 |
| 41008 | 缺少code参数 | 检查回调参数 |
| 42001 | access_token超时 | 使用refresh_token刷新或重新授权 |
| 40003 | 非法的openid | 检查openid是否正确 |
4.2 错误响应格式
{
"errcode": 40029,
"errmsg": "invalid code"
}
5. 安全注意事项
- State参数:必须使用随机字符串防止CSRF攻击
- AppSecret保护:不要在前端暴露AppSecret
- Token存储:access_token不要长期存储在前端
- HTTPS:生产环境必须使用HTTPS
- 权限控制:根据scope合理申请用户权限
6. 完整代码示例
@Service
public class WeChatLoginService {
public LoginResult weChatLogin(String code, String state) {
// 1. 验证state
validateState(state);
// 2. 获取access_token
AccessTokenResult tokenResult = getAccessToken(code);
// 3. 获取用户信息
UserInfoResult userInfo = getUserInfo(tokenResult.getAccessToken(),
tokenResult.getOpenid());
// 4. 业务处理
return processLogin(userInfo);
}
private void validateState(String state) {
// 从Redis或Session中验证state
String storedState = redisTemplate.opsForValue().get("wechat_state:" + state);
if (storedState == null) {
throw new WeChatAuthException("Invalid state parameter");
}
// 使用后立即删除
redisTemplate.delete("wechat_state:" + state);
}
}
这个完整的API使用流程确保了微信登录的安全性和可靠性,在实际开发中需要根据具体业务需求进行适当的调整和优化。