在Spring Boot中对接微信公众号以获取用户头像和昵称,主要涉及微信OAuth2.0网页授权流程。以下是详细步骤和代码示例:
1. 准备工作
- 注册微信公众号(服务号)并完成开发者资质认证
- 配置公众号网页授权域名(在公众号后台设置)
- 获取AppID和AppSecret
2. 配置application.properties
ini
wx.mp.appId=你的公众号AppID
wx.mp.appSecret=你的公众号AppSecret
wx.mp.callbackUrl=你的回调地址
3. 创建配置类
kotlin
@Configuration
public class WeChatConfig {
@Value("${wx.mp.appId}")
private String appId;
@Value("${wx.mp.appSecret}")
private String appSecret;
@Value("${wx.mp.callbackUrl}")
private String callbackUrl;
// 获取网页授权access_token的URL
public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
// 获取用户信息的URL
public static final String USER_INFO_URL = "https://api.weixin.qq.com/sns/userinfo";
}
4. 授权流程实现
步骤1:生成授权URL
kotlin
@RestController
@RequestMapping("/wechat")
public class WeChatController {
@Autowired
private WeChatConfig weChatConfig;
@GetMapping("/auth")
public String auth() throws UnsupportedEncodingException {
String redirectUri = URLEncoder.encode(weChatConfig.getCallbackUrl(), "UTF-8");
return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?" +
"appid=" + weChatConfig.getAppId() +
"&redirect_uri=" + redirectUri +
"&response_type=code" +
"&scope=snsapi_userinfo" + // 需要获取用户信息时使用snsapi_userinfo
"&state=STATE#wechat_redirect";
}
}
步骤2:处理回调(获取code)
typescript
@GetMapping("/callback")
public String callback(@RequestParam("code") String code,
@RequestParam(value = "state", required = false) String state) {
// 1. 使用code获取access_token和openid
Map<String, String> accessTokenMap = getAccessToken(code);
// 2. 使用access_token和openid获取用户信息
Map<String, Object> userInfo = getUserInfo(accessTokenMap.get("access_token"),
accessTokenMap.get("openid"));
// 处理用户信息(示例返回)
return "用户信息:" + userInfo.toString();
}
private Map<String, String> getAccessToken(String code) {
String url = WeChatConfig.ACCESS_TOKEN_URL +
"?appid=" + weChatConfig.getAppId() +
"&secret=" + weChatConfig.getAppSecret() +
"&code=" + code +
"&grant_type=authorization_code";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
return JSON.parseObject(response, Map.class);
}
private Map<String, Object> getUserInfo(String accessToken, String openid) {
String url = WeChatConfig.USER_INFO_URL +
"?access_token=" + accessToken +
"&openid=" + openid +
"&lang=zh_CN";
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
return JSON.parseObject(response, Map.class);
}
5. 用户信息响应示例
成功响应示例:
json
{
"openid": "OPENID",
"nickname": "NICKNAME",
"sex": 1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege": ["PRIVILEGE1", "PRIVILEGE2"]
}
6. 注意事项
- 域名备案:回调域名必须与公众号后台配置的网页授权域名一致
- URL编码:redirect_uri需要URLEncode处理
- 安全验证:实际生产环境应验证state参数防止CSRF攻击
- 异常处理:需要处理微信接口返回的错误码(如40029无效code)
- HTTPS:正式环境需要使用HTTPS协议
- 存储用户信息:建议将获取的用户信息存储到数据库或session中
7. 常见错误处理
- 40163:code已被使用,确保code只能使用一次
- 40029:无效code,检查code是否正确且未过期
- 48001:未授权该API,检查公众号权限设置
完整实现时建议:
- 添加异常处理机制
- 使用HTTP客户端工具类(如OkHttp)
- 添加日志记录
- 使用Redis缓存access_token(注意网页授权的access_token与普通access_token不同)
以上代码示例展示了基本的微信OAuth2.0授权流程,实际应用中需要根据具体业务需求进行扩展和完善。