mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	优化 mp 账号的刷新机制,使用 Job 轮询,替换 MQ 广播
This commit is contained in:
		@@ -164,7 +164,7 @@ public class CollectionUtils {
 | 
				
			|||||||
        return from.stream().filter(predicate).findFirst().orElse(null);
 | 
					        return from.stream().filter(predicate).findFirst().orElse(null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static <T, V extends Comparable<? super V>> V getMaxValue(List<T> from, Function<T, V> valueFunc) {
 | 
					    public static <T, V extends Comparable<? super V>> V getMaxValue(Collection<T> from, Function<T, V> valueFunc) {
 | 
				
			||||||
        if (CollUtil.isEmpty(from)) {
 | 
					        if (CollUtil.isEmpty(from)) {
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -15,8 +15,8 @@ import cn.iocoder.yudao.module.bpm.convert.definition.BpmTaskAssignRuleConvert;
 | 
				
			|||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
 | 
					import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmTaskAssignRuleDO;
 | 
				
			||||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
 | 
					import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmUserGroupDO;
 | 
				
			||||||
import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
 | 
					import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmTaskAssignRuleMapper;
 | 
				
			||||||
import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
 | 
					import cn.iocoder.yudao.module.bpm.enums.DictTypeConstants;
 | 
				
			||||||
 | 
					import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum;
 | 
				
			||||||
import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 | 
					import cn.iocoder.yudao.module.bpm.framework.flowable.core.behavior.script.BpmTaskAssignScript;
 | 
				
			||||||
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 | 
					import cn.iocoder.yudao.module.system.api.dept.DeptApi;
 | 
				
			||||||
import cn.iocoder.yudao.module.system.api.dept.PostApi;
 | 
					import cn.iocoder.yudao.module.system.api.dept.PostApi;
 | 
				
			||||||
@@ -89,7 +89,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId,
 | 
					    public List<BpmTaskAssignRuleDO> getTaskAssignRuleListByProcessDefinitionId(String processDefinitionId,
 | 
				
			||||||
        String taskDefinitionKey) {
 | 
					                                                                                String taskDefinitionKey) {
 | 
				
			||||||
        return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
 | 
					        return taskRuleMapper.selectListByProcessDefinitionId(processDefinitionId, taskDefinitionKey);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -128,14 +128,14 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
 | 
				
			|||||||
        validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
 | 
					        validTaskAssignRuleOptions(reqVO.getType(), reqVO.getOptions());
 | 
				
			||||||
        // 校验是否已经配置
 | 
					        // 校验是否已经配置
 | 
				
			||||||
        BpmTaskAssignRuleDO existRule =
 | 
					        BpmTaskAssignRuleDO existRule =
 | 
				
			||||||
            taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(reqVO.getModelId(), reqVO.getTaskDefinitionKey());
 | 
					                taskRuleMapper.selectListByModelIdAndTaskDefinitionKey(reqVO.getModelId(), reqVO.getTaskDefinitionKey());
 | 
				
			||||||
        if (existRule != null) {
 | 
					        if (existRule != null) {
 | 
				
			||||||
            throw exception(TASK_ASSIGN_RULE_EXISTS, reqVO.getModelId(), reqVO.getTaskDefinitionKey());
 | 
					            throw exception(TASK_ASSIGN_RULE_EXISTS, reqVO.getModelId(), reqVO.getTaskDefinitionKey());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 存储
 | 
					        // 存储
 | 
				
			||||||
        BpmTaskAssignRuleDO rule = BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO)
 | 
					        BpmTaskAssignRuleDO rule = BpmTaskAssignRuleConvert.INSTANCE.convert(reqVO)
 | 
				
			||||||
            .setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
 | 
					                .setProcessDefinitionId(BpmTaskAssignRuleDO.PROCESS_DEFINITION_ID_NULL); // 只有流程模型,才允许新建
 | 
				
			||||||
        taskRuleMapper.insert(rule);
 | 
					        taskRuleMapper.insert(rule);
 | 
				
			||||||
        return rule.getId();
 | 
					        return rule.getId();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -169,14 +169,14 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // 遍历,匹配对应的规则
 | 
					        // 遍历,匹配对应的规则
 | 
				
			||||||
        Map<String, BpmTaskAssignRuleRespVO> processInstanceRuleMap =
 | 
					        Map<String, BpmTaskAssignRuleRespVO> processInstanceRuleMap =
 | 
				
			||||||
            CollectionUtils.convertMap(processInstanceRules, BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
 | 
					                CollectionUtils.convertMap(processInstanceRules, BpmTaskAssignRuleRespVO::getTaskDefinitionKey);
 | 
				
			||||||
        for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
 | 
					        for (BpmTaskAssignRuleRespVO modelRule : modelRules) {
 | 
				
			||||||
            BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
 | 
					            BpmTaskAssignRuleRespVO processInstanceRule = processInstanceRuleMap.get(modelRule.getTaskDefinitionKey());
 | 
				
			||||||
            if (processInstanceRule == null) {
 | 
					            if (processInstanceRule == null) {
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType()) || !ObjectUtil.equal(
 | 
					            if (!ObjectUtil.equals(modelRule.getType(), processInstanceRule.getType()) || !ObjectUtil.equal(
 | 
				
			||||||
                modelRule.getOptions(), processInstanceRule.getOptions())) {
 | 
					                    modelRule.getOptions(), processInstanceRule.getOptions())) {
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -192,7 +192,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
 | 
				
			|||||||
        // 开始复制
 | 
					        // 开始复制
 | 
				
			||||||
        List<BpmTaskAssignRuleDO> newRules = BpmTaskAssignRuleConvert.INSTANCE.convertList2(rules);
 | 
					        List<BpmTaskAssignRuleDO> newRules = BpmTaskAssignRuleConvert.INSTANCE.convertList2(rules);
 | 
				
			||||||
        newRules.forEach(rule -> rule.setProcessDefinitionId(toProcessDefinitionId).setId(null).setCreateTime(null)
 | 
					        newRules.forEach(rule -> rule.setProcessDefinitionId(toProcessDefinitionId).setId(null).setCreateTime(null)
 | 
				
			||||||
            .setUpdateTime(null));
 | 
					                .setUpdateTime(null));
 | 
				
			||||||
        taskRuleMapper.insertBatch(newRules);
 | 
					        taskRuleMapper.insertBatch(newRules);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -215,7 +215,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
 | 
				
			|||||||
        if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
 | 
					        if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.ROLE.getType())) {
 | 
				
			||||||
            roleApi.validRoleList(options);
 | 
					            roleApi.validRoleList(options);
 | 
				
			||||||
        } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
 | 
					        } else if (ObjectUtils.equalsAny(type, BpmTaskAssignRuleTypeEnum.DEPT_MEMBER.getType(),
 | 
				
			||||||
            BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
 | 
					                BpmTaskAssignRuleTypeEnum.DEPT_LEADER.getType())) {
 | 
				
			||||||
            deptApi.validateDeptList(options);
 | 
					            deptApi.validateDeptList(options);
 | 
				
			||||||
        } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
 | 
					        } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.POST.getType())) {
 | 
				
			||||||
            postApi.validPostList(options);
 | 
					            postApi.validPostList(options);
 | 
				
			||||||
@@ -225,7 +225,7 @@ public class BpmTaskAssignRuleServiceImpl implements BpmTaskAssignRuleService {
 | 
				
			|||||||
            userGroupService.validUserGroups(options);
 | 
					            userGroupService.validUserGroups(options);
 | 
				
			||||||
        } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
 | 
					        } else if (Objects.equals(type, BpmTaskAssignRuleTypeEnum.SCRIPT.getType())) {
 | 
				
			||||||
            dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT,
 | 
					            dictDataApi.validateDictDataList(DictTypeConstants.TASK_ASSIGN_SCRIPT,
 | 
				
			||||||
                CollectionUtils.convertSet(options, String::valueOf));
 | 
					                    CollectionUtils.convertSet(options, String::valueOf));
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            throw new IllegalArgumentException(format("未知的规则类型({})", type));
 | 
					            throw new IllegalArgumentException(format("未知的规则类型({})", type));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,8 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
 | 
				
			|||||||
        // mock 方法(startUser)
 | 
					        // mock 方法(startUser)
 | 
				
			||||||
        AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L));
 | 
					        AdminUserRespDTO startUser = randomPojo(AdminUserRespDTO.class, o -> o.setDeptId(10L));
 | 
				
			||||||
        when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
 | 
					        when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
 | 
				
			||||||
 | 
					        // mock 方法(getStartUserDept)没有部门
 | 
				
			||||||
 | 
					        when(deptApi.getDept(eq(10L))).thenReturn(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 调用
 | 
					        // 调用
 | 
				
			||||||
        Set<Long> result = script.calculateTaskCandidateUsers(execution);
 | 
					        Set<Long> result = script.calculateTaskCandidateUsers(execution);
 | 
				
			||||||
@@ -56,7 +58,9 @@ public class BpmTaskAssignLeaderX2ScriptTest extends BaseMockitoUnitTest {
 | 
				
			|||||||
        when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
 | 
					        when(adminUserApi.getUser(eq(1L))).thenReturn(startUser);
 | 
				
			||||||
        DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L)
 | 
					        DeptRespDTO startUserDept = randomPojo(DeptRespDTO.class, o -> o.setId(10L).setParentId(100L)
 | 
				
			||||||
                .setLeaderUserId(20L));
 | 
					                .setLeaderUserId(20L));
 | 
				
			||||||
 | 
					        // mock 方法(getDept)
 | 
				
			||||||
        when(deptApi.getDept(eq(10L))).thenReturn(startUserDept);
 | 
					        when(deptApi.getDept(eq(10L))).thenReturn(startUserDept);
 | 
				
			||||||
 | 
					        when(deptApi.getDept(eq(100L))).thenReturn(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 调用
 | 
					        // 调用
 | 
				
			||||||
        Set<Long> result = script.calculateTaskCandidateUsers(execution);
 | 
					        Set<Long> result = script.calculateTaskCandidateUsers(execution);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 | 
				
			|||||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO;
 | 
					import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
 | 
					import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
 | 
				
			||||||
import org.apache.ibatis.annotations.Mapper;
 | 
					import org.apache.ibatis.annotations.Mapper;
 | 
				
			||||||
 | 
					import org.apache.ibatis.annotations.Select;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Mapper
 | 
					@Mapper
 | 
				
			||||||
public interface MpAccountMapper extends BaseMapperX<MpAccountDO> {
 | 
					public interface MpAccountMapper extends BaseMapperX<MpAccountDO> {
 | 
				
			||||||
@@ -22,4 +25,7 @@ public interface MpAccountMapper extends BaseMapperX<MpAccountDO> {
 | 
				
			|||||||
        return selectOne(MpAccountDO::getAppId, appId);
 | 
					        return selectOne(MpAccountDO::getAppId, appId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Select("SELECT COUNT(*) FROM pay_account WHERE update_time > #{maxUpdateTime}")
 | 
				
			||||||
 | 
					    Long selectCountByUpdateTimeGt(LocalDateTime maxUpdateTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
package cn.iocoder.yudao.module.mp.mq.consumer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener;
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.module.mp.mq.message.MpAccountRefreshMessage;
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.module.mp.service.account.MpAccountService;
 | 
					 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					 | 
				
			||||||
import org.springframework.stereotype.Component;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.annotation.Resource;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 针对 {@link MpAccountRefreshMessage} 的消费者
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author 芋道源码
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Component
 | 
					 | 
				
			||||||
@Slf4j
 | 
					 | 
				
			||||||
public class MpAccountRefreshConsumer extends AbstractChannelMessageListener<MpAccountRefreshMessage> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private MpAccountService mpAccountService;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void onMessage(MpAccountRefreshMessage message) {
 | 
					 | 
				
			||||||
        log.info("[onMessage][收到 Account 刷新消息]");
 | 
					 | 
				
			||||||
        mpAccountService.initLocalCache();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,21 +0,0 @@
 | 
				
			|||||||
package cn.iocoder.yudao.module.mp.mq.message;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
 | 
					 | 
				
			||||||
import lombok.Data;
 | 
					 | 
				
			||||||
import lombok.EqualsAndHashCode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 公众号账号刷新 Message
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author 芋道源码
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Data
 | 
					 | 
				
			||||||
@EqualsAndHashCode(callSuper = true)
 | 
					 | 
				
			||||||
public class MpAccountRefreshMessage extends AbstractChannelMessage {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public String getChannel() {
 | 
					 | 
				
			||||||
        return "mp.account.refresh";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,28 +0,0 @@
 | 
				
			|||||||
package cn.iocoder.yudao.module.mp.mq.producer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.module.mp.mq.message.MpAccountRefreshMessage;
 | 
					 | 
				
			||||||
import org.springframework.stereotype.Component;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.annotation.Resource;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * 公众号账号 Producer
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author 芋道源码
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Component
 | 
					 | 
				
			||||||
public class MpAccountProducer {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private RedisMQTemplate redisMQTemplate;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * 发送 {@link MpAccountRefreshMessage} 消息
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void sendAccountRefreshMessage() {
 | 
					 | 
				
			||||||
        MpAccountRefreshMessage message = new MpAccountRefreshMessage();
 | 
					 | 
				
			||||||
        redisMQTemplate.send(message);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
package cn.iocoder.yudao.module.mp.service.account;
 | 
					package cn.iocoder.yudao.module.mp.service.account;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import cn.hutool.core.collection.CollUtil;
 | 
				
			||||||
import cn.hutool.core.util.ObjUtil;
 | 
					import cn.hutool.core.util.ObjUtil;
 | 
				
			||||||
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 | 
					import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 | 
				
			||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
					import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
				
			||||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 | 
					 | 
				
			||||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
 | 
					import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
 | 
				
			||||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO;
 | 
					import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountCreateReqVO;
 | 
				
			||||||
import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO;
 | 
					import cn.iocoder.yudao.module.mp.controller.admin.account.vo.MpAccountPageReqVO;
 | 
				
			||||||
@@ -13,7 +13,6 @@ import cn.iocoder.yudao.module.mp.dal.dataobject.account.MpAccountDO;
 | 
				
			|||||||
import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper;
 | 
					import cn.iocoder.yudao.module.mp.dal.mysql.account.MpAccountMapper;
 | 
				
			||||||
import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants;
 | 
					import cn.iocoder.yudao.module.mp.enums.ErrorCodeConstants;
 | 
				
			||||||
import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
 | 
					import cn.iocoder.yudao.module.mp.framework.mp.core.MpServiceFactory;
 | 
				
			||||||
import cn.iocoder.yudao.module.mp.mq.producer.MpAccountProducer;
 | 
					 | 
				
			||||||
import com.google.common.annotations.VisibleForTesting;
 | 
					import com.google.common.annotations.VisibleForTesting;
 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
@@ -21,15 +20,20 @@ import me.chanjar.weixin.common.error.WxErrorException;
 | 
				
			|||||||
import me.chanjar.weixin.mp.api.WxMpService;
 | 
					import me.chanjar.weixin.mp.api.WxMpService;
 | 
				
			||||||
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
 | 
					import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
 | 
				
			||||||
import org.springframework.context.annotation.Lazy;
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
 | 
					import org.springframework.scheduling.annotation.Scheduled;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
import org.springframework.validation.annotation.Validated;
 | 
					import org.springframework.validation.annotation.Validated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.annotation.PostConstruct;
 | 
					import javax.annotation.PostConstruct;
 | 
				
			||||||
import javax.annotation.Resource;
 | 
					import javax.annotation.Resource;
 | 
				
			||||||
 | 
					import java.time.LocalDateTime;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.concurrent.TimeUnit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
					import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 | 
				
			||||||
 | 
					import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
 | 
				
			||||||
 | 
					import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMaxValue;
 | 
				
			||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS;
 | 
					import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -58,9 +62,6 @@ public class MpAccountServiceImpl implements MpAccountService {
 | 
				
			|||||||
    @Lazy // 延迟加载,解决循环依赖的问题
 | 
					    @Lazy // 延迟加载,解决循环依赖的问题
 | 
				
			||||||
    private MpServiceFactory mpServiceFactory;
 | 
					    private MpServiceFactory mpServiceFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Resource
 | 
					 | 
				
			||||||
    private MpAccountProducer mpAccountProducer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    @PostConstruct
 | 
					    @PostConstruct
 | 
				
			||||||
    public void initLocalCache() {
 | 
					    public void initLocalCache() {
 | 
				
			||||||
@@ -72,7 +73,30 @@ public class MpAccountServiceImpl implements MpAccountService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // 第二步:构建缓存。创建或更新支付 Client
 | 
					            // 第二步:构建缓存。创建或更新支付 Client
 | 
				
			||||||
            mpServiceFactory.init(accounts);
 | 
					            mpServiceFactory.init(accounts);
 | 
				
			||||||
            accountCache = CollectionUtils.convertMap(accounts, MpAccountDO::getAppId);
 | 
					            accountCache = convertMap(accounts, MpAccountDO::getAppId);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 通过定时任务轮询,刷新缓存
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * 目的:多节点部署时,通过轮询”通知“所有节点,进行刷新
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Scheduled(initialDelay = 60, fixedRate = 60, timeUnit = TimeUnit.SECONDS)
 | 
				
			||||||
 | 
					    public void refreshLocalCache() {
 | 
				
			||||||
 | 
					        // 注意:忽略自动多租户,因为要全局初始化缓存
 | 
				
			||||||
 | 
					        TenantUtils.executeIgnore(() -> {
 | 
				
			||||||
 | 
					            // 情况一:如果缓存里没有数据,则直接刷新缓存
 | 
				
			||||||
 | 
					            if (CollUtil.isEmpty(accountCache)) {
 | 
				
			||||||
 | 
					                initLocalCache();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // 情况二,如果缓存里数据,则通过 updateTime 判断是否有数据变更,有变更则刷新缓存
 | 
				
			||||||
 | 
					            LocalDateTime maxTime = getMaxValue(accountCache.values(), MpAccountDO::getUpdateTime);
 | 
				
			||||||
 | 
					            if (mpAccountMapper.selectCountByUpdateTimeGt(maxTime) > 0) {
 | 
				
			||||||
 | 
					                initLocalCache();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -85,8 +109,8 @@ public class MpAccountServiceImpl implements MpAccountService {
 | 
				
			|||||||
        MpAccountDO account = MpAccountConvert.INSTANCE.convert(createReqVO);
 | 
					        MpAccountDO account = MpAccountConvert.INSTANCE.convert(createReqVO);
 | 
				
			||||||
        mpAccountMapper.insert(account);
 | 
					        mpAccountMapper.insert(account);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 发送刷新消息
 | 
					        // 刷新缓存
 | 
				
			||||||
        mpAccountProducer.sendAccountRefreshMessage();
 | 
					        initLocalCache();
 | 
				
			||||||
        return account.getId();
 | 
					        return account.getId();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,8 +125,8 @@ public class MpAccountServiceImpl implements MpAccountService {
 | 
				
			|||||||
        MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO);
 | 
					        MpAccountDO updateObj = MpAccountConvert.INSTANCE.convert(updateReqVO);
 | 
				
			||||||
        mpAccountMapper.updateById(updateObj);
 | 
					        mpAccountMapper.updateById(updateObj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 发送刷新消息
 | 
					        // 刷新缓存
 | 
				
			||||||
        mpAccountProducer.sendAccountRefreshMessage();
 | 
					        initLocalCache();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
@@ -112,8 +136,8 @@ public class MpAccountServiceImpl implements MpAccountService {
 | 
				
			|||||||
        // 删除
 | 
					        // 删除
 | 
				
			||||||
        mpAccountMapper.deleteById(id);
 | 
					        mpAccountMapper.deleteById(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 发送刷新消息
 | 
					        // 刷新缓存
 | 
				
			||||||
        mpAccountProducer.sendAccountRefreshMessage();
 | 
					        initLocalCache();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private MpAccountDO validateAccountExists(Long id) {
 | 
					    private MpAccountDO validateAccountExists(Long id) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,6 @@ import lombok.Data;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * 支付单信息 Response DTO
 | 
					 * 支付单信息 Response DTO
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * TODO 芋艿:还没定好字段
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author 芋道源码
 | 
					 * @author 芋道源码
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,8 +8,6 @@ import java.time.LocalDateTime;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * 退款单信息 Response DTO
 | 
					 * 退款单信息 Response DTO
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * TODO 芋艿:还没定好字段
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author 芋道源码
 | 
					 * @author 芋道源码
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Data
 | 
					@Data
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,12 +61,6 @@
 | 
				
			|||||||
            <artifactId>yudao-spring-boot-starter-job</artifactId>
 | 
					            <artifactId>yudao-spring-boot-starter-job</artifactId>
 | 
				
			||||||
        </dependency>
 | 
					        </dependency>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- 消息队列相关 -->
 | 
					 | 
				
			||||||
        <dependency>
 | 
					 | 
				
			||||||
            <groupId>cn.iocoder.boot</groupId>
 | 
					 | 
				
			||||||
            <artifactId>yudao-spring-boot-starter-mq</artifactId>
 | 
					 | 
				
			||||||
        </dependency>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        <!-- Test 测试相关 -->
 | 
					        <!-- Test 测试相关 -->
 | 
				
			||||||
        <dependency>
 | 
					        <dependency>
 | 
				
			||||||
            <groupId>cn.iocoder.boot</groupId>
 | 
					            <groupId>cn.iocoder.boot</groupId>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR
 | 
				
			|||||||
import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert;
 | 
					import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert;
 | 
				
			||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
 | 
					import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
 | 
				
			||||||
import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
 | 
					import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
 | 
				
			||||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
 | 
					 | 
				
			||||||
import lombok.Getter;
 | 
					import lombok.Getter;
 | 
				
			||||||
import lombok.Setter;
 | 
					import lombok.Setter;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
@@ -112,7 +111,7 @@ public class PayChannelServiceImpl implements PayChannelService {
 | 
				
			|||||||
        channelMapper.insert(channel);
 | 
					        channelMapper.insert(channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 刷新缓存
 | 
					        // 刷新缓存
 | 
				
			||||||
        refreshLocalCache();
 | 
					        initLocalCache();
 | 
				
			||||||
        return channel.getId();
 | 
					        return channel.getId();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,7 +126,7 @@ public class PayChannelServiceImpl implements PayChannelService {
 | 
				
			|||||||
        channelMapper.updateById(channel);
 | 
					        channelMapper.updateById(channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 刷新缓存
 | 
					        // 刷新缓存
 | 
				
			||||||
        refreshLocalCache();
 | 
					        initLocalCache();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@@ -160,7 +159,7 @@ public class PayChannelServiceImpl implements PayChannelService {
 | 
				
			|||||||
        channelMapper.deleteById(id);
 | 
					        channelMapper.deleteById(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 刷新缓存
 | 
					        // 刷新缓存
 | 
				
			||||||
        refreshLocalCache();
 | 
					        initLocalCache();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private PayChannelDO validateChannelExists(Long id) {
 | 
					    private PayChannelDO validateChannelExists(Long id) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -167,7 +167,8 @@ yudao:
 | 
				
			|||||||
      - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
 | 
					      - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
 | 
				
			||||||
      - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
 | 
					      - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
 | 
				
			||||||
  pay:
 | 
					  pay:
 | 
				
			||||||
    callback-url: http://yunai.natapp1.cc/admin-api/pay/notify/callback
 | 
					    order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
 | 
				
			||||||
 | 
					    refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
 | 
				
			||||||
  demo: true # 开启演示模式
 | 
					  demo: true # 开启演示模式
 | 
				
			||||||
 | 
					
 | 
				
			||||||
justauth:
 | 
					justauth:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user