💡 一则也许对你有用的小广告 🏆

欢迎飞飞程序员   ,你将获得:专属的实战项目(已更新的所有会员标识的项目都能学习) / 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. 安全注意事项

  1. State参数:必须使用随机字符串防止CSRF攻击
  2. AppSecret保护:不要在前端暴露AppSecret
  3. Token存储:access_token不要长期存储在前端
  4. HTTPS:生产环境必须使用HTTPS
  5. 权限控制:根据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使用流程确保了微信登录的安全性和可靠性,在实际开发中需要根据具体业务需求进行适当的调整和优化。

已是第一篇
下一篇 java版本的 ARM64 Compressed Archive 和 x64 Compressed Archive 的区别

全部评论(0)

头像
😃 😁 😅 😂 😍 😜 😝 🤑 🥵 🥰 😙 😎 😵 😭 😱 😖 🥳 👽 🙈 🤡 😤 💣 💯 💢 ❤️ 👍 👏 👋 👌 🤏 🙏
还没有任何评论哟~