首页 > 基础资料 博客日记
weixin-java-cp-demo:基于Spring Boot和WxJava实现的微信企业号集群环境配置
2024-11-05 21:00:07基础资料围观35次
文章weixin-java-cp-demo:基于Spring Boot和WxJava实现的微信企业号集群环境配置分享给大家,欢迎收藏Java资料网,专注分享技术知识
pom依赖
<dependencies>
<!--微信服务号第三方SDK-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
<version>${weixin-java}</version>
</dependency>
</dependencies>
Redis初始类
@Component
public class RedissonClientInitializer {
@Value("${wecom.redis.database}")
private int database;
@Value("${wecom.redis.host}")
private String host;
@Value("${wecom.redis.port}")
private String port;
@Value("${wecom.redis.password}")
private String password;
public RedissonClient initialize() {
Config config = new Config();
config.useSingleServer().setAddress(String.format("redis://%s:%s", this.host, this.port));
if (!this.password.isEmpty()) {
config.useSingleServer().setPassword(this.password);
}
config.useSingleServer().setDatabase(this.database);
StringCodec codec = new StringCodec();
config.setCodec(codec);
return Redisson.create(config);
}
}
企业微信配置类
@Configuration
@RequiredArgsConstructor
@Slf4j
public class WxCpConfiguration {
private final AccountMapper accountMapper;
private final TenantMapper tenantMapper;
private final RedissonClientInitializer initializer;
private static Map<String, WxCpService> cpServices = new ConcurrentHashMap<>();
public WxCpService getCpService(String corpId, Integer agentId) {
WxCpService cpService = cpServices.get(corpId + agentId);
if (!Optional.ofNullable(cpService).isPresent()) {
//若缓存中未找到,去数据库再查一次
Account account = accountMapper.selectOne(Wrappers.<Account>lambdaQuery().eq(Account::getUniqueId, corpId + agentId));
//若查询结果不为空,更新缓存
if (!ObjectUtils.isEmpty(account)) {
WxCpDefaultConfigImpl config = JSONObject.parseObject(account.getAccountConfig(), WxCpDefaultConfigImpl.class);
log.info("config:{}",config);
WxCpRedissonConfigImpl redissonConfig = new WxCpRedissonConfigImpl(initializer.initialize(), "workRedis:");
redissonConfig.setCorpId(config.getCorpId());
redissonConfig.setAgentId(config.getAgentId());
redissonConfig.setCorpSecret(config.getCorpSecret());
WxCpServiceImpl wxCpService = new WxCpServiceImpl();
wxCpService.setWxCpConfigStorage(redissonConfig);
setCpService(corpId, agentId, wxCpService);
log.info("缓存已更新:corpId:{},agentId:{}",corpId,agentId);
return wxCpService;
}
}
return Optional.ofNullable(cpService).orElseThrow(() -> {
log.error("未找到 corpId: {}, agentId: {} 对应的 WxCpService", corpId, agentId);
return new CommonException("未配置此service");
});
}
public static void setCpService(String corpId, Integer agentId,WxCpServiceImpl service) {
cpServices.put(corpId + agentId, service);
}
@PostConstruct
public void initServices() {
try {
List<Tenant> tenants = tenantMapper.selectList(Wrappers.emptyWrapper());
for (Tenant tenant : tenants) {
String dsKey = SecurityConstants.PROJECT_PREFIX + tenant.getTenantId();
DynamicDataSourceContextHolder.push(dsKey);
List<Account> accounts = accountMapper.selectList(new LambdaQueryWrapper<Account>().eq(Account::getSendChannel, 1));
// 提取 accountConfig 字段,并将其映射为 List<WxCpDefaultConfigImpl>
List<WxCpDefaultConfigImpl> list = accounts.stream()
.map(account -> JSON.parseObject(account.getAccountConfig(), WxCpDefaultConfigImpl.class))
.collect(Collectors.toList());
cpServices = list.stream().map(this::apply).filter(Optional::isPresent).map(Optional::get)
.collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getCorpId() + service.getWxCpConfigStorage().getAgentId(), a -> a));
}
} catch (Exception e) {
log.error("企业微信初始化失败",e);
} finally {
DynamicDataSourceContextHolder.clear();
}
}
private Optional<WxCpServiceImpl> apply(WxCpDefaultConfigImpl a) {
if (ObjectUtils.isEmpty(a)) {
Optional.ofNullable(new WxCpServiceImpl());
}
WxCpRedissonConfigImpl config = new WxCpRedissonConfigImpl(initializer.initialize(), "workRedis:");
config.setCorpId(a.getCorpId());
config.setAgentId(a.getAgentId());
config.setCorpSecret(a.getCorpSecret());
config.setToken(a.getToken());
config.setAesKey(a.getAesKey());
val service = new WxCpServiceImpl();
service.setWxCpConfigStorage(config);
log.info("初始化企业微信服务:corpId:{},agentId:{}",a.getCorpId(),a.getAgentId());
return Optional.of(service);
}
}
企业微信保存
@PostMapping("/wecom/save")
@ApiOperation("企业微信保存数据")
public R saveWecom(@RequestBody WxCpAccountDTO channelAccount) {
AccountService accountService = accountServiceFactory.getAccountService(ENTERPRISE_WE_CHAT_SERVICE_NAME+ACCOUNT);
accountService.save(channelAccount);
return R.ok();
}
@Override
@Transactional
public void save(WxCpAccountDTO accountDTO) {
//校验账号是否存在
Account existAccount = getExistAccount(accountDTO.getConfig());
if (existAccount != null) {
throw new CommonException("07020004", existAccount.getName(), userInfoMapper.selectByUsername(existAccount.getCreateBy()).getTrueName());
}// 处理企业微信渠道的逻辑
WxCpDefaultConfigImpl config = BeanCopyUtils.turnToVO(accountDTO.getConfig(), WxCpDefaultConfigImpl.class);
WxCpServiceImpl wxCpService = new WxCpServiceImpl();
wxCpService.setWxCpConfigStorage(config);
String name;
try {
WxCpAgent wxCpAgent = wxCpService.getAgentService().get(config.getAgentId());
name = wxCpAgent.getName();
String cover = wxCpAgent.getSquareLogoUrl();
accountDTO.setName(name);
accountDTO.setCover(cover);
accountDTO.setAccountConfig(JSONObject.toJSONString(accountDTO.getConfig()));
accountDTO.setUniqueId(config.getCorpId() + config.getAgentId());
//更新缓存
WxCpRedissonConfigImpl redissonConfig = new WxCpRedissonConfigImpl(initializer.initialize(), "workRedis:");
redissonConfig.setCorpId(config.getCorpId());
redissonConfig.setAgentId(config.getAgentId());
redissonConfig.setCorpSecret(config.getCorpSecret());
wxCpService.setWxCpConfigStorage(redissonConfig);
WxCpConfiguration.setCpService(config.getCorpId(), config.getAgentId(), wxCpService);
} catch (WxErrorException e) {
log.error("企业微信用户信息绑定失败:", e);
throw new CommonException("07020002", WxCpErrorMsgEnum.findMsgByCode(e.getError().getErrorCode()));
}
// 其他保存逻辑
accountDomainService.save(accountDTO);
}
账号表
@Data
@TableName("new_media_account")
@Accessors(chain = true)
public class Account extends BaseDomain {
/**
* 账号名称
*/
private String name;
/**
* 唯一id
*/
private String uniqueId;
/**
* 头像
*/
private String cover;
/**
* 发送渠道
*/
private Integer sendChannel;
/**
* 账号配置
*/
private String accountConfig;
/**
* 账号状态 0-登录失效 1-登录成功
*/
private Integer status;
}
基类
@Getter
@Setter
@Accessors(chain = true)
public class BaseDomain extends BaseEntity{
/**
* 自增主键
*/
private Integer autoPk;
/**
* 业务主键
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* 租户id
*/
@TableField(fill = FieldFill.INSERT)
private Integer tenantId;
@TableField(exist=false)
private Integer tenantIdManual;
@TableField(exist=false)
private Long groupByCount;
/**
* 逻辑删除的标记位(0:否,1:是)
* 赋予默认值是为了批量新增的时候不报非空字段的错误
*/
@TableLogic
private Integer isDelete=0;
public Long generateId(){
IdentifierGenerator identifierGenerator = SpringContextHolder.getBean(IdentifierGenerator.class);
Number number = identifierGenerator.nextId(this);
this.setId(number.longValue());
return getId();
}
}
@Getter
@Setter
@Accessors(chain = true)
public class BaseEntity implements Serializable {
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
文章来源:https://blog.csdn.net/qq_17287341/article/details/141864204
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: