diff --git a/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java b/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java index 4434ab9..4527a35 100644 --- a/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java +++ b/src/main/java/com/gxwebsoft/common/core/config/MybatisPlusConfig.java @@ -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", diff --git a/src/main/java/com/gxwebsoft/common/core/utils/WxMiniProgramDecryptUtil.java b/src/main/java/com/gxwebsoft/common/core/utils/WxMiniProgramDecryptUtil.java new file mode 100644 index 0000000..b2af68f --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/utils/WxMiniProgramDecryptUtil.java @@ -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; + } +} diff --git a/src/main/java/com/gxwebsoft/common/system/controller/SettingController.java b/src/main/java/com/gxwebsoft/common/system/controller/SettingController.java index bab90dc..4111bc1 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/SettingController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/SettingController.java @@ -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().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; + } } diff --git a/src/main/java/com/gxwebsoft/common/system/controller/UserController.java b/src/main/java/com/gxwebsoft/common/system/controller/UserController.java index 2128a43..f9ae330 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/UserController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/UserController.java @@ -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); diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java index 4f17252..35a7a42 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java @@ -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 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 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 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 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().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().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获取失败"); } /** diff --git a/src/main/java/com/gxwebsoft/common/system/entity/Menu.java b/src/main/java/com/gxwebsoft/common/system/entity/Menu.java index 79ffce5..f97edfd 100644 --- a/src/main/java/com/gxwebsoft/common/system/entity/Menu.java +++ b/src/main/java/com/gxwebsoft/common/system/entity/Menu.java @@ -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; diff --git a/src/main/java/com/gxwebsoft/common/system/entity/User.java b/src/main/java/com/gxwebsoft/common/system/entity/User.java index 14b7118..00fbaa3 100644 --- a/src/main/java/com/gxwebsoft/common/system/entity/User.java +++ b/src/main/java/com/gxwebsoft/common/system/entity/User.java @@ -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) diff --git a/src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.java b/src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.java index 63a3fc2..42081be 100644 --- a/src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.java +++ b/src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.java @@ -57,6 +57,9 @@ public interface UserMapper extends BaseMapper { @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); diff --git a/src/main/java/com/gxwebsoft/common/system/mapper/xml/UserMapper.xml b/src/main/java/com/gxwebsoft/common/system/mapper/xml/UserMapper.xml index 06db2d0..15e101c 100644 --- a/src/main/java/com/gxwebsoft/common/system/mapper/xml/UserMapper.xml +++ b/src/main/java/com/gxwebsoft/common/system/mapper/xml/UserMapper.xml @@ -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) + + AND a.tenant_id = #{param.tenantId} + LIMIT 1 diff --git a/src/main/java/com/gxwebsoft/common/system/param/MenuParam.java b/src/main/java/com/gxwebsoft/common/system/param/MenuParam.java index 34eef38..46f147e 100644 --- a/src/main/java/com/gxwebsoft/common/system/param/MenuParam.java +++ b/src/main/java/com/gxwebsoft/common/system/param/MenuParam.java @@ -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; + } diff --git a/src/main/java/com/gxwebsoft/common/system/param/SettingUpdateParam.java b/src/main/java/com/gxwebsoft/common/system/param/SettingUpdateParam.java new file mode 100644 index 0000000..7f5eef0 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/param/SettingUpdateParam.java @@ -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 additionalProperties; +} diff --git a/src/main/java/com/gxwebsoft/common/system/param/UserImportParam.java b/src/main/java/com/gxwebsoft/common/system/param/UserImportParam.java index 054a253..a8cdd43 100644 --- a/src/main/java/com/gxwebsoft/common/system/param/UserImportParam.java +++ b/src/main/java/com/gxwebsoft/common/system/param/UserImportParam.java @@ -42,6 +42,9 @@ public class UserImportParam implements Serializable { @Excel(name = "角色") private String roleName; + @Excel(name = "状态") + private Integer status; + @Excel(name = "备注") private String comments; diff --git a/src/main/java/com/gxwebsoft/common/system/param/UserParam.java b/src/main/java/com/gxwebsoft/common/system/param/UserParam.java index 80f3174..e912b90 100644 --- a/src/main/java/com/gxwebsoft/common/system/param/UserParam.java +++ b/src/main/java/com/gxwebsoft/common/system/param/UserParam.java @@ -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; } diff --git a/src/main/java/com/gxwebsoft/common/system/service/UserService.java b/src/main/java/com/gxwebsoft/common/system/service/UserService.java index c367a30..ad8a6f9 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/UserService.java +++ b/src/main/java/com/gxwebsoft/common/system/service/UserService.java @@ -98,6 +98,8 @@ public interface UserService extends IService, 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, UserDetailsService { User getAdminByPhone(UserParam param); + User getAdminByPhone(UserParam param,Integer tenantId); + User getAllByUserId(String userId); Integer userNumInPark(UserParam param); diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java index c345b57..cf57903 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java @@ -181,10 +181,22 @@ public class UserServiceImpl extends ServiceImpl implements Us return getOne( new LambdaQueryWrapper() .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() + .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 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 getAdminsByPhone(LoginParam param){ final UserParam userParam = new UserParam();