# Conflicts:
#	yudao-module-ai/pom.xml
#	yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/vo/segment/AiKnowledgeSegmentPageReqVO.java
#	yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
#	yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeSegmentServiceImpl.java
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmTaskController.java
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmParallelMultiInstanceBehavior.java
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmCopyTaskDelegate.java
#	yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
#	yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/CodegenServiceImplTest.java
#	yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue2Test.java
#	yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngineVue3Test.java
#	yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
#	yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
#	yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageListReqVO.java
#	yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/kefu/vo/message/AppKeFuMessagePageReqVO.java
#	yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java
#	yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
#	yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateService.java
#	yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
#	yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java
#	yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java
#	yudao-module-member/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/MemberUserController.java
#	yudao-module-pay/pom.xml
#	yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
#	yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletRechargeController.java
#	yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
#	yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java
#	yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
#	yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
#	yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/mail/MailTemplateServiceImplTest.java
#	yudao-module-system/src/test/resources/sql/create_tables.sql
This commit is contained in:
YunaiV
2025-12-28 10:44:59 +08:00
68 changed files with 3650 additions and 1295 deletions

View File

@@ -85,7 +85,7 @@ public class SocialClientApiImpl implements SocialClientApi {
// 2. 获得社交用户
SocialUserRespDTO socialUser = socialUserService.getSocialUserByUserId(reqDTO.getUserType(), reqDTO.getUserId(),
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType());
if (StrUtil.isBlankIfStr(socialUser.getOpenid())) {
if (ObjUtil.isNull(socialUser) || StrUtil.isBlankIfStr(socialUser.getOpenid())) {
log.warn("[sendWxaSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:会员 openid 缺失]", reqDTO);
return;
}

View File

@@ -64,6 +64,14 @@ public class PostController {
return success(true);
}
@DeleteMapping("delete-list")
@Operation(summary = "批量删除岗位")
@PreAuthorize("@ss.hasPermission('system:post:delete')")
public CommonResult<Boolean> deletePostList(@RequestParam("ids") List<Long> ids) {
postService.deletePostList(ids);
return success(true);
}
@GetMapping(value = "/get")
@Operation(summary = "获得岗位信息")
@Parameter(name = "id", description = "岗位编号", required = true, example = "1024")

View File

@@ -36,6 +36,14 @@ public class LoginLogController {
@Resource
private LoginLogService loginLogService;
@GetMapping("/get")
@Operation(summary = "获得登录日志")
@PreAuthorize("@ss.hasPermission('system:login-log:query')")
public CommonResult<LoginLogRespVO> getLoginLog(Long id) {
LoginLogDO loginLog = loginLogService.getLoginLog(id);
return success(BeanUtils.toBean(loginLog, LoginLogRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得登录日志分页列表")
@PreAuthorize("@ss.hasPermission('system:login-log:query')")

View File

@@ -13,11 +13,13 @@ import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO;
import cn.iocoder.yudao.module.system.service.logger.OperateLogService;
import com.fhs.core.trans.anno.TransMethodResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@@ -38,6 +40,15 @@ public class OperateLogController {
@Resource
private OperateLogService operateLogService;
@GetMapping("/get")
@Operation(summary = "查看操作日志")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:operate-log:query')")
public CommonResult<OperateLogRespVO> getOperateLog(@RequestParam("id") Long id) {
OperateLogDO operateLog = operateLogService.getOperateLog(id);
return success(BeanUtils.toBean(operateLog, OperateLogRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "查看操作日志分页列表")
@PreAuthorize("@ss.hasPermission('system:operate-log:query')")
@@ -50,6 +61,7 @@ public class OperateLogController {
@Operation(summary = "导出操作日志")
@GetMapping("/export-excel")
@PreAuthorize("@ss.hasPermission('system:operate-log:export')")
@TransMethodResult
@ApiAccessLog(operateType = EXPORT)
public void exportOperateLog(HttpServletResponse response, @Valid OperateLogPageReqVO exportReqVO) throws IOException {
exportReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);

View File

@@ -1,8 +1,10 @@
package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
import com.fhs.core.trans.anno.Trans;
import com.fhs.core.trans.constant.TransType;
import com.fhs.core.trans.vo.VO;
@@ -31,6 +33,11 @@ public class OperateLogRespVO implements VO {
@ExcelProperty("操作人")
private String userName;
@Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1", implementation = Integer.class)
@ExcelProperty("用户类型")
@DictFormat(DictTypeConstants.USER_TYPE)
private Integer userType;
@Schema(description = "操作模块类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "订单")
@ExcelProperty("操作模块类型")
private String type;

View File

@@ -11,10 +11,12 @@ import cn.iocoder.yudao.module.system.controller.admin.sms.vo.log.SmsLogRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsLogDO;
import cn.iocoder.yudao.module.system.service.sms.SmsLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -44,6 +46,15 @@ public class SmsLogController {
return success(BeanUtils.toBean(pageResult, SmsLogRespVO.class));
}
@GetMapping("/get")
@Operation(summary = "获得短信日志")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:sms-log:query')")
public CommonResult<SmsLogRespVO> getSmsLog(@RequestParam("id") Long id) {
SmsLogDO smsLog = smsLogService.getSmsLog(id);
return success(BeanUtils.toBean(smsLog, SmsLogRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出短信日志 Excel")
@PreAuthorize("@ss.hasPermission('system:sms-log:export')")

View File

@@ -27,9 +27,12 @@ public class SocialClientRespVO {
@Schema(description = "客户端密钥", requiredMode = Schema.RequiredMode.REQUIRED, example = "peter")
private String clientSecret;
@Schema(description = "授权方的网页应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000045")
@Schema(description = "授权方的网页应用编号", example = "2000045")
private String agentId;
@Schema(description = "publicKey 公钥", example = "2000045")
private String publicKey;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;

View File

@@ -45,6 +45,9 @@ public class SocialClientSaveReqVO {
@Schema(description = "授权方的网页应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000045")
private String agentId;
@Schema(description = "publicKey 公钥", example = "2000045")
private String publicKey;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
@@ -58,4 +61,12 @@ public class SocialClientSaveReqVO {
|| !StrUtil.isEmpty(agentId);
}
@AssertTrue(message = "publicKey 不能为空")
@JsonIgnore
public boolean isPublicKeyValid() {
// 如果是支付宝,必须填写 publicKey 属性
return !Objects.equals(socialType, SocialTypeEnum.ALIPAY_MINI_PROGRAM.getType())
|| !StrUtil.isEmpty(publicKey);
}
}

View File

@@ -5,8 +5,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO;
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
@@ -26,8 +28,6 @@ public interface AuthConvert {
AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class);
AuthLoginRespVO convert(OAuth2AccessTokenDO bean);
default AuthPermissionInfoRespVO convert(AdminUserDO user, List<RoleDO> roleList, List<MenuDO> menuList) {
return AuthPermissionInfoRespVO.builder()
.user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class))

View File

@@ -73,4 +73,12 @@ public class SocialClientDO extends TenantBaseDO {
*/
private String agentId;
/**
* publicKey 公钥
*
* 目前只有部分“社交类型”在使用:
* 1. 支付宝:支付宝公钥
*/
private String publicKey;
}

View File

@@ -53,6 +53,12 @@ public enum SocialTypeEnum implements ArrayValuable<Integer> {
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html">接入文档</a>
*/
WECHAT_MINI_PROGRAM(34, "WECHAT_MINI_PROGRAM"),
/**
* 支付宝小程序
*
* @see <a href="https://opendocs.alipay.com/mini/05dxgc?pathHash=1a3ecb13">接入文档</a>
*/
ALIPAY_MINI_PROGRAM(40, "ALIPAY"),
;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(SocialTypeEnum::getType).toArray(Integer[]::new);

View File

@@ -91,10 +91,10 @@ public class AliyunSmsClient extends AbstractSmsClient {
@Override
public SmsTemplateRespDTO getSmsTemplate(String apiTemplateId) throws Throwable {
// 1. 执行请求
// 参考链接 https://api.aliyun.com/document/Dysmsapi/2017-05-25/QuerySmsTemplate
// 参考链接 https://api.aliyun.com/document/Dysmsapi/2017-05-25/GetSmsTemplate
TreeMap<String, Object> queryParam = new TreeMap<>();
queryParam.put("TemplateCode", apiTemplateId);
JSONObject response = request("QuerySmsTemplate", queryParam);
JSONObject response = request("GetSmsTemplate", queryParam);
// 2.1 请求失败
String code = response.getStr("Code");

View File

@@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
@@ -215,13 +216,13 @@ public class AdminAuthServiceImpl implements AdminAuthService {
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, getUserType().getValue(),
OAuth2ClientConstants.CLIENT_ID_DEFAULT, null);
// 构建返回结果
return AuthConvert.INSTANCE.convert(accessTokenDO);
return BeanUtils.toBean(accessTokenDO, AuthLoginRespVO.class);
}
@Override
public AuthLoginRespVO refreshToken(String refreshToken) {
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, OAuth2ClientConstants.CLIENT_ID_DEFAULT);
return AuthConvert.INSTANCE.convert(accessTokenDO);
return BeanUtils.toBean(accessTokenDO, AuthLoginRespVO.class);
}
@Override

View File

@@ -12,6 +12,14 @@ import javax.validation.Valid;
*/
public interface LoginLogService {
/**
* 获得登录日志
*
* @param id 编号
* @return 登录日志
*/
LoginLogDO getLoginLog(Long id);
/**
* 获得登录日志分页
*

View File

@@ -21,6 +21,11 @@ public class LoginLogServiceImpl implements LoginLogService {
@Resource
private LoginLogMapper loginLogMapper;
@Override
public LoginLogDO getLoginLog(Long id) {
return loginLogMapper.selectById(id);
}
@Override
public PageResult<LoginLogDO> getLoginLogPage(LoginLogPageReqVO pageReqVO) {
return loginLogMapper.selectPage(pageReqVO);

View File

@@ -20,6 +20,14 @@ public interface OperateLogService {
*/
void createOperateLog(OperateLogCreateReqDTO createReqDTO);
/**
* 获得操作日志
*
* @param id 编号
* @return 操作日志
*/
OperateLogDO getOperateLog(Long id);
/**
* 获得操作日志分页列表
*

View File

@@ -32,6 +32,11 @@ public class OperateLogServiceImpl implements OperateLogService {
operateLogMapper.insert(log);
}
@Override
public OperateLogDO getOperateLog(Long id) {
return operateLogMapper.selectById(id);
}
@Override
public PageResult<OperateLogDO> getOperateLogPage(OperateLogPageReqVO pageReqVO) {
return operateLogMapper.selectPage(pageReqVO);

View File

@@ -19,8 +19,10 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -53,7 +55,7 @@ public class MailTemplateServiceImpl implements MailTemplateService {
// 插入
MailTemplateDO template = BeanUtils.toBean(createReqVO, MailTemplateDO.class)
.setParams(parseTemplateContentParams(createReqVO.getContent()));
.setParams(parseTemplateTitleAndContentParams(createReqVO.getTitle(), createReqVO.getContent()));
mailTemplateMapper.insert(template);
return template.getId();
}
@@ -69,7 +71,7 @@ public class MailTemplateServiceImpl implements MailTemplateService {
// 更新
MailTemplateDO updateObj = BeanUtils.toBean(updateReqVO, MailTemplateDO.class)
.setParams(parseTemplateContentParams(updateReqVO.getContent()));
.setParams(parseTemplateTitleAndContentParams(updateReqVO.getTitle(), updateReqVO.getContent()));
mailTemplateMapper.updateById(updateObj);
}
@@ -129,7 +131,77 @@ public class MailTemplateServiceImpl implements MailTemplateService {
@Override
public String formatMailTemplateContent(String content, Map<String, Object> params) {
return StrUtil.format(content, params);
// 1. 先替换模板变量
String formattedContent = StrUtil.format(content, params);
// 关联 Pull Requesthttps://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1461 讨论
// 2.1 反转义HTML特殊字符
formattedContent = unescapeHtml(formattedContent);
// 2.2 处理代码块(确保<pre><code>标签格式正确)
formattedContent = formatHtmlCodeBlocks(formattedContent);
// 2.3 将最外层的 pre 标签替换为 div 标签
formattedContent = replaceOuterPreWithDiv(formattedContent);
return formattedContent;
}
private String replaceOuterPreWithDiv(String content) {
if (StrUtil.isEmpty(content)) {
return content;
}
// 使用正则表达式匹配所有的 <pre> 标签,包括嵌套的 <code> 标签
String regex = "(?s)<pre[^>]*>(.*?)</pre>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// 提取 <pre> 标签内的内容
String innerContent = matcher.group(1);
// 返回 div 标签包裹的内容
matcher.appendReplacement(sb, "<div>" + innerContent + "</div>");
}
matcher.appendTail(sb);
return sb.toString();
}
/**
* 反转义 HTML 特殊字符
*
* @param input 输入字符串
* @return 反转义后的字符串
*/
private String unescapeHtml(String input) {
if (StrUtil.isEmpty(input)) {
return input;
}
return input
.replace("&amp;", "&")
.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&quot;", "\"")
.replace("&#39;", "'")
.replace("&nbsp;", " ");
}
/**
* 格式化 HTML 中的代码块
*
* @param content 邮件内容
* @return 格式化后的邮件内容
*/
private String formatHtmlCodeBlocks(String content) {
// 匹配 <pre><code> 标签的代码块
Pattern codeBlockPattern = Pattern.compile("<pre\\s*.*?><code\\s*.*?>(.*?)</code></pre>", Pattern.DOTALL);
Matcher matcher = codeBlockPattern.matcher(content);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// 获取代码块内容
String codeBlock = matcher.group(1);
// 为代码块添加样式
String replacement = "<pre style=\"background-color: #f5f5f5; padding: 10px; border-radius: 5px; overflow-x: auto;\"><code>" + codeBlock + "</code></pre>";
matcher.appendReplacement(sb, replacement);
}
matcher.appendTail(sb);
return sb.toString();
}
@Override
@@ -137,14 +209,31 @@ public class MailTemplateServiceImpl implements MailTemplateService {
return mailTemplateMapper.selectCountByAccountId(accountId);
}
/**
* 解析标题和内容中的参数
*/
@VisibleForTesting
public List<String> parseTemplateTitleAndContentParams(String title, String content) {
List<String> titleParams = ReUtil.findAllGroup1(PATTERN_PARAMS, title);
List<String> contentParams = ReUtil.findAllGroup1(PATTERN_PARAMS, content);
// 合并参数并去重
List<String> allParams = new ArrayList<>(titleParams);
for (String param : contentParams) {
if (!allParams.contains(param)) {
allParams.add(param);
}
}
return allParams;
}
/**
* 获得邮件模板中的参数,形如 {key}
*
* @param content 内容
* @return 参数列表
*/
private List<String> parseTemplateContentParams(String content) {
List<String> parseTemplateContentParams(String content) {
return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
}
}
}

View File

@@ -180,7 +180,13 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
.setClientId(clientDO.getClientId()).setScopes(refreshTokenDO.getScopes())
.setRefreshToken(refreshTokenDO.getRefreshToken())
.setExpiresTime(LocalDateTime.now().plusSeconds(clientDO.getAccessTokenValiditySeconds()));
accessTokenDO.setTenantId(TenantContextHolder.getTenantId()); // 手动设置租户编号,避免缓存到 Redis 的时候,无对应的租户编号
// 优先从 refreshToken 获取租户编号,避免 ThreadLocal 被污染时导致 tenantId 为 null
// 可能关联的 issuehttps://t.zsxq.com/JIi5G
Long tenantId = refreshTokenDO.getTenantId();
if (tenantId == null) {
tenantId = TenantContextHolder.getTenantId();
}
accessTokenDO.setTenantId(tenantId);
oauth2AccessTokenMapper.insert(accessTokenDO);
// 记录到 Redis 中
oauth2AccessTokenRedisDAO.set(accessTokenDO);

View File

@@ -255,6 +255,9 @@ public class MenuServiceImpl implements MenuService {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
if (id == null) {
throw exception(MENU_NAME_DUPLICATE);
}
if (!menu.getId().equals(id)) {
throw exception(MENU_NAME_DUPLICATE);
}
@@ -277,7 +280,7 @@ public class MenuServiceImpl implements MenuService {
}
// 如果 id 为空,说明不用比较是否为相同 id 的菜单
if (id == null) {
return;
throw exception(MENU_COMPONENT_NAME_DUPLICATE);
}
if (!menu.getId().equals(id)) {
throw exception(MENU_COMPONENT_NAME_DUPLICATE);

View File

@@ -58,6 +58,14 @@ public interface SmsLogService {
void updateSmsReceiveResult(Long id, String apiSerialNo, Boolean success,
LocalDateTime receiveTime, String apiReceiveCode, String apiReceiveMsg);
/**
* 获得短信日志
*
* @param id 日志编号
* @return 短信日志
*/
SmsLogDO getSmsLog(Long id);
/**
* 获得短信日志分页
*

View File

@@ -78,6 +78,11 @@ public class SmsLogServiceImpl implements SmsLogService {
.receiveTime(receiveTime).apiReceiveCode(apiReceiveCode).apiReceiveMsg(apiReceiveMsg).build());
}
@Override
public SmsLogDO getSmsLog(Long id) {
return smsLogMapper.selectById(id);
}
@Override
public PageResult<SmsLogDO> getSmsLogPage(SmsLogPageReqVO pageReqVO) {
return smsLogMapper.selectPage(pageReqVO);

View File

@@ -50,6 +50,7 @@ import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthAlipayRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -168,7 +169,7 @@ public class SocialClientServiceImpl implements SocialClientService {
public AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state) {
// 构建请求
AuthRequest authRequest = buildAuthRequest(socialType, userType);
AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build();
AuthCallback authCallback = AuthCallback.builder().code(code).auth_code(code).state(state).build();
// 执行请求
AuthResponse<?> authResponse = authRequest.login(authCallback);
log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", socialType,
@@ -204,7 +205,15 @@ public class SocialClientServiceImpl implements SocialClientService {
if (client.getAgentId() != null) { // 如果有 agentId 则修改 agentId
newAuthConfig.setAgentId(client.getAgentId());
}
// 如果是阿里的小程序
if (SocialTypeEnum.ALIPAY_MINI_PROGRAM.getType().equals(socialType)) {
return new AuthAlipayRequest(newAuthConfig, client.getPublicKey());
}
// 2.3 设置会 request 里,进行后续使用
if (SocialTypeEnum.ALIPAY_MINI_PROGRAM.getType().equals(socialType)) {
// 特殊:如果是支付宝的小程序,多了 publicKey 属性,可见 AuthConfig 里的 alipayPublicKey 字段说明
return new AuthAlipayRequest(newAuthConfig, client.getPublicKey());
}
ReflectUtil.setFieldValue(request, "config", newAuthConfig);
}
return request;