本文目录导读:

我来为你提供一个完整的Java微信登录案例,这个案例会包含服务端的主要逻辑代码。
整体流程
- 前端获取微信授权code
- 后端用code换取access_token和openid
- 获取用户信息
- 生成业务token返回给前端
后端Java实现
添加依赖(pom.xml)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
微信配置类
@Component
@ConfigurationProperties(prefix = "wechat")
@Data
public class WechatConfig {
// 微信小程序appId
private String appId;
// 微信小程序secret
private String secret;
// 微信登录凭证校验接口
private String code2SessionUrl = "https://api.weixin.qq.com/sns/jscode2session";
// 获取access_token接口
private String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
// 获取用户信息接口
private String userInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info";
}
application.yml配置
wechat: app-id: your_appid secret: your_secret
微信登录服务类
@Service
@Slf4j
public class WechatLoginService {
@Autowired
private WechatConfig wechatConfig;
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 微信登录主方法
* @param code 前端获取的临时code
* @return 登录结果
*/
public LoginResult login(String code) {
try {
// 1. 用code获取session_key和openid
WxSession session = getSessionKey(code);
if (session == null || session.getOpenid() == null) {
return LoginResult.fail("获取微信session失败");
}
// 2. 查询或创建用户
User user = findOrCreateUser(session.getOpenid());
// 3. 生成业务token
String token = generateToken(user);
// 4. 返回登录结果
return LoginResult.success(token, user);
} catch (Exception e) {
log.error("微信登录失败", e);
return LoginResult.fail("登录失败");
}
}
/**
* 通过code获取session
*/
private WxSession getSessionKey(String code) {
String url = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
wechatConfig.getCode2SessionUrl(),
wechatConfig.getAppId(),
wechatConfig.getSecret(),
code);
String result = HttpClientUtil.doGet(url);
WxSession session = JSON.parseObject(result, WxSession.class);
if (session.getErrcode() != null && session.getErrcode() != 0) {
log.error("微信登录失败: {}", result);
return null;
}
return session;
}
/**
* 获取微信用户信息(如需获取昵称、头像等)
*/
public WxUserInfo getWxUserInfo(String accessToken, String openid) {
String url = String.format("%s?access_token=%s&openid=%s&lang=zh_CN",
wechatConfig.getUserInfoUrl(),
accessToken,
openid);
String result = HttpClientUtil.doGet(url);
return JSON.parseObject(result, WxUserInfo.class);
}
/**
* 查询或创建用户
*/
private User findOrCreateUser(String openid) {
// 查询数据库,这里用伪代码表示
User user = userMapper.findByOpenid(openid);
if (user == null) {
// 创建新用户
user = new User();
user.setOpenid(openid);
user.setNickname("微信用户");
user.setCreateTime(new Date());
userMapper.insert(user);
}
return user;
}
/**
* 生成token
*/
private String generateToken(User user) {
// 使用JWT或UUID生成token
String token = UUID.randomUUID().toString().replace("-", "");
// 存储到redis,设置过期时间
redisTemplate.opsForValue().set(
"token:" + token,
JSON.toJSONString(user),
7, // 7天过期
TimeUnit.DAYS
);
return token;
}
}
用户实体类
@Data
public class User {
private Long id;
private String openid;
private String nickname;
private String avatar;
private Date createTime;
private Date updateTime;
}
微信会话对象
@Data
public class WxSession {
private String openid;
private String sessionKey;
private String unionid;
private Integer errcode;
private String errmsg;
}
用户信息对象
@Data
public class WxUserInfo {
private String openid;
private String nickname;
private Integer sex;
private String province;
private String city;
private String country;
private String headimgurl;
private String unionid;
}
登录结果封装
@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginResult {
private boolean success;
private String token;
private User user;
private String message;
public static LoginResult success(String token, User user) {
return new LoginResult(true, token, user, null);
}
public static LoginResult fail(String message) {
return new LoginResult(false, null, null, message);
}
}
HTTP工具类
@Component
public class HttpClientUtil {
public static String doGet(String url) {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
return EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
控制器
@RestController
@RequestMapping("/api/wechat")
public class WechatLoginController {
@Autowired
private WechatLoginService wechatLoginService;
/**
* 微信登录接口
*/
@PostMapping("/login")
public Result login(@RequestParam String code) {
LoginResult loginResult = wechatLoginService.login(code);
if (loginResult.isSuccess()) {
return Result.success(loginResult);
}
return Result.error(loginResult.getMessage());
}
/**
* 验证token是否有效
*/
@GetMapping("/verify")
public Result verifyToken(@RequestHeader("Authorization") String token) {
// 验证token逻辑
return Result.success();
}
}
前端调用示例(微信小程序)
// pages/login/login.js
Page({
data: {},
// 微信登录按钮点击事件
wechatLogin: function() {
wx.login({
success: (res) => {
if (res.code) {
// 调用后端接口
wx.request({
url: 'https://your-api.com/api/wechat/login',
method: 'POST',
data: {
code: res.code
},
success: (response) => {
if (response.data.success) {
// 存储token
wx.setStorageSync('token', response.data.data.token);
// 登录成功跳转
wx.navigateBack();
} else {
wx.showToast({
title: '登录失败',
icon: 'none'
});
}
}
});
}
}
});
}
});
注意事项
- code只能使用一次,每次登录都需要前端重新获取
- session_key 不应该传给前端,只在服务端使用
- 建议使用 HTTPS 协议保证数据传输安全
- token过期时间 根据业务需求设置
- 用户信息建议使用 缓存 减少数据库查询
这个案例提供了完整的微信登录后端实现,你可以根据实际业务需求进行调整和扩展。