feat(system): 优化微信登录和用户注册逻辑

- 新增微信小程序数据解密工具类 WxMiniProgramDecryptUtil
- 重构微信登录接口,支持两种方式获取手机号
- 优化用户注册逻辑,增加租户ID参数
- 更新相关实体类和参数类,以支持新的功能
This commit is contained in:
2025-09-03 18:25:45 +08:00
parent 5961fdbcb9
commit 61dab98a6d
15 changed files with 641 additions and 72 deletions

View File

@@ -63,7 +63,6 @@ public class MybatisPlusConfig {
public boolean ignoreTable(String tableName) {
return Arrays.asList(
"sys_tenant",
// "sys_user",
"sys_dictionary",
"sys_dictionary_data",
"sys_user_oauth",

View File

@@ -0,0 +1,105 @@
package com.gxwebsoft.common.core.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;
/**
* 微信小程序数据解密工具类
* 用于解密微信小程序的encryptedData数据
*
* @author WebSoft
*/
public class WxMiniProgramDecryptUtil {
/**
* 解密微信小程序数据
*
* @param encryptedData 加密的数据
* @param sessionKey 会话密钥
* @param iv 初始向量
* @return 解密后的JSON字符串
* @throws Exception 解密失败时抛出异常
*/
public static String decrypt(String encryptedData, String sessionKey, String iv) throws Exception {
// Base64解码
byte[] dataByte = Base64.decodeBase64(encryptedData);
byte[] keyByte = Base64.decodeBase64(sessionKey);
byte[] ivByte = Base64.decodeBase64(iv);
try {
// 如果密钥长度不够则补齐到32位
if (keyByte.length % 16 != 0) {
int groups = keyByte.length / 16 + (keyByte.length % 16 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 16];
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
keyByte = temp;
}
// 初始化
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivByte);
cipher.init(Cipher.DECRYPT_MODE, spec, paramSpec);
// 解密
byte[] resultByte = cipher.doFinal(dataByte);
if (null != resultByte && resultByte.length > 0) {
String result = new String(resultByte, StandardCharsets.UTF_8);
return result;
}
} catch (Exception e) {
throw new Exception("微信小程序数据解密失败", e);
}
return null;
}
/**
* 解密手机号信息
*
* @param encryptedData 加密的数据
* @param sessionKey 会话密钥
* @param iv 初始向量
* @return 手机号码解密失败返回null
*/
public static String decryptPhoneNumber(String encryptedData, String sessionKey, String iv) {
try {
String decryptedData = decrypt(encryptedData, sessionKey, iv);
if (decryptedData != null) {
JSONObject jsonObject = JSON.parseObject(decryptedData);
return jsonObject.getString("phoneNumber");
}
} catch (Exception e) {
System.err.println("解密手机号失败: " + e.getMessage());
e.printStackTrace();
}
return null;
}
/**
* 解密用户信息
*
* @param encryptedData 加密的数据
* @param sessionKey 会话密钥
* @param iv 初始向量
* @return 解密后的用户信息JSON对象解密失败返回null
*/
public static JSONObject decryptUserInfo(String encryptedData, String sessionKey, String iv) {
try {
String decryptedData = decrypt(encryptedData, sessionKey, iv);
if (decryptedData != null) {
return JSON.parseObject(decryptedData);
}
} catch (Exception e) {
System.err.println("解密用户信息失败: " + e.getMessage());
e.printStackTrace();
}
return null;
}
}

View File

@@ -1,5 +1,6 @@
package com.gxwebsoft.common.system.controller;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -11,6 +12,7 @@ import com.gxwebsoft.common.system.entity.Setting;
import com.gxwebsoft.common.system.entity.Tenant;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.param.SettingParam;
import com.gxwebsoft.common.system.param.SettingUpdateParam;
import com.gxwebsoft.common.system.service.SettingService;
import com.gxwebsoft.common.system.service.TenantService;
import io.swagger.annotations.Api;
@@ -76,7 +78,16 @@ public class SettingController extends BaseController {
@OperationLog
@ApiOperation("添加系统设置")
@PostMapping()
public ApiResult<?> save(@RequestBody Setting setting) {
public ApiResult<?> save(@RequestBody SettingUpdateParam settingParam) {
final User loginUser = getLoginUser();
if(loginUser == null){
return fail("请先登录");
}
// 转换为Setting对象
Setting setting = convertToSetting(settingParam);
setting.setTenantId(loginUser.getTenantId());
if (settingService.save(setting)) {
return success("添加成功");
}
@@ -87,11 +98,15 @@ public class SettingController extends BaseController {
@OperationLog
@ApiOperation("修改系统设置")
@PutMapping()
public ApiResult<?> update(@RequestBody Setting setting) {
public ApiResult<?> update(@RequestBody SettingUpdateParam settingParam) {
final User loginUser = getLoginUser();
if(loginUser == null){
return fail("请先登录");
}
// 转换为Setting对象
Setting setting = convertToSetting(settingParam);
setting.setTenantId(loginUser.getTenantId());
if (settingService.updateById(setting)) {
// 更新系统设置信息到缓存 key = ""
String key = setting.getSettingKey().concat(":").concat(loginUser.getTenantId().toString());
@@ -178,7 +193,7 @@ public class SettingController extends BaseController {
@ApiOperation("根据key更新系统设置")
@OperationLog
@PutMapping("/updateByKey")
public ApiResult<?> updateByKey(@RequestBody Setting setting) {
public ApiResult<?> updateByKey(@RequestBody SettingUpdateParam settingParam) {
final User loginUser = getLoginUser();
if(loginUser == null){
return fail("请先登录");
@@ -186,6 +201,11 @@ public class SettingController extends BaseController {
if(!loginUser.getIsSuperAdmin()){
return fail("权限不足");
}
// 转换为Setting对象
Setting setting = convertToSetting(settingParam);
setting.setTenantId(loginUser.getTenantId());
return success(settingService.updateByKey(setting));
}
@@ -193,7 +213,10 @@ public class SettingController extends BaseController {
@OperationLog
@ApiOperation("更新主题皮肤")
@PutMapping("/theme")
public ApiResult<?> theme(@RequestBody Setting setting) {
public ApiResult<?> theme(@RequestBody SettingUpdateParam settingParam) {
// 转换为Setting对象
Setting setting = convertToSetting(settingParam);
setting.setTenantId(getTenantId());
String key = "theme:".concat(getTenantId().toString());
// 新增
final Setting one = settingService.getOne(new LambdaQueryWrapper<Setting>().eq(Setting::getSettingKey, setting.getSettingKey()));
@@ -218,4 +241,156 @@ public class SettingController extends BaseController {
String key = "theme:".concat(getTenantId().toString());
return success("获取成功",redisUtil.get(key));
}
/**
* 将SettingUpdateParam转换为Setting对象
* 根据settingKey的不同将相应的字段组装成JSON格式的content
*/
private Setting convertToSetting(SettingUpdateParam param) {
Setting setting = new Setting();
setting.setSettingKey(param.getSettingKey());
setting.setSortNumber(param.getSortNumber());
setting.setComments(param.getComments());
setting.setTenantId(param.getTenantId());
// 如果直接提供了content则使用content
if (StrUtil.isNotBlank(param.getContent())) {
setting.setContent(param.getContent());
return setting;
}
// 根据settingKey构建相应的JSON content
JSONObject contentJson = new JSONObject();
switch (param.getSettingKey()) {
case "mp-weixin":
// 微信小程序配置
if (StrUtil.isNotBlank(param.getAppId())) {
contentJson.put("appId", param.getAppId());
}
if (StrUtil.isNotBlank(param.getAppSecret())) {
contentJson.put("appSecret", param.getAppSecret());
}
break;
case "payment":
// 支付配置
if (StrUtil.isNotBlank(param.getMchId())) {
contentJson.put("mchId", param.getMchId());
}
if (StrUtil.isNotBlank(param.getApiKey())) {
contentJson.put("apiKey", param.getApiKey());
}
if (StrUtil.isNotBlank(param.getWechatApiKey())) {
contentJson.put("wechatApiKey", param.getWechatApiKey());
}
if (StrUtil.isNotBlank(param.getMerchantSerialNumber())) {
contentJson.put("merchantSerialNumber", param.getMerchantSerialNumber());
}
if (StrUtil.isNotBlank(param.getApiclientCert())) {
contentJson.put("apiclientCert", param.getApiclientCert());
}
if (StrUtil.isNotBlank(param.getApiclientKey())) {
contentJson.put("apiclientKey", param.getApiclientKey());
}
break;
case "sms":
// 短信配置
if (StrUtil.isNotBlank(param.getAccessKeyId())) {
contentJson.put("accessKeyId", param.getAccessKeyId());
}
if (StrUtil.isNotBlank(param.getAccessKeySecret())) {
contentJson.put("accessKeySecret", param.getAccessKeySecret());
}
if (StrUtil.isNotBlank(param.getSignName())) {
contentJson.put("signName", param.getSignName());
}
if (StrUtil.isNotBlank(param.getTemplateCode())) {
contentJson.put("templateCode", param.getTemplateCode());
}
break;
case "wx-work":
// 企业微信配置
if (StrUtil.isNotBlank(param.getCorpId())) {
contentJson.put("corpId", param.getCorpId());
}
if (StrUtil.isNotBlank(param.getSecret())) {
contentJson.put("secret", param.getSecret());
}
break;
case "wx-official":
// 微信公众号配置
if (StrUtil.isNotBlank(param.getAppId())) {
contentJson.put("appId", param.getAppId());
}
if (StrUtil.isNotBlank(param.getAppSecret())) {
contentJson.put("appSecret", param.getAppSecret());
}
if (StrUtil.isNotBlank(param.getToken())) {
contentJson.put("token", param.getToken());
}
if (StrUtil.isNotBlank(param.getEncodingAESKey())) {
contentJson.put("encodingAESKey", param.getEncodingAESKey());
}
break;
case "setting":
// 基本设置
if (StrUtil.isNotBlank(param.getSiteName())) {
contentJson.put("siteName", param.getSiteName());
}
if (StrUtil.isNotBlank(param.getLogo())) {
contentJson.put("logo", param.getLogo());
}
if (StrUtil.isNotBlank(param.getDescription())) {
contentJson.put("description", param.getDescription());
}
if (StrUtil.isNotBlank(param.getKeywords())) {
contentJson.put("keywords", param.getKeywords());
}
break;
case "upload":
// 上传配置
if (StrUtil.isNotBlank(param.getBucketName())) {
contentJson.put("bucketName", param.getBucketName());
}
if (StrUtil.isNotBlank(param.getBucketDomain())) {
contentJson.put("bucketDomain", param.getBucketDomain());
}
if (StrUtil.isNotBlank(param.getBucketEndpoint())) {
contentJson.put("bucketEndpoint", param.getBucketEndpoint());
}
if (StrUtil.isNotBlank(param.getAccessKeyId())) {
contentJson.put("accessKeyId", param.getAccessKeyId());
}
if (StrUtil.isNotBlank(param.getAccessKeySecret())) {
contentJson.put("accessKeySecret", param.getAccessKeySecret());
}
break;
case "printer":
// 打印机配置
if (StrUtil.isNotBlank(param.getDeviceNo())) {
contentJson.put("deviceNo", param.getDeviceNo());
}
if (StrUtil.isNotBlank(param.getPrinterKey())) {
contentJson.put("printerKey", param.getPrinterKey());
}
break;
default:
// 处理其他配置或动态字段
if (param.getAdditionalProperties() != null) {
contentJson.putAll(param.getAdditionalProperties());
}
break;
}
setting.setContent(contentJson.toJSONString());
return setting;
}
}

View File

@@ -481,6 +481,7 @@ public class UserController extends BaseController {
u.setPoints(one.getPoints());
u.setEmail(one.getEmail());
u.setAddress(one.getAddress());
u.setStatus(one.getStatus());
u.setComments(one.getComments());
u.setCompanyId(one.getCompanyId());
@@ -600,6 +601,7 @@ public class UserController extends BaseController {
example1.setOrganizationName("总公司");
example1.setSexName("");
example1.setRoleName("管理员");
example1.setStatus(0);
example1.setAddress("地址");
example1.setComments("");
templateData.add(example1);
@@ -615,6 +617,7 @@ public class UserController extends BaseController {
example2.setOrganizationName("分公司");
example2.setSexName("");
example2.setRoleName("注册用户");
example1.setStatus(0);
example2.setAddress("地址");
example2.setComments("");
templateData.add(example2);

View File

@@ -17,6 +17,7 @@ import com.gxwebsoft.common.core.security.JwtSubject;
import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.WxMiniProgramDecryptUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.*;
@@ -112,7 +113,8 @@ public class WxLoginController extends BaseController {
throw new BusinessException("授权失败,请重试");
}
// 查询是否存在
User user = userService.getByPhone(phone);
User user = userService.getAdminByPhone(userParam);
// 超级管理员验证
if (userParam.getIsSuperAdmin() != null) {
final LoginParam loginParam = new LoginParam();
@@ -225,45 +227,100 @@ public class WxLoginController extends BaseController {
// 获取openid
private JSONObject getOpenIdByCode(UserParam userParam) {
// 获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKey("mp-weixin");
// 获取openId
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + setting.getString("appId") + "&secret=" + setting.getString("appSecret") + "&js_code=" + userParam.getCode() + "&grant_type=authorization_code";
// 执行get请求
String result = HttpUtil.get(apiUrl);
// 解析access_token
return JSON.parseObject(result);
try {
// 获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKey("mp-weixin");
// 获取openId
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + setting.getString("appId") + "&secret=" + setting.getString("appSecret") + "&js_code=" + userParam.getCode() + "&grant_type=authorization_code";
// 执行get请求
String result = HttpUtil.get(apiUrl);
// 验证响应内容
if (StrUtil.isBlank(result)) {
throw new BusinessException("微信接口响应为空");
}
// 清理响应中的控制字符
String cleanResult = result.trim().replaceAll("[\u0000-\u001f]", "");
System.out.println("获取openId响应: " + cleanResult);
// 解析响应
return JSON.parseObject(cleanResult);
} catch (Exception e) {
System.err.println("获取openId异常: " + e.getMessage());
e.printStackTrace();
throw new BusinessException("获取openId失败请重试");
}
}
/**
* 获取微信手机号码
* 支持两种方式:
* 1. 新版API方式使用code直接获取手机号
* 2. 旧版解密方式使用encryptedData、iv、sessionKey解密获取手机号
*
* @param userParam 需要传微信凭证code
* @param userParam 需要传微信凭证code或encryptedData等参数
*/
private String getPhoneByCode(UserParam userParam) {
// 获取手机号
String apiUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken();
HashMap<String, Object> paramMap = new HashMap<>();
if (StrUtil.isBlank(userParam.getCode())) {
throw new BusinessException("code不能为空");
// 方式1如果有encryptedData使用解密方式获取手机号
if (StrUtil.isNotBlank(userParam.getEncryptedData()) &&
StrUtil.isNotBlank(userParam.getIv()) &&
StrUtil.isNotBlank(userParam.getSessionKey())) {
try {
return WxMiniProgramDecryptUtil.decryptPhoneNumber(
userParam.getEncryptedData(),
userParam.getSessionKey(),
userParam.getIv()
);
} catch (Exception e) {
System.err.println("解密手机号失败: " + e.getMessage());
// 解密失败继续尝试新版API方式
}
}
paramMap.put("code", userParam.getCode());
// 执行post请求
String post = HttpUtil.post(apiUrl, JSON.toJSONString(paramMap));
JSONObject json = JSON.parseObject(post);
if (json.get("errcode").equals(0)) {
JSONObject phoneInfo = JSON.parseObject(json.getString("phone_info"));
// 微信用户的手机号码
final String phoneNumber = phoneInfo.getString("phoneNumber");
// 验证手机号码
// if (userParam.getNotVerifyPhone() == null && !Validator.isMobile(phoneNumber)) {
// String key = ACCESS_TOKEN_KEY.concat(":").concat(getTenantId().toString());
// redisTemplate.delete(key);
// throw new BusinessException("手机号码格式不正确");
// }
return phoneNumber;
// 方式2使用新版API方式获取手机号
if (StrUtil.isNotBlank(userParam.getCode())) {
try {
String apiUrl = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken();
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("code", userParam.getCode());
// 执行post请求
String post = HttpUtil.post(apiUrl, JSON.toJSONString(paramMap));
// 增加响应内容验证和清理
if (StrUtil.isBlank(post)) {
throw new BusinessException("微信接口响应为空");
}
// 清理响应中的控制字符
String cleanResponse = post.trim().replaceAll("[\u0000-\u001f]", "");
System.out.println("微信获取手机号响应: " + cleanResponse);
JSONObject json = JSON.parseObject(cleanResponse);
if (json.get("errcode").equals(0)) {
JSONObject phoneInfo = JSON.parseObject(json.getString("phone_info"));
// 微信用户的手机号码
final String phoneNumber = phoneInfo.getString("phoneNumber");
// 验证手机号码
// if (userParam.getNotVerifyPhone() == null && !Validator.isMobile(phoneNumber)) {
// String key = ACCESS_TOKEN_KEY.concat(":").concat(getTenantId().toString());
// redisTemplate.delete(key);
// throw new BusinessException("手机号码格式不正确");
// }
return phoneNumber;
} else {
String errorMsg = json.getString("errmsg");
System.err.println("微信获取手机号失败: errcode=" + json.get("errcode") + ", errmsg=" + errorMsg);
throw new BusinessException("获取手机号失败:" + errorMsg);
}
} catch (Exception e) {
System.err.println("获取微信手机号异常: " + e.getMessage());
e.printStackTrace();
throw new BusinessException("获取手机号失败,请重试");
}
}
return null;
throw new BusinessException("获取手机号失败,请检查参数");
}
/**
@@ -300,14 +357,32 @@ public class WxLoginController extends BaseController {
// 执行get请求
String result = HttpUtil.get(url);
System.out.println("result = " + result);
// 解析access_token
JSONObject response = JSON.parseObject(result);
if (response.getString("access_token") != null) {
// 存入缓存
redisTemplate.opsForValue().set(key, result, 7000L, TimeUnit.SECONDS);
return response.getString("access_token");
try {
// 验证响应内容
if (StrUtil.isBlank(result)) {
throw new BusinessException("微信接口响应为空");
}
// 清理响应中的控制字符
String cleanResult = result.trim().replaceAll("[\u0000-\u001f]", "");
// 解析access_token
JSONObject response = JSON.parseObject(cleanResult);
if (response.getString("access_token") != null) {
// 存入缓存
redisTemplate.opsForValue().set(key, cleanResult, 7000L, TimeUnit.SECONDS);
return response.getString("access_token");
} else {
String errorMsg = response.getString("errmsg");
System.err.println("获取access_token失败: " + errorMsg);
throw new BusinessException("获取access_token失败" + errorMsg);
}
} catch (Exception e) {
System.err.println("解析access_token异常: " + e.getMessage());
e.printStackTrace();
throw new BusinessException("小程序配置不正确或网络异常");
}
throw new BusinessException("小程序配置不正确");
}
@ApiOperation("获取微信openId并更新")
@@ -450,31 +525,63 @@ public class WxLoginController extends BaseController {
}
// 请求微信接口获取openid
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session";
final HashMap<String, Object> map = new HashMap<>();
map.put("appid", AppId);
map.put("secret", AppSecret);
map.put("js_code", mp.getCode());
map.put("grant_type", "authorization_code");
final String response = HttpUtil.get(apiUrl, map);
final JSONObject jsonObject = JSONObject.parseObject(response);
String openid = jsonObject.getString("openid");
String sessionKey = jsonObject.getString("session_key");
String unionid = jsonObject.getString("unionid");
try {
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session";
final HashMap<String, Object> map = new HashMap<>();
map.put("appid", AppId);
map.put("secret", AppSecret);
map.put("js_code", mp.getCode());
map.put("grant_type", "authorization_code");
final String response = HttpUtil.get(apiUrl, map);
if (StrUtil.isNotBlank(openid)) {
User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getOpenid, openid).last("limit 1"));
final User userInfo = userService.getByIdRel(user.getUserId());
if (ObjectUtil.isNotEmpty(userInfo)) {
// 签发token
String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_REGISTER, null, user.getTenantId(), request);
return success("登录成功", new LoginResult(access_token, userInfo));
}
return fail("用户未注册", openid);
// 验证响应内容
if (StrUtil.isBlank(response)) {
return fail("微信接口响应为空");
}
// 清理响应中的控制字符
String cleanResponse = response.trim().replaceAll("[\u0000-\u001f]", "");
System.out.println("获取openId响应: " + cleanResponse);
final JSONObject jsonObject = JSONObject.parseObject(cleanResponse);
// 检查微信接口是否返回错误
if (jsonObject.containsKey("errcode") && !jsonObject.getInteger("errcode").equals(0)) {
String errmsg = jsonObject.getString("errmsg");
System.err.println("微信接口返回错误: errcode=" + jsonObject.get("errcode") + ", errmsg=" + errmsg);
return fail("微信授权失败:" + errmsg);
}
String openid = jsonObject.getString("openid");
String sessionKey = jsonObject.getString("session_key");
String unionid = jsonObject.getString("unionid");
if (StrUtil.isNotBlank(openid)) {
User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getOpenid, openid).eq(User::getDeleted,0).last("limit 1"));
// 检查用户是否存在
if (user == null) {
return fail("用户未注册", openid);
}
final User userInfo = userService.getByIdRel(user.getUserId());
if (ObjectUtil.isNotEmpty(userInfo)) {
// 签发token
String access_token = JwtUtil.buildToken(new JwtSubject(user.getUsername(), user.getTenantId()),
configProperties.getTokenExpireTime(), configProperties.getTokenKey());
loginRecordService.saveAsync(user.getUsername(), LoginRecord.TYPE_REGISTER, null, user.getTenantId(), request);
return success("登录成功", new LoginResult(access_token, userInfo));
} else {
return fail("用户信息获取失败", openid);
}
} else {
return fail("openId获取失败");
}
} catch (Exception e) {
System.err.println("openId登录异常: " + e.getMessage());
e.printStackTrace();
return fail("登录失败,请重试");
}
return fail("openId获取失败");
}
/**

View File

@@ -48,6 +48,10 @@ public class Menu implements GrantedAuthority {
@ApiModelProperty("菜单类型, 0菜单, 1按钮")
private Integer menuType;
@ApiModelProperty("打开方式, 0当前页, 1新窗口")
@TableField(exist = false)
private Integer openType;
@ApiModelProperty("排序号")
private Integer sortNumber;

View File

@@ -9,7 +9,7 @@ import lombok.Data;
import org.springframework.security.core.userdetails.UserDetails;
import java.math.BigDecimal;
import java.util.Date;
import java.time.LocalDateTime;
import java.util.List;
/**
@@ -94,7 +94,7 @@ public class User implements UserDetails {
@ApiModelProperty("出生日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthday;
private LocalDateTime birthday;
@ApiModelProperty(value = "年龄")
private Integer age;
@@ -235,13 +235,16 @@ public class User implements UserDetails {
private String tenantName;
@ApiModelProperty(value = "最后结算时间")
private Date settlementTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime settlementTime;
@ApiModelProperty("注册时间")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@ApiModelProperty("修改时间")
private Date updateTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@ApiModelProperty("公司名称")
@TableField(exist = false)

View File

@@ -57,6 +57,9 @@ public interface UserMapper extends BaseMapper<User> {
@InterceptorIgnore(tenantLine = "true")
User selectAdminByPhone(@Param("param") UserParam param);
@InterceptorIgnore(tenantLine = "true")
User selectAdminByPhone(@Param("param") UserParam param, @Param("tenantId") Integer tenantId);
@InterceptorIgnore(tenantLine = "true")
User selectByUserId(@Param("userId") Integer userId);

View File

@@ -303,6 +303,9 @@
AND a.phone = #{param.phone}
AND a.template_id = #{param.templateId}
AND (a.username = 'superAdmin' OR a.username = 'admin' OR a.is_admin = 1)
<if test="param.tenantId">
AND a.tenant_id = #{param.tenantId}
</if>
LIMIT 1
</where>
</select>

View File

@@ -1,5 +1,6 @@
package com.gxwebsoft.common.system.param;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.gxwebsoft.common.core.annotation.QueryField;
import com.gxwebsoft.common.core.annotation.QueryType;
@@ -47,6 +48,10 @@ public class MenuParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer menuType;
@ApiModelProperty("打开方式, 0当前页, 1新窗口")
@TableField(exist = false)
private Integer openType;
@ApiModelProperty("权限标识")
private String authority;
@@ -72,4 +77,8 @@ public class MenuParam extends BaseParam {
@QueryField(type = QueryType.EQ)
private Integer companyId;
@ApiModelProperty("租户名称")
@TableField(exist = false)
private String tenantName;
}

View File

@@ -0,0 +1,124 @@
package com.gxwebsoft.common.system.param;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Map;
/**
* 系统设置更新参数
* 用于处理包含配置字段的更新请求
*
* @author WebSoft
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel(description = "系统设置更新参数")
public class SettingUpdateParam {
@ApiModelProperty(value = "设置项标示")
private String settingKey;
@ApiModelProperty(value = "设置内容json格式")
private String content;
@ApiModelProperty(value = "排序号")
private Integer sortNumber;
@ApiModelProperty(value = "备注")
private String comments;
@ApiModelProperty(value = "租户id")
private Integer tenantId;
// 微信小程序配置字段
@ApiModelProperty(value = "微信小程序AppId")
private String appId;
@ApiModelProperty(value = "微信小程序AppSecret")
private String appSecret;
// 支付配置字段
@ApiModelProperty(value = "商户号")
private String mchId;
@ApiModelProperty(value = "API密钥")
private String apiKey;
@ApiModelProperty(value = "微信支付API密钥")
private String wechatApiKey;
@ApiModelProperty(value = "商户序列号")
private String merchantSerialNumber;
@ApiModelProperty(value = "API客户端证书")
private String apiclientCert;
@ApiModelProperty(value = "API客户端密钥")
private String apiclientKey;
// 短信配置字段
@ApiModelProperty(value = "短信AccessKey")
private String accessKeyId;
@ApiModelProperty(value = "短信AccessSecret")
private String accessKeySecret;
@ApiModelProperty(value = "短信签名")
private String signName;
@ApiModelProperty(value = "短信模板")
private String templateCode;
// 企业微信配置字段
@ApiModelProperty(value = "企业ID")
private String corpId;
@ApiModelProperty(value = "应用Secret")
private String secret;
// 微信公众号配置字段
@ApiModelProperty(value = "公众号Token")
private String token;
@ApiModelProperty(value = "公众号EncodingAESKey")
private String encodingAESKey;
// 基本设置字段
@ApiModelProperty(value = "网站名称")
private String siteName;
@ApiModelProperty(value = "网站Logo")
private String logo;
@ApiModelProperty(value = "网站描述")
private String description;
@ApiModelProperty(value = "网站关键词")
private String keywords;
// 上传配置字段
@ApiModelProperty(value = "存储桶名称")
private String bucketName;
@ApiModelProperty(value = "存储桶域名")
private String bucketDomain;
@ApiModelProperty(value = "存储桶端点")
private String bucketEndpoint;
// 打印机配置字段
@ApiModelProperty(value = "打印机设备号")
private String deviceNo;
@ApiModelProperty(value = "打印机密钥")
private String printerKey;
/**
* 获取其他未定义的字段
* 用于处理动态配置字段
*/
private Map<String, Object> additionalProperties;
}

View File

@@ -42,6 +42,9 @@ public class UserImportParam implements Serializable {
@Excel(name = "角色")
private String roleName;
@Excel(name = "状态")
private Integer status;
@Excel(name = "备注")
private String comments;

View File

@@ -296,4 +296,16 @@ public class UserParam extends BaseParam {
@ApiModelProperty(value = "是否已安装")
@TableField(exist = false)
private Boolean installed;
@ApiModelProperty(value = "微信小程序解密数据")
@TableField(exist = false)
private String encryptedData;
@ApiModelProperty(value = "微信小程序解密向量")
@TableField(exist = false)
private String iv;
@ApiModelProperty(value = "微信小程序会话密钥")
@TableField(exist = false)
private String sessionKey;
}

View File

@@ -98,6 +98,8 @@ public interface UserService extends IService<User>, UserDetailsService {
*/
User getByPhone(String phone);
User getByPhone(String phone,Integer tenantId);
User getByUnionId(UserParam userParam);
User getByOauthId(UserParam userParam);
@@ -114,6 +116,8 @@ public interface UserService extends IService<User>, UserDetailsService {
User getAdminByPhone(UserParam param);
User getAdminByPhone(UserParam param,Integer tenantId);
User getAllByUserId(String userId);
Integer userNumInPark(UserParam param);

View File

@@ -181,10 +181,22 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
return getOne(
new LambdaQueryWrapper<User>()
.eq(User::getPhone, phone)
.eq(User::getDeleted,0)
.orderByDesc(User::getUserId).last("limit 1")
);
}
@Override
public User getByPhone(String phone,Integer tenantId) {
return getOne(
new LambdaQueryWrapper<User>()
.eq(User::getPhone, phone)
.eq(User::getTenantId, tenantId)
.eq(User::getDeleted,0)
.orderByDesc(User::getUserId).last("limit 1")
);
}
@Override
public User getByUnionId(UserParam param) {
return getOne(
@@ -276,10 +288,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Override
public User getAdminByPhone(UserParam param) {
System.out.println("param222 = " + param);
return baseMapper.selectAdminByPhone(param);
}
public User getAdminByPhone(UserParam param,Integer tenantId){
return baseMapper.selectAdminByPhone(param,tenantId);
}
@Override
public List<User> getAdminsByPhone(LoginParam param){
final UserParam userParam = new UserParam();