feat(auth): 添加微信登录功能- 新增微信登录相关配置和接口

- 实现微信登录逻辑,包括获取 openid 和 session_key- 更新安全配置,允许微信登录请求通过
- 添加必要的依赖和数据传输对象
This commit is contained in:
FalingCliff 2025-05-24 23:49:51 +08:00
parent 1e4d0abd3a
commit ae619cc964
7 changed files with 215 additions and 8 deletions

View File

@ -0,0 +1,19 @@
package com.example.admin_server.controller.client;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author FallingCliff
* @since 2025-05-24
*/
@RestController
@RequestMapping("/api/client/customer")
public class CustomerController {
}

View File

@ -1,9 +1,13 @@
package com.example.admin_server.controller.client; package com.example.admin_server.controller.client;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.admin_server.common.Result; import com.example.admin_server.common.Result;
import com.example.admin_server.config.WxConfig; import com.example.admin_server.config.WxConfig;
import com.example.admin_server.model.dto.WxLoginDTO; import com.example.admin_server.model.dto.WxLoginDTO;
import com.example.admin_server.model.entity.Customer;
import com.example.admin_server.service.ICustomerService;
import com.example.admin_server.utils.JwtUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -13,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -23,6 +28,8 @@ import java.util.Map;
public class WxLoginController { public class WxLoginController {
private final WxConfig wxConfig; private final WxConfig wxConfig;
private final ICustomerService iCustomerService;
private final JwtUtil jwtUtil;
@PostMapping("/login") @PostMapping("/login")
@ApiOperation(value = "微信登录") @ApiOperation(value = "微信登录")
@ -32,32 +39,58 @@ public class WxLoginController {
return Result.fail("code 参数不能为空"); return Result.fail("code 参数不能为空");
} }
// 构造请求微信的 URL // 请求微信接口
String url = wxConfig.getJscode2sessionUrl() String url = wxConfig.getJscode2sessionUrl()
+ "?appid=" + wxConfig.getAppid() + "?appid=" + wxConfig.getAppid()
+ "&secret=" + wxConfig.getSecret() + "&secret=" + wxConfig.getSecret()
+ "&js_code=" + code + "&js_code=" + code
+ "&grant_type=authorization_code"; + "&grant_type=authorization_code";
// 请求微信服务器
RestTemplate restTemplate = new RestTemplate(); RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class); String response = restTemplate.getForObject(url, String.class);
// 解析微信响应
JSONObject jsonObject = JSONObject.parseObject(response); JSONObject jsonObject = JSONObject.parseObject(response);
System.out.println(jsonObject);
String openid = jsonObject.getString("openid"); String openid = jsonObject.getString("openid");
String sessionKey = jsonObject.getString("session_key"); String sessionKey = jsonObject.getString("session_key");
String unionid = jsonObject.getString("unionid");
if (openid == null) { if (openid == null) {
String errMsg = jsonObject.getString("errmsg"); return Result.fail("微信登录失败: " + jsonObject.getString("errmsg"));
return Result.fail("微信登录失败: " + errMsg);
} }
// TODO: 你可以在这里用 openid 查数据库创建或更新用户生成 JWT // 查找用户是否已存在
Customer customer = iCustomerService.getOne(new QueryWrapper<Customer>().eq("openid", openid));
if (customer == null) {
// 创建新用户
customer = new Customer()
.setOpenid(openid)
.setSessionKey(sessionKey)
.setUnionid(unionid)
.setNickname("微信用户") // 默认昵称可后续完善
.setAvatarUrl(null)
.setCreateTime(LocalDateTime.now())
.setUpdateTime(LocalDateTime.now());
iCustomerService.save(customer);
} else {
// 更新 session_key update_time
customer.setSessionKey(sessionKey);
customer.setUpdateTime(LocalDateTime.now());
iCustomerService.updateById(customer);
}
Map<String, Object> claims = new HashMap<>();
claims.put("id", customer.getId());
claims.put("username", customer.getUsername());
claims.put("sessionKey", customer.getSessionKey());
claims.put("openid", customer.getOpenid());
String token = jwtUtil.generateToken(claims);
Map<String, Object> resultData = new HashMap<>(); Map<String, Object> resultData = new HashMap<>();
resultData.put("token", token);
resultData.put("openid", openid); resultData.put("openid", openid);
resultData.put("token", "mock-token-" + openid); // 后期你可以用 JWT 替换这里 resultData.put("nickname", customer.getNickname());
resultData.put("avatar", customer.getAvatarUrl());
return Result.ok("登录成功", resultData); return Result.ok("登录成功", resultData);
} }

View File

@ -0,0 +1,16 @@
package com.example.admin_server.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.admin_server.model.entity.Customer;
/**
* <p>
* Mapper 接口
* </p>
*
* @author FallingCliff
* @since 2025-05-24
*/
public interface CustomerMapper extends BaseMapper<Customer> {
}

View File

@ -0,0 +1,82 @@
package com.example.admin_server.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* <p>
*
* </p>
*
* @author FallingCliff
* @since 2025-05-24
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("customer")
@ApiModel(value="Customer对象", description="客户表")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "微信openid")
@TableField("openid")
private String openid;
@ApiModelProperty(value = "微信会话密钥(可选存储)")
@TableField("session_key")
private String sessionKey;
@ApiModelProperty(value = "微信unionid如果获取到")
@TableField("unionid")
private String unionid;
@ApiModelProperty(value = "用户名")
@TableField("username")
private String username;
@ApiModelProperty(value = "密码")
@TableField("password")
private String password;
@ApiModelProperty(value = "用户昵称")
@TableField("nickname")
private String nickname;
@ApiModelProperty(value = "头像URL")
@TableField("avatar_url")
private String avatarUrl;
@ApiModelProperty(value = "邮箱")
@TableField("email")
private String email;
@ApiModelProperty(value = "手机号(后续绑定时)")
@TableField("phone")
private String phone;
@ApiModelProperty(value = "创建时间")
@TableField("create_time")
private LocalDateTime createTime;
@ApiModelProperty(value = "更新时间")
@TableField("update_time")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,16 @@
package com.example.admin_server.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.admin_server.model.entity.Customer;
/**
* <p>
* 服务类
* </p>
*
* @author FallingCliff
* @since 2025-05-24
*/
public interface ICustomerService extends IService<Customer> {
}

View File

@ -0,0 +1,20 @@
package com.example.admin_server.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.admin_server.mapper.CustomerMapper;
import com.example.admin_server.model.entity.Customer;
import com.example.admin_server.service.ICustomerService;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author FallingCliff
* @since 2025-05-24
*/
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements ICustomerService {
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.admin_server.mapper.CustomerMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.example.admin_server.model.entity.Customer">
<id column="id" property="id" />
<result column="openid" property="openid" />
<result column="session_key" property="sessionKey" />
<result column="unionid" property="unionid" />
<result column="username" property="username" />
<result column="password" property="password" />
<result column="nickname" property="nickname" />
<result column="avatar_url" property="avatarUrl" />
<result column="email" property="email" />
<result column="phone" property="phone" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
</resultMap>
</mapper>