mirror of
				https://gitee.com/binary/weixin-java-tools.git
				synced 2025-11-01 03:25:35 +08:00 
			
		
		
		
	🆕 #3372【视频号】增加支持多视频号账号的spring-boot-starter组件
This commit is contained in:
		| @ -0,0 +1,15 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.autoconfigure; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.configuration.WxChannelMultiServiceConfiguration; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.context.annotation.Import; | ||||
|  | ||||
| /** | ||||
|  * 微信视频号自动注册 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Configuration | ||||
| @Import(WxChannelMultiServiceConfiguration.class) | ||||
| public class WxChannelMultiAutoConfiguration {} | ||||
| @ -0,0 +1,21 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.configuration; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.configuration.services.WxChannelInJedisConfiguration; | ||||
| import com.binarywang.spring.starter.wxjava.channel.configuration.services.WxChannelInMemoryConfiguration; | ||||
| import com.binarywang.spring.starter.wxjava.channel.configuration.services.WxChannelInRedisTemplateConfiguration; | ||||
| import com.binarywang.spring.starter.wxjava.channel.configuration.services.WxChannelInRedissonConfiguration; | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiProperties; | ||||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.context.annotation.Import; | ||||
|  | ||||
| /** | ||||
|  * 微信视频号相关服务自动注册 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Configuration | ||||
| @EnableConfigurationProperties(WxChannelMultiProperties.class) | ||||
| @Import({WxChannelInJedisConfiguration.class, WxChannelInMemoryConfiguration.class, WxChannelInRedissonConfiguration.class, WxChannelInRedisTemplateConfiguration.class}) | ||||
| public class WxChannelMultiServiceConfiguration {} | ||||
| @ -0,0 +1,140 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.configuration.services; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.enums.HttpClientType; | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelSingleProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.service.WxChannelMultiServices; | ||||
| import com.binarywang.spring.starter.wxjava.channel.service.WxChannelMultiServicesImpl; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import me.chanjar.weixin.channel.api.WxChannelService; | ||||
| import me.chanjar.weixin.channel.api.impl.WxChannelServiceHttpClientImpl; | ||||
| import me.chanjar.weixin.channel.api.impl.WxChannelServiceImpl; | ||||
| import me.chanjar.weixin.channel.config.WxChannelConfig; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| /** | ||||
|  * WxChannelConfigStorage 抽象配置类 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @RequiredArgsConstructor | ||||
| @Slf4j | ||||
| public abstract class AbstractWxChannelConfiguration { | ||||
|   protected WxChannelMultiServices wxChannelMultiServices(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     Map<String, WxChannelSingleProperties> appsMap = wxChannelMultiProperties.getApps(); | ||||
|     if (appsMap == null || appsMap.isEmpty()) { | ||||
|       log.warn("微信视频号应用参数未配置,通过 WxChannelMultiServices#getWxChannelService(\"tenantId\")获取实例将返回空"); | ||||
|       return new WxChannelMultiServicesImpl(); | ||||
|     } | ||||
|     /** | ||||
|      * 校验 appId 是否唯一,避免使用 redis 缓存 token、ticket 时错乱。 | ||||
|      * | ||||
|      * 查看 {@link me.chanjar.weixin.channel.config.impl.WxChannelRedisConfigImpl#setAppid(String)} | ||||
|      */ | ||||
|     Collection<WxChannelSingleProperties> apps = appsMap.values(); | ||||
|     if (apps.size() > 1) { | ||||
|       // 校验 appId 是否唯一 | ||||
|       boolean multi = apps.stream() | ||||
|         // 没有 appId,如果不判断是否为空,这里会报 NPE 异常 | ||||
|         .collect(Collectors.groupingBy(c -> c.getAppId() == null ? 0 : c.getAppId(), Collectors.counting())) | ||||
|         .entrySet().stream().anyMatch(e -> e.getValue() > 1); | ||||
|       if (multi) { | ||||
|         throw new RuntimeException("请确保微信视频号配置 appId 的唯一性"); | ||||
|       } | ||||
|     } | ||||
|     WxChannelMultiServicesImpl services = new WxChannelMultiServicesImpl(); | ||||
|  | ||||
|     Set<Map.Entry<String, WxChannelSingleProperties>> entries = appsMap.entrySet(); | ||||
|     for (Map.Entry<String, WxChannelSingleProperties> entry : entries) { | ||||
|       String tenantId = entry.getKey(); | ||||
|       WxChannelSingleProperties wxChannelSingleProperties = entry.getValue(); | ||||
|       WxChannelDefaultConfigImpl storage = this.wxChannelConfigStorage(wxChannelMultiProperties); | ||||
|       this.configApp(storage, wxChannelSingleProperties); | ||||
|       this.configHttp(storage, wxChannelMultiProperties.getConfigStorage()); | ||||
|       WxChannelService wxChannelService = this.wxChannelService(storage, wxChannelMultiProperties, wxChannelSingleProperties.isUseStableAccessToken()); | ||||
|       services.addWxChannelService(tenantId, wxChannelService); | ||||
|     } | ||||
|     return services; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * 配置 WxChannelDefaultConfigImpl | ||||
|    * | ||||
|    * @param wxChannelMultiProperties 参数 | ||||
|    * @return WxChannelDefaultConfigImpl | ||||
|    */ | ||||
|   protected abstract WxChannelDefaultConfigImpl wxChannelConfigStorage(WxChannelMultiProperties wxChannelMultiProperties); | ||||
|  | ||||
|   public WxChannelService wxChannelService(WxChannelConfig wxChannelConfig, WxChannelMultiProperties wxChannelMultiProperties, boolean useStableAccessToken) { | ||||
|     WxChannelMultiProperties.ConfigStorage storage = wxChannelMultiProperties.getConfigStorage(); | ||||
|     HttpClientType httpClientType = storage.getHttpClientType(); | ||||
|     WxChannelService wxChannelService; | ||||
|     switch (httpClientType) { | ||||
| //      case OK_HTTP: | ||||
| //        wxChannelService = new WxChannelServiceOkHttpImpl(false, false); | ||||
| //        break; | ||||
|       case HTTP_CLIENT: | ||||
|         wxChannelService = new WxChannelServiceHttpClientImpl(useStableAccessToken, false); | ||||
|         break; | ||||
|       default: | ||||
|         wxChannelService = new WxChannelServiceImpl(); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     wxChannelService.setConfig(wxChannelConfig); | ||||
|     int maxRetryTimes = storage.getMaxRetryTimes(); | ||||
|     if (maxRetryTimes < 0) { | ||||
|       maxRetryTimes = 0; | ||||
|     } | ||||
|     int retrySleepMillis = storage.getRetrySleepMillis(); | ||||
|     if (retrySleepMillis < 0) { | ||||
|       retrySleepMillis = 1000; | ||||
|     } | ||||
|     wxChannelService.setRetrySleepMillis(retrySleepMillis); | ||||
|     wxChannelService.setMaxRetryTimes(maxRetryTimes); | ||||
|     return wxChannelService; | ||||
|   } | ||||
|  | ||||
|   private void configApp(WxChannelDefaultConfigImpl config, WxChannelSingleProperties wxChannelSingleProperties) { | ||||
|     String appId = wxChannelSingleProperties.getAppId(); | ||||
|     String appSecret = wxChannelSingleProperties.getSecret(); | ||||
|     String token = wxChannelSingleProperties.getToken(); | ||||
|     String aesKey = wxChannelSingleProperties.getAesKey(); | ||||
|  | ||||
|     config.setAppid(appId); | ||||
|     config.setSecret(appSecret); | ||||
|     if (StringUtils.isNotBlank(token)) { | ||||
|       config.setToken(token); | ||||
|     } | ||||
|     if (StringUtils.isNotBlank(aesKey)) { | ||||
|       config.setAesKey(aesKey); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private void configHttp(WxChannelDefaultConfigImpl config, WxChannelMultiProperties.ConfigStorage storage) { | ||||
|     String httpProxyHost = storage.getHttpProxyHost(); | ||||
|     Integer httpProxyPort = storage.getHttpProxyPort(); | ||||
|     String httpProxyUsername = storage.getHttpProxyUsername(); | ||||
|     String httpProxyPassword = storage.getHttpProxyPassword(); | ||||
|     if (StringUtils.isNotBlank(httpProxyHost)) { | ||||
|       config.setHttpProxyHost(httpProxyHost); | ||||
|       if (httpProxyPort != null) { | ||||
|         config.setHttpProxyPort(httpProxyPort); | ||||
|       } | ||||
|       if (StringUtils.isNotBlank(httpProxyUsername)) { | ||||
|         config.setHttpProxyUsername(httpProxyUsername); | ||||
|       } | ||||
|       if (StringUtils.isNotBlank(httpProxyPassword)) { | ||||
|         config.setHttpProxyPassword(httpProxyPassword); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,74 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.configuration.services; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiRedisProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.service.WxChannelMultiServices; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelRedisConfigImpl; | ||||
| import me.chanjar.weixin.common.redis.JedisWxRedisOps; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import redis.clients.jedis.JedisPool; | ||||
| import redis.clients.jedis.JedisPoolConfig; | ||||
|  | ||||
| /** | ||||
|  * 自动装配基于 jedis 策略配置 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Configuration | ||||
| @ConditionalOnProperty(prefix = WxChannelMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "jedis") | ||||
| @RequiredArgsConstructor | ||||
| public class WxChannelInJedisConfiguration extends AbstractWxChannelConfiguration { | ||||
|   private final WxChannelMultiProperties wxChannelMultiProperties; | ||||
|   private final ApplicationContext applicationContext; | ||||
|  | ||||
|   @Bean | ||||
|   public WxChannelMultiServices wxChannelMultiServices() { | ||||
|     return this.wxChannelMultiServices(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   protected WxChannelDefaultConfigImpl wxChannelConfigStorage(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     return this.configRedis(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   private WxChannelDefaultConfigImpl configRedis(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     WxChannelMultiRedisProperties wxChannelMultiRedisProperties = wxChannelMultiProperties.getConfigStorage().getRedis(); | ||||
|     JedisPool jedisPool; | ||||
|     if (wxChannelMultiRedisProperties != null && StringUtils.isNotEmpty(wxChannelMultiRedisProperties.getHost())) { | ||||
|       jedisPool = getJedisPool(wxChannelMultiProperties); | ||||
|     } else { | ||||
|       jedisPool = applicationContext.getBean(JedisPool.class); | ||||
|     } | ||||
|     return new WxChannelRedisConfigImpl(new JedisWxRedisOps(jedisPool), wxChannelMultiProperties.getConfigStorage().getKeyPrefix()); | ||||
|   } | ||||
|  | ||||
|   private JedisPool getJedisPool(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     WxChannelMultiProperties.ConfigStorage storage = wxChannelMultiProperties.getConfigStorage(); | ||||
|     WxChannelMultiRedisProperties redis = storage.getRedis(); | ||||
|  | ||||
|     JedisPoolConfig config = new JedisPoolConfig(); | ||||
|     if (redis.getMaxActive() != null) { | ||||
|       config.setMaxTotal(redis.getMaxActive()); | ||||
|     } | ||||
|     if (redis.getMaxIdle() != null) { | ||||
|       config.setMaxIdle(redis.getMaxIdle()); | ||||
|     } | ||||
|     if (redis.getMaxWaitMillis() != null) { | ||||
|       config.setMaxWaitMillis(redis.getMaxWaitMillis()); | ||||
|     } | ||||
|     if (redis.getMinIdle() != null) { | ||||
|       config.setMinIdle(redis.getMinIdle()); | ||||
|     } | ||||
|     config.setTestOnBorrow(true); | ||||
|     config.setTestWhileIdle(true); | ||||
|  | ||||
|     return new JedisPool(config, redis.getHost(), redis.getPort(), redis.getTimeout(), redis.getPassword(), redis.getDatabase()); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,36 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.configuration.services; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.service.WxChannelMultiServices; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
|  | ||||
| /** | ||||
|  * 自动装配基于内存策略配置 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Configuration | ||||
| @ConditionalOnProperty(prefix = WxChannelMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "memory", matchIfMissing = true) | ||||
| @RequiredArgsConstructor | ||||
| public class WxChannelInMemoryConfiguration extends AbstractWxChannelConfiguration { | ||||
|   private final WxChannelMultiProperties wxChannelMultiProperties; | ||||
|  | ||||
|   @Bean | ||||
|   public WxChannelMultiServices wxChannelMultiServices() { | ||||
|     return this.wxChannelMultiServices(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   protected WxChannelDefaultConfigImpl wxChannelConfigStorage(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     return this.configInMemory(); | ||||
|   } | ||||
|  | ||||
|   private WxChannelDefaultConfigImpl configInMemory() { | ||||
|     return new WxChannelDefaultConfigImpl(); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,42 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.configuration.services; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.service.WxChannelMultiServices; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelRedisConfigImpl; | ||||
| import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.data.redis.core.StringRedisTemplate; | ||||
|  | ||||
| /** | ||||
|  * 自动装配基于 redisTemplate 策略配置 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Configuration | ||||
| @ConditionalOnProperty(prefix = WxChannelMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "redis_template") | ||||
| @RequiredArgsConstructor | ||||
| public class WxChannelInRedisTemplateConfiguration extends AbstractWxChannelConfiguration { | ||||
|   private final WxChannelMultiProperties wxChannelMultiProperties; | ||||
|   private final ApplicationContext applicationContext; | ||||
|  | ||||
|   @Bean | ||||
|   public WxChannelMultiServices wxChannelMultiServices() { | ||||
|     return this.wxChannelMultiServices(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   protected WxChannelDefaultConfigImpl wxChannelConfigStorage(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     return this.configRedisTemplate(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   private WxChannelDefaultConfigImpl configRedisTemplate(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     StringRedisTemplate redisTemplate = applicationContext.getBean(StringRedisTemplate.class); | ||||
|     return new WxChannelRedisConfigImpl(new RedisTemplateWxRedisOps(redisTemplate), wxChannelMultiProperties.getConfigStorage().getKeyPrefix()); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,62 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.configuration.services; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.properties.WxChannelMultiRedisProperties; | ||||
| import com.binarywang.spring.starter.wxjava.channel.service.WxChannelMultiServices; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelDefaultConfigImpl; | ||||
| import me.chanjar.weixin.channel.config.impl.WxChannelRedissonConfigImpl; | ||||
| import org.apache.commons.lang3.StringUtils; | ||||
| import org.redisson.Redisson; | ||||
| import org.redisson.api.RedissonClient; | ||||
| import org.redisson.config.Config; | ||||
| import org.redisson.config.TransportMode; | ||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
|  | ||||
| /** | ||||
|  * 自动装配基于 redisson 策略配置 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Configuration | ||||
| @ConditionalOnProperty(prefix = WxChannelMultiProperties.PREFIX + ".config-storage", name = "type", havingValue = "redisson") | ||||
| @RequiredArgsConstructor | ||||
| public class WxChannelInRedissonConfiguration extends AbstractWxChannelConfiguration { | ||||
|   private final WxChannelMultiProperties wxChannelMultiProperties; | ||||
|   private final ApplicationContext applicationContext; | ||||
|  | ||||
|   @Bean | ||||
|   public WxChannelMultiServices wxChannelMultiServices() { | ||||
|     return this.wxChannelMultiServices(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   protected WxChannelDefaultConfigImpl wxChannelConfigStorage(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     return this.configRedisson(wxChannelMultiProperties); | ||||
|   } | ||||
|  | ||||
|   private WxChannelDefaultConfigImpl configRedisson(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     WxChannelMultiRedisProperties redisProperties = wxChannelMultiProperties.getConfigStorage().getRedis(); | ||||
|     RedissonClient redissonClient; | ||||
|     if (redisProperties != null && StringUtils.isNotEmpty(redisProperties.getHost())) { | ||||
|       redissonClient = getRedissonClient(wxChannelMultiProperties); | ||||
|     } else { | ||||
|       redissonClient = applicationContext.getBean(RedissonClient.class); | ||||
|     } | ||||
|     return new WxChannelRedissonConfigImpl(redissonClient, wxChannelMultiProperties.getConfigStorage().getKeyPrefix()); | ||||
|   } | ||||
|  | ||||
|   private RedissonClient getRedissonClient(WxChannelMultiProperties wxChannelMultiProperties) { | ||||
|     WxChannelMultiProperties.ConfigStorage storage = wxChannelMultiProperties.getConfigStorage(); | ||||
|     WxChannelMultiRedisProperties redis = storage.getRedis(); | ||||
|  | ||||
|     Config config = new Config(); | ||||
|     config.useSingleServer().setAddress("redis://" + redis.getHost() + ":" + redis.getPort()).setDatabase(redis.getDatabase()).setPassword(redis.getPassword()); | ||||
|     config.setTransportMode(TransportMode.NIO); | ||||
|     return Redisson.create(config); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.enums; | ||||
|  | ||||
| /** | ||||
|  * httpclient类型 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| public enum HttpClientType { | ||||
|   /** | ||||
|    * HttpClient | ||||
|    */ | ||||
|   HTTP_CLIENT, | ||||
|   // WxChannelServiceOkHttpImpl 实现经测试无法正常完成业务固暂不支持OK_HTTP方式 | ||||
| //  /** | ||||
| //   * OkHttp. | ||||
| //   */ | ||||
| //  OK_HTTP, | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.enums; | ||||
|  | ||||
| /** | ||||
|  * storage类型 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| public enum StorageType { | ||||
|   /** | ||||
|    * 内存 | ||||
|    */ | ||||
|   MEMORY, | ||||
|   /** | ||||
|    * redis(JedisClient) | ||||
|    */ | ||||
|   JEDIS, | ||||
|   /** | ||||
|    * redis(Redisson) | ||||
|    */ | ||||
|   REDISSON, | ||||
|   /** | ||||
|    * redis(RedisTemplate) | ||||
|    */ | ||||
|   REDIS_TEMPLATE | ||||
| } | ||||
| @ -0,0 +1,96 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.properties; | ||||
|  | ||||
| import com.binarywang.spring.starter.wxjava.channel.enums.HttpClientType; | ||||
| import com.binarywang.spring.starter.wxjava.channel.enums.StorageType; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | ||||
| import org.springframework.boot.context.properties.NestedConfigurationProperty; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * 微信多视频号接入相关配置属性 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| @ConfigurationProperties(WxChannelMultiProperties.PREFIX) | ||||
| public class WxChannelMultiProperties implements Serializable { | ||||
|   private static final long serialVersionUID = - 8361973118805546037L; | ||||
|   public static final String PREFIX = "wx.channel"; | ||||
|  | ||||
|   private Map<String, WxChannelSingleProperties> apps = new HashMap<>(); | ||||
|  | ||||
|   /** | ||||
|    * 存储策略 | ||||
|    */ | ||||
|   private final ConfigStorage configStorage = new ConfigStorage(); | ||||
|  | ||||
|   @Data | ||||
|   @NoArgsConstructor | ||||
|   public static class ConfigStorage implements Serializable { | ||||
|     private static final long serialVersionUID = - 5152619132544179942L; | ||||
|  | ||||
|     /** | ||||
|      * 存储类型. | ||||
|      */ | ||||
|     private StorageType type = StorageType.MEMORY; | ||||
|  | ||||
|     /** | ||||
|      * 指定key前缀. | ||||
|      */ | ||||
|     private String keyPrefix = "wx:channel:multi"; | ||||
|  | ||||
|     /** | ||||
|      * redis连接配置. | ||||
|      */ | ||||
|     @NestedConfigurationProperty | ||||
|     private final WxChannelMultiRedisProperties redis = new WxChannelMultiRedisProperties(); | ||||
|  | ||||
|     /** | ||||
|      * http客户端类型. | ||||
|      */ | ||||
|     private HttpClientType httpClientType = HttpClientType.HTTP_CLIENT; | ||||
|  | ||||
|     /** | ||||
|      * http代理主机. | ||||
|      */ | ||||
|     private String httpProxyHost; | ||||
|  | ||||
|     /** | ||||
|      * http代理端口. | ||||
|      */ | ||||
|     private Integer httpProxyPort; | ||||
|  | ||||
|     /** | ||||
|      * http代理用户名. | ||||
|      */ | ||||
|     private String httpProxyUsername; | ||||
|  | ||||
|     /** | ||||
|      * http代理密码. | ||||
|      */ | ||||
|     private String httpProxyPassword; | ||||
|  | ||||
|     /** | ||||
|      * http 请求最大重试次数 | ||||
|      * | ||||
|      * <p>{@link me.chanjar.weixin.channel.api.WxChannelService#setMaxRetryTimes(int)}</p> | ||||
|      * <p>{@link me.chanjar.weixin.channel.api.impl.BaseWxChannelServiceImpl#setMaxRetryTimes(int)}</p> | ||||
|      */ | ||||
|     private int maxRetryTimes = 5; | ||||
|  | ||||
|     /** | ||||
|      * http 请求重试间隔 | ||||
|      * | ||||
|      * <p>{@link me.chanjar.weixin.channel.api.WxChannelService#setRetrySleepMillis(int)}</p> | ||||
|      * <p>{@link me.chanjar.weixin.channel.api.impl.BaseWxChannelServiceImpl#setRetrySleepMillis(int)}</p> | ||||
|      */ | ||||
|     private int retrySleepMillis = 1000; | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,63 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.properties; | ||||
|  | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * Redis配置 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| public class WxChannelMultiRedisProperties implements Serializable { | ||||
|   private static final long serialVersionUID = 9061055444734277357L; | ||||
|  | ||||
|   /** | ||||
|    * 主机地址. | ||||
|    */ | ||||
|   private String host = "127.0.0.1"; | ||||
|  | ||||
|   /** | ||||
|    * 端口号. | ||||
|    */ | ||||
|   private int port = 6379; | ||||
|  | ||||
|   /** | ||||
|    * 密码. | ||||
|    */ | ||||
|   private String password; | ||||
|  | ||||
|   /** | ||||
|    * 超时. | ||||
|    */ | ||||
|   private int timeout = 2000; | ||||
|  | ||||
|   /** | ||||
|    * 数据库. | ||||
|    */ | ||||
|   private int database = 0; | ||||
|  | ||||
|   /** | ||||
|    * 最大活动连接数 | ||||
|    */ | ||||
|   private Integer maxActive; | ||||
|  | ||||
|   /** | ||||
|    * 最大空闲连接数 | ||||
|    */ | ||||
|   private Integer maxIdle; | ||||
|  | ||||
|   /** | ||||
|    * 最小空闲连接数 | ||||
|    */ | ||||
|   private Integer minIdle; | ||||
|  | ||||
|   /** | ||||
|    * 最大等待时间 | ||||
|    */ | ||||
|   private Integer maxWaitMillis; | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.properties; | ||||
|  | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * 微信视频号相关配置属性 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| public class WxChannelSingleProperties implements Serializable { | ||||
|   private static final long serialVersionUID = 5306630351265124825L; | ||||
|  | ||||
|   /** | ||||
|    * 设置微信视频号的 appid. | ||||
|    */ | ||||
|   private String appId; | ||||
|  | ||||
|   /** | ||||
|    * 设置微信视频号的 secret. | ||||
|    */ | ||||
|   private String secret; | ||||
|  | ||||
|   /** | ||||
|    * 设置微信视频号的 token. | ||||
|    */ | ||||
|   private String token; | ||||
|  | ||||
|   /** | ||||
|    * 设置微信视频号的 EncodingAESKey. | ||||
|    */ | ||||
|   private String aesKey; | ||||
|  | ||||
|   /** | ||||
|    * 是否使用稳定版 Access Token | ||||
|    */ | ||||
|   private boolean useStableAccessToken = false; | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.service; | ||||
|  | ||||
| import me.chanjar.weixin.channel.api.WxChannelService; | ||||
|  | ||||
| /** | ||||
|  * 视频号 {@link WxChannelService} 所有实例存放类. | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| public interface WxChannelMultiServices { | ||||
|   /** | ||||
|    * 通过租户 Id 获取 WxChannelService | ||||
|    * | ||||
|    * @param tenantId 租户 Id | ||||
|    * @return WxChannelService | ||||
|    */ | ||||
|   WxChannelService getWxChannelService(String tenantId); | ||||
|  | ||||
|   /** | ||||
|    * 根据租户 Id,从列表中移除一个 WxChannelService 实例 | ||||
|    * | ||||
|    * @param tenantId 租户 Id | ||||
|    */ | ||||
|   void removeWxChannelService(String tenantId); | ||||
| } | ||||
| @ -0,0 +1,36 @@ | ||||
| package com.binarywang.spring.starter.wxjava.channel.service; | ||||
|  | ||||
| import me.chanjar.weixin.channel.api.WxChannelService; | ||||
|  | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
|  | ||||
| /** | ||||
|  * 视频号 {@link WxChannelMultiServices} 实现 | ||||
|  * | ||||
|  * @author <a href="https://github.com/Winnie-by996">Winnie</a> | ||||
|  * @date 2024/9/13 | ||||
|  */ | ||||
| public class WxChannelMultiServicesImpl implements WxChannelMultiServices { | ||||
|   private final Map<String, WxChannelService> services = new ConcurrentHashMap<>(); | ||||
|  | ||||
|   @Override | ||||
|   public WxChannelService getWxChannelService(String tenantId) { | ||||
|     return this.services.get(tenantId); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * 根据租户 Id,添加一个 WxChannelService 到列表 | ||||
|    * | ||||
|    * @param tenantId         租户 Id | ||||
|    * @param wxChannelService WxChannelService 实例 | ||||
|    */ | ||||
|   public void addWxChannelService(String tenantId, WxChannelService wxChannelService) { | ||||
|     this.services.put(tenantId, wxChannelService); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void removeWxChannelService(String tenantId) { | ||||
|     this.services.remove(tenantId); | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,2 @@ | ||||
| org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ | ||||
| com.binarywang.spring.starter.wxjava.channel.autoconfigure.WxChannelMultiAutoConfiguration | ||||
| @ -0,0 +1 @@ | ||||
| com.binarywang.spring.starter.wxjava.channel.autoconfigure.WxChannelMultiAutoConfiguration | ||||
		Reference in New Issue
	
	Block a user
	 Winnie
					Winnie