From 1219b30f43ef24b83729cc8bb7f32f0dde044beb Mon Sep 17 00:00:00 2001 From: caozehui <2427765068@qq.com> Date: Tue, 10 Feb 2026 15:27:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/AuthorizeRequestsCustomizer.java | 1 + .../MsgpushSecurityAutoConfiguration.java | 2 +- .../MsgpushWebSecurityConfigurerAdapter.java | 1 + ...eadLocalSecurityContextHolderStrategy.java | 2 +- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../module/push/annoation/CheckIdmpotent.java | 16 ++ .../msgpush-module-push-server/pom.xml | 14 ++ .../module/push/PushServerApplication.java | 2 + .../msgpush/module/push/checker/IChecker.java | 13 ++ .../push/checker/MsgPushGuardChain.java | 44 ++++++ .../push/checker/impl/BlacklistChecker.java | 16 ++ .../push/checker/impl/IdempotencyChecker.java | 16 ++ .../push/checker/impl/QuotaChecker.java | 16 ++ .../push/checker/impl/RateLimitChecker.java | 17 +++ .../client/channel/appPush/AppPushClient.java | 8 + .../appPush/factory/AppPushFactory.java | 8 + .../push/client/channel/mail/MailClient.java | 15 ++ .../channel/mail/factory/MailFactory.java | 27 ++++ .../channel/mail/impl/AliYunMailClient.java | 86 +++++++++++ .../channel/sms/Impl/AliYunSmsClient.java | 144 ++++++++++++++++++ .../channel/sms/Impl/TelecomSmsClient.java | 89 +++++++++++ .../push/client/channel/sms/SmsClient.java | 31 ++++ .../channel/sms/factory/SmsFactory.java | 33 ++++ .../push/client/constant/ClientConstant.java | 11 ++ .../client/setting/BaseChannelSetting.java | 9 ++ .../setting/appPush/AppPushSetting.java | 18 +++ .../appPush/UniPushAppPushSetting.java | 20 +++ .../setting/mail/AliYunMailSetting.java | 22 +++ .../push/client/setting/mail/MailSetting.java | 16 ++ .../client/setting/sms/AliYunSmsSetting.java | 22 +++ .../push/client/setting/sms/SmsSetting.java | 15 ++ .../client/setting/sms/TelecomSmsSetting.java | 20 +++ .../ChannelProviderConfigController.java | 22 +++ .../vo/ChannelProviderConfigReqVO.java | 32 ++++ .../message/MessageRecordController.java | 35 +++++ .../message/vo/MessageRecordSendReqVO.java | 42 +++++ .../channel/ChannelProviderConfigDO.java | 84 ++++++++++ .../dataobject/message/MessageRecordDO.java | 123 +++++++++++++++ .../channel/ChannelProviderConfigMapper.java | 9 ++ .../mysql/message/MessageRecordMapper.java | 9 ++ .../channel/ChannelProviderConfigService.java | 4 + .../ChannelProviderConfigServiceImpl.java | 7 + .../service/message/MessageRecordService.java | 14 ++ .../message/MessageRecordServiceImpl.java | 13 ++ .../module/push/util/RestTemplateUtil.java | 121 +++++++++++++++ .../src/main/resources/application-dev.yaml | 8 +- .../src/main/resources/application-local.yaml | 31 ++-- .../src/main/resources/application.yaml | 17 +++ .../module/push/AliYunMailClientTest.java | 18 +++ .../module/push/sms/AliYumSmsClientTest.java | 49 ++++++ .../module/push/sms/TelecomSmsClientTest.java | 33 ++++ .../server/MsgpushServerApplication.java | 4 +- 52 files changed, 1408 insertions(+), 22 deletions(-) create mode 100644 msgpush-module-push/msgpush-module-push-api/src/main/java/com/njcn/msgpush/module/push/annoation/CheckIdmpotent.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/IChecker.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/MsgPushGuardChain.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/BlacklistChecker.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/IdempotencyChecker.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/QuotaChecker.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/RateLimitChecker.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/AppPushClient.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/factory/AppPushFactory.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/MailClient.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/factory/MailFactory.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/impl/AliYunMailClient.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/AliYunSmsClient.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/TelecomSmsClient.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/SmsClient.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/factory/SmsFactory.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/constant/ClientConstant.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/BaseChannelSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/AppPushSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/UniPushAppPushSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/AliYunMailSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/MailSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/AliYunSmsSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/SmsSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/TelecomSmsSetting.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/ChannelProviderConfigController.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/vo/ChannelProviderConfigReqVO.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/MessageRecordController.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/vo/MessageRecordSendReqVO.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/channel/ChannelProviderConfigDO.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/message/MessageRecordDO.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/channel/ChannelProviderConfigMapper.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/message/MessageRecordMapper.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigService.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigServiceImpl.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordService.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordServiceImpl.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/util/RestTemplateUtil.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/AliYunMailClientTest.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/AliYumSmsClientTest.java create mode 100644 msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/TelecomSmsClientTest.java diff --git a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/AuthorizeRequestsCustomizer.java b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/AuthorizeRequestsCustomizer.java index 6716f12..d788f0e 100644 --- a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/AuthorizeRequestsCustomizer.java +++ b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/AuthorizeRequestsCustomizer.java @@ -6,6 +6,7 @@ import org.springframework.core.Ordered; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; +import org.springframework.stereotype.Component; /** * 自定义的 URL 的安全配置 diff --git a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushSecurityAutoConfiguration.java b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushSecurityAutoConfiguration.java index 70d0007..1d664cf 100644 --- a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushSecurityAutoConfiguration.java +++ b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushSecurityAutoConfiguration.java @@ -38,7 +38,7 @@ public class MsgpushSecurityAutoConfiguration { private SecurityProperties securityProperties; /** - * 认证失败处理类 Bean + * 身份认证失败处理类 Bean */ @Bean public AuthenticationEntryPoint authenticationEntryPoint() { diff --git a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushWebSecurityConfigurerAdapter.java b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushWebSecurityConfigurerAdapter.java index e48adbd..2179122 100644 --- a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushWebSecurityConfigurerAdapter.java +++ b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/config/MsgpushWebSecurityConfigurerAdapter.java @@ -8,6 +8,7 @@ import com.google.common.collect.Multimap; import jakarta.annotation.Resource; import jakarta.annotation.security.PermitAll; import jakarta.servlet.DispatcherType; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.context.ApplicationContext; diff --git a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java index 5b40ce9..98dc67e 100644 --- a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java +++ b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/java/com/njcn/msgpush/framework/security/core/context/TransmittableThreadLocalSecurityContextHolderStrategy.java @@ -15,7 +15,7 @@ import org.springframework.util.Assert; public class TransmittableThreadLocalSecurityContextHolderStrategy implements SecurityContextHolderStrategy { /** - * 使用 TransmittableThreadLocal 作为上下文 + * 使用 TransmittableThreadLocal 实现线程之间上下文的传递。 */ private static final ThreadLocal CONTEXT_HOLDER = new TransmittableThreadLocal<>(); diff --git a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index c7f1adb..18bf437 100644 --- a/msgpush-framework/msgpush-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/msgpush-framework/msgpush-spring-boot-starter-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -1,5 +1,4 @@ com.njcn.msgpush.framework.security.config.MsgpushSecurityRpcAutoConfiguration com.njcn.msgpush.framework.security.config.MsgpushSecurityAutoConfiguration -com.njcn.msgpush.framework.security.config.MsgpushWebSecurityConfigurerAdapter com.njcn.msgpush.framework.operatelog.config.MsgpushOperateLogConfiguration com.njcn.msgpush.framework.operatelog.config.MsgpushOperateLogRpcAutoConfiguration \ No newline at end of file diff --git a/msgpush-module-push/msgpush-module-push-api/src/main/java/com/njcn/msgpush/module/push/annoation/CheckIdmpotent.java b/msgpush-module-push/msgpush-module-push-api/src/main/java/com/njcn/msgpush/module/push/annoation/CheckIdmpotent.java new file mode 100644 index 0000000..198358a --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-api/src/main/java/com/njcn/msgpush/module/push/annoation/CheckIdmpotent.java @@ -0,0 +1,16 @@ +package com.njcn.msgpush.module.push.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author caozehui + * @data 2026-02-10 + * @description 接口幂等性检查注解 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface CheckIdmpotent { +} diff --git a/msgpush-module-push/msgpush-module-push-server/pom.xml b/msgpush-module-push/msgpush-module-push-server/pom.xml index ced7551..92fcf3a 100644 --- a/msgpush-module-push/msgpush-module-push-server/pom.xml +++ b/msgpush-module-push/msgpush-module-push-server/pom.xml @@ -105,6 +105,20 @@ hutool-extra + + + com.aliyun + dm20151123 + 1.9.3 + + + + + com.aliyun + dysmsapi20170525 + 4.2.0 + + diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/PushServerApplication.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/PushServerApplication.java index 02f6a82..34fbee9 100644 --- a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/PushServerApplication.java +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/PushServerApplication.java @@ -2,9 +2,11 @@ package com.njcn.msgpush.module.push; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; /** * 项目的启动类 + * * @author hongawen */ @SpringBootApplication diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/IChecker.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/IChecker.java new file mode 100644 index 0000000..8aadd2d --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/IChecker.java @@ -0,0 +1,13 @@ +package com.njcn.msgpush.module.push.checker; + +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +/** + * @author caozehui + * @data 2026-02-27 + * @description 检查器接口 + */ +public interface IChecker { + + boolean check(MessageRecordSendReqVO reqVO); +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/MsgPushGuardChain.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/MsgPushGuardChain.java new file mode 100644 index 0000000..d5b29e5 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/MsgPushGuardChain.java @@ -0,0 +1,44 @@ +package com.njcn.msgpush.module.push.checker; + +import com.njcn.msgpush.module.push.checker.impl.BlacklistChecker; +import com.njcn.msgpush.module.push.checker.impl.IdempotencyChecker; +import com.njcn.msgpush.module.push.checker.impl.QuotaChecker; +import com.njcn.msgpush.module.push.checker.impl.RateLimitChecker; +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author caozehui + * @data 2026-02-28 + * @description 检查链 + */ +public class MsgPushGuardChain { + private final List checkers; + + public MsgPushGuardChain() { + this.checkers = new ArrayList<>(); + this.checkers.add(new IdempotencyChecker()); + this.checkers.add(new BlacklistChecker()); + this.checkers.add(new QuotaChecker()); + this.checkers.add(new RateLimitChecker()); + } + + public boolean checkAll(MessageRecordSendReqVO reqVO) { + for (IChecker checker : checkers) { + boolean result = checker.check(reqVO); + if (!result) { + // 任何一层检查失败,立即返回拒绝 + logRejection(reqVO); + return result; + } + } + return true; + } + + private void logRejection(MessageRecordSendReqVO reqVO) { + // 记录拒绝日志,用于监控和分析 + System.out.printf("消息请求被拒绝: receiver=%s, messageId=%s, reason=%s%n", reqVO.getReceiver(), reqVO.getMessageId()); + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/BlacklistChecker.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/BlacklistChecker.java new file mode 100644 index 0000000..fac6a62 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/BlacklistChecker.java @@ -0,0 +1,16 @@ +package com.njcn.msgpush.module.push.checker.impl; + +import com.njcn.msgpush.module.push.checker.IChecker; +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +/** + * @author caozehui + * @data 2026-02-27 + * @description 黑名单检查器 + */ +public class BlacklistChecker implements IChecker { + @Override + public boolean check(MessageRecordSendReqVO reqVO) { + return true; + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/IdempotencyChecker.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/IdempotencyChecker.java new file mode 100644 index 0000000..c7065fa --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/IdempotencyChecker.java @@ -0,0 +1,16 @@ +package com.njcn.msgpush.module.push.checker.impl; + +import com.njcn.msgpush.module.push.checker.IChecker; +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +/** + * @author caozehui + * @data 2026-02-27 + * @description 接口幂等性检查器 + */ +public class IdempotencyChecker implements IChecker { + @Override + public boolean check(MessageRecordSendReqVO reqVO) { + return true; + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/QuotaChecker.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/QuotaChecker.java new file mode 100644 index 0000000..464936d --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/QuotaChecker.java @@ -0,0 +1,16 @@ +package com.njcn.msgpush.module.push.checker.impl; + +import com.njcn.msgpush.module.push.checker.IChecker; +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +/** + * @author caozehui + * @data 2026-02-27 + * @description 系统配额检查器 + */ +public class QuotaChecker implements IChecker { + @Override + public boolean check(MessageRecordSendReqVO reqVO) { + return true; + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/RateLimitChecker.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/RateLimitChecker.java new file mode 100644 index 0000000..e3e97b9 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/checker/impl/RateLimitChecker.java @@ -0,0 +1,17 @@ +package com.njcn.msgpush.module.push.checker.impl; + + +import com.njcn.msgpush.module.push.checker.IChecker; +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +/** + * @author caozehui + * @data 2026-02-27 + * @description 接收者频率检查器 + */ +public class RateLimitChecker implements IChecker { + @Override + public boolean check(MessageRecordSendReqVO reqVO) { + return true; + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/AppPushClient.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/AppPushClient.java new file mode 100644 index 0000000..c974cce --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/AppPushClient.java @@ -0,0 +1,8 @@ +package com.njcn.msgpush.module.push.client.channel.appPush; + +/** + * @author caozehui + * @data 2026-02-11 + */ +public interface AppPushClient { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/factory/AppPushFactory.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/factory/AppPushFactory.java new file mode 100644 index 0000000..d91cb16 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/appPush/factory/AppPushFactory.java @@ -0,0 +1,8 @@ +package com.njcn.msgpush.module.push.client.channel.appPush.factory; + +/** + * @author caozehui + * @data 2026-02-11 + */ +public class AppPushFactory { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/MailClient.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/MailClient.java new file mode 100644 index 0000000..18a595c --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/MailClient.java @@ -0,0 +1,15 @@ +package com.njcn.msgpush.module.push.client.channel.mail; + +import java.util.List; +import java.util.Map; + +/** + * @author caozehui + * @data 2026-02-11 + */ +public interface MailClient { + + void sendMail(String accountName, Integer addressType, Boolean replyToAddress, String toAddress, String subject, String htmlBody); + + void queryMailAddressByParam(); +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/factory/MailFactory.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/factory/MailFactory.java new file mode 100644 index 0000000..d1a0465 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/factory/MailFactory.java @@ -0,0 +1,27 @@ +package com.njcn.msgpush.module.push.client.channel.mail.factory; + +import cn.hutool.core.util.StrUtil; +import com.njcn.msgpush.module.push.client.channel.mail.MailClient; +import com.njcn.msgpush.module.push.client.channel.mail.impl.AliYunMailClient; +import com.njcn.msgpush.module.push.client.constant.ClientConstant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author caozehui + * @data 2026-02-11 + */ +@Component +public class MailFactory { + + @Autowired + private AliYunMailClient aliYunMailClient; + + public MailClient getClient(String mailProviderTypeName) throws RuntimeException { + if (StrUtil.equals(ClientConstant.ALI_YUN, mailProviderTypeName)) { + return aliYunMailClient; + } else { + throw new RuntimeException("暂时不提供" + mailProviderTypeName + "邮件服务提供商"); + } + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/impl/AliYunMailClient.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/impl/AliYunMailClient.java new file mode 100644 index 0000000..cf5dcfa --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/mail/impl/AliYunMailClient.java @@ -0,0 +1,86 @@ +package com.njcn.msgpush.module.push.client.channel.mail.impl; + +import com.alibaba.fastjson.JSON; +import com.aliyun.dm20151123.Client; +import com.aliyun.dm20151123.models.QueryMailAddressByParamRequest; +import com.aliyun.dm20151123.models.QueryMailAddressByParamResponse; +import com.aliyun.dm20151123.models.SingleSendMailRequest; +import com.aliyun.teaopenapi.models.Config; +import com.aliyun.teautil.models.RuntimeOptions; +import com.njcn.msgpush.module.push.client.channel.mail.MailClient; +import com.njcn.msgpush.module.push.client.setting.mail.AliYunMailSetting; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; + +/** + * @author caozehui + * @data 2026-02-11 + */ +@Slf4j +@Service +public class AliYunMailClient implements MailClient { + private static final String ACCOUNT_NAME = "accountName"; + private static final Integer ADDRESS_TYPE = 0; + private static final String REPLY_TO_ADDRESS = "replyToAddress"; + private static final String HTML_BODY = "htmlBody"; + private static final String TEXT_BODY = "textBody"; + private static final String TO_ADDRESS = "toAddress"; + private static final String SUBJECT = "subject"; + private static final String CLICK_TRACE = "1"; + + @Autowired + private AliYunMailSetting aliYunMailSetting; + + private Client client; + + @PostConstruct + public void init() { + Config config = new Config() + .setAccessKeyId(aliYunMailSetting.getAccessKeyId()) + .setAccessKeySecret(aliYunMailSetting.getAccessKeySecret()) + .setRegionId(aliYunMailSetting.getRegionId()) + .setEndpoint(aliYunMailSetting.getEndpoint()); + + try { + this.client = new Client(config); + } catch (Exception e) { + log.error("阿里云-邮件服务初始化失败,请检查配置信息"); + throw new RuntimeException(e); + } + } + + @Override + public void sendMail(String accountName, Integer addressType, Boolean replyToAddress, String toAddress, String subject, String htmlBody) { + RuntimeOptions runtimeOptions = new RuntimeOptions(); + // 设置自动重试,默认是不开启的。重试次数默认是3次 + runtimeOptions.autoretry = true; + SingleSendMailRequest request = new SingleSendMailRequest() + .setAccountName(accountName) + .setAddressType(addressType) + .setReplyToAddress(replyToAddress) + .setToAddress(toAddress) + .setSubject(subject) + .setHtmlBody(htmlBody); + try { + client.singleSendMailWithOptions(request, runtimeOptions); + } catch (Exception e) { + throw new RuntimeException("阿里云-邮件服务发送失败"); + } + } + + @Override + public void queryMailAddressByParam() { + QueryMailAddressByParamRequest queryMailAddressByParamRequest = null; + try { + queryMailAddressByParamRequest = QueryMailAddressByParamRequest.build(new HashMap<>()); + QueryMailAddressByParamResponse response = client.queryMailAddressByParam(queryMailAddressByParamRequest); + System.out.println(JSON.toJSON(response)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/AliYunSmsClient.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/AliYunSmsClient.java new file mode 100644 index 0000000..d767f7a --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/AliYunSmsClient.java @@ -0,0 +1,144 @@ +package com.njcn.msgpush.module.push.client.channel.sms.Impl; + +import com.aliyun.dysmsapi20170525.Client; +import com.aliyun.dysmsapi20170525.models.*; +import com.aliyun.teaopenapi.models.Config; +import com.aliyun.teautil.models.RuntimeOptions; +import com.njcn.msgpush.module.push.client.channel.sms.SmsClient; +import com.njcn.msgpush.module.push.client.setting.sms.AliYunSmsSetting; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static com.aliyun.teautil.Common.toJSONString; + + +/** + * @author caozehui + * @data 2026-02-11 + * @description 阿里云短信服务实现 + */ +@Slf4j +@Service +public class AliYunSmsClient implements SmsClient { + + public static final String SIGN_NAME = "signName"; + public static final String TEMPLATE_CODE = "templateCode"; + public static final String TEMPLATE_PARAM = "templateParam"; + public static final String OK = "OK"; + + + @Autowired + private AliYunSmsSetting aliYunSmsSetting; + private Client client; + + private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor( + 5, + 5, + 1000, + TimeUnit.MILLISECONDS, + new java.util.concurrent.ArrayBlockingQueue<>(1000), + r -> { + Thread thread = new Thread(r); + thread.setName("AliYunSmsClient-Pool-" + thread.getId()); + thread.setDaemon(false); + return thread; + }, + new ThreadPoolExecutor.CallerRunsPolicy() + ); + + @PostConstruct + public void init() { + Config config = new Config() + .setAccessKeyId(aliYunSmsSetting.getAccessKeyId()) + .setAccessKeySecret(aliYunSmsSetting.getAccessKeySecret()) + .setRegionId(aliYunSmsSetting.getRegionId()) + .setEndpoint(aliYunSmsSetting.getEndpoint()); + + try { + this.client = new Client(config); + } catch (Exception e) { + log.error("阿里云-短信服务初始化失败,请检查配置信息"); + throw new RuntimeException(e); + } + } + + @Override + public boolean sendSms(Map params, String phoneNumber) throws Exception { + Future future = THREAD_POOL_EXECUTOR.submit(() -> { + // todo 修改消息的状态为 sending + + RuntimeOptions runtimeOptions = new RuntimeOptions(); + // 设置自动重试,默认是不开启的。重试次数默认是3次 + runtimeOptions.autoretry = true; + SendSmsRequest request = new SendSmsRequest() + .setPhoneNumbers(phoneNumber) + .setSignName(params.get(SIGN_NAME).toString()) + .setTemplateCode(params.get(TEMPLATE_CODE).toString()) + .setTemplateParam(params.get(TEMPLATE_PARAM).toString()); + try { + SendSmsResponse response = this.client.sendSmsWithOptions(request, runtimeOptions); + System.out.println(toJSONString(response)); + if (OK.equals(response.body.code)) { + return true; + } else { + return false; + } + } catch (Exception e) { + log.error("阿里云-短信服务发送失败"); + throw new Exception(e); + } + }); + Boolean b = future.get(3, TimeUnit.SECONDS); + if (b) { + // todo 修改消息的状态为 success + } else { + // todo 修改消息的状态为 failed + } + return b; + } + + @Override + public boolean sendBatchSms(Map params, List phoneNumbers) { + RuntimeOptions runtimeOptions = new RuntimeOptions(); + // 设置自动重试,默认是不开启的。重试次数默认是3次 + runtimeOptions.autoretry = true; + SendBatchSmsRequest request = new SendBatchSmsRequest() + .setPhoneNumberJson(toJSONString(phoneNumbers)) + .setSignNameJson(toJSONString(params.get(SIGN_NAME))) + .setTemplateCode(params.get(TEMPLATE_CODE).toString()) + .setTemplateParamJson(toJSONString(params.get(TEMPLATE_PARAM))); + try { + SendBatchSmsResponse response = this.client.sendBatchSmsWithOptions(request, runtimeOptions); + System.out.println(toJSONString(response)); + if (OK.equals(response.body.code)) { + return true; + } else { + return false; + } + } catch (Exception e) { + log.error("阿里云-短信服务发送失败"); + throw new RuntimeException(e); + } + } + + @Override + public void querySmsTemplateList() { + QuerySmsTemplateListRequest request = new QuerySmsTemplateListRequest(); + request.setPageIndex(1); + request.setPageSize(10); + try { + QuerySmsTemplateListResponse querySmsTemplateListResponse = this.client.querySmsTemplateList(request); + System.out.println(toJSONString(querySmsTemplateListResponse)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/TelecomSmsClient.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/TelecomSmsClient.java new file mode 100644 index 0000000..51b9761 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/Impl/TelecomSmsClient.java @@ -0,0 +1,89 @@ +package com.njcn.msgpush.module.push.client.channel.sms.Impl; + +import cn.hutool.core.util.StrUtil; +import com.njcn.msgpush.module.push.client.channel.sms.SmsClient; +import com.njcn.msgpush.module.push.client.setting.sms.TelecomSmsSetting; +import com.njcn.msgpush.module.push.util.RestTemplateUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author caozehui + * @data 2026-02-11 + * @description 电信e企云短信服务实现 + */ +@Slf4j +@Service +public class TelecomSmsClient implements SmsClient { + + /** + * 短信接口地址 + */ + private static final String API_URL = "https://sms.ymeeting.cn/smsv2"; + /** + * 虚拟接入码 + */ + private static final String ACCESS_CODE = "106905631"; + /** + * 短信接口内容类型 + */ + private static final String CONTENT_TYPE = "application/json;charset=utf-8"; + + // public static final String ACCOUNT = "account"; +// public static final String PASSWORD = "password"; + public static final String CONTENT = "content"; + + @Autowired + private TelecomSmsSetting telecomSmsSetting; + + @Autowired + private RestTemplateUtil restTemplateUtil; + + @Override + public boolean sendSms(Map params, String phoneNumber) throws Exception { + return this.sendBatchSms(params, List.of(phoneNumber)); + } + + @Override + public boolean sendBatchSms(Map params, List phoneNumbers) { + // 构建请求参数 + Map request = new HashMap<>(); + request.put("action", "send"); + request.put("account", telecomSmsSetting.getAccount()); + request.put("password", telecomSmsSetting.getPassword()); + request.put("mobile", StrUtil.join(StrUtil.COMMA, phoneNumbers)); + request.put("content", params.get(CONTENT).toString()); + request.put("extno", ACCESS_CODE); + + // 设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", CONTENT_TYPE); + + // 发送请求 + ResponseEntity response = restTemplateUtil.post( + API_URL, + request, + headers, + String.class + ); + String body = response.getBody(); + + if (body.contains("\"status\": 0")) { + return true; + } else { + return false; + } + } + + @Override + public void querySmsTemplateList() { + + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/SmsClient.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/SmsClient.java new file mode 100644 index 0000000..2c15c02 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/SmsClient.java @@ -0,0 +1,31 @@ +package com.njcn.msgpush.module.push.client.channel.sms; + +import java.util.List; +import java.util.Map; + +/** + * @author caozehui + * @data 2026-02-10 + */ +public interface SmsClient { + + /** + * 向单个手机号发送短信 + * + * @param phoneNumber 手机号 + * @param params 参数 + * @return 发送结果 + */ + boolean sendSms(Map params, String phoneNumber) throws Exception; + + /** + * 向多个手机号发送短信 + * + * @param phoneNumbers 手机号集合 + * @param params 参数 + * @return 发送结果 + */ + boolean sendBatchSms(Map params, List phoneNumbers); + + void querySmsTemplateList(); +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/factory/SmsFactory.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/factory/SmsFactory.java new file mode 100644 index 0000000..c151a78 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/channel/sms/factory/SmsFactory.java @@ -0,0 +1,33 @@ +package com.njcn.msgpush.module.push.client.channel.sms.factory; + +import cn.hutool.core.util.StrUtil; +import com.njcn.msgpush.module.push.client.channel.sms.Impl.AliYunSmsClient; +import com.njcn.msgpush.module.push.client.channel.sms.Impl.TelecomSmsClient; +import com.njcn.msgpush.module.push.client.channel.sms.SmsClient; +import com.njcn.msgpush.module.push.client.constant.ClientConstant; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author caozehui + * @data 2026-02-11 + */ +@Component +public class SmsFactory { + + @Autowired + private AliYunSmsClient aliYunSmsClient; + + @Autowired + private TelecomSmsClient telecomSmsClient; + + public SmsClient getClient(String smsProviderTypeName) throws RuntimeException { + if (StrUtil.equals(ClientConstant.ALI_YUN, smsProviderTypeName)) { + return aliYunSmsClient; + } else if (StrUtil.equals(ClientConstant.TELECOM, smsProviderTypeName)) { + return telecomSmsClient; + } else { + throw new RuntimeException("暂时不提供" + smsProviderTypeName + "短信服务提供商"); + } + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/constant/ClientConstant.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/constant/ClientConstant.java new file mode 100644 index 0000000..be77b08 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/constant/ClientConstant.java @@ -0,0 +1,11 @@ +package com.njcn.msgpush.module.push.client.constant; + +/** + * @author caozehui + * @data 2026-02-10 + */ +public interface ClientConstant { + String ALI_YUN = "阿里云"; + + String TELECOM = "电信"; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/BaseChannelSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/BaseChannelSetting.java new file mode 100644 index 0000000..02acdfc --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/BaseChannelSetting.java @@ -0,0 +1,9 @@ +package com.njcn.msgpush.module.push.client.setting; + +/** + * @author caozehui + * @data 2026-02-09 + * @description 各个推送渠道通用的配置 + */ +public abstract class BaseChannelSetting { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/AppPushSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/AppPushSetting.java new file mode 100644 index 0000000..671802c --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/AppPushSetting.java @@ -0,0 +1,18 @@ +package com.njcn.msgpush.module.push.client.setting.appPush; + +import com.njcn.msgpush.module.push.client.setting.BaseChannelSetting; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author caozehui + * @data 2026-02-09 + * @description App推送配置 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public abstract class AppPushSetting extends BaseChannelSetting { + private String appKey; //示例 + private String secret; //示例 + private String key; //示例 +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/UniPushAppPushSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/UniPushAppPushSetting.java new file mode 100644 index 0000000..3f76b7d --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/appPush/UniPushAppPushSetting.java @@ -0,0 +1,20 @@ +package com.njcn.msgpush.module.push.client.setting.appPush; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * @author caozehui + * @data 2026-02-09 + * @description UniPush应用推送配置 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class UniPushAppPushSetting extends AppPushSetting { + private String accessKeyId; + private String accessKeySecret; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/AliYunMailSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/AliYunMailSetting.java new file mode 100644 index 0000000..0fe8aab --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/AliYunMailSetting.java @@ -0,0 +1,22 @@ +package com.njcn.msgpush.module.push.client.setting.mail; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author caozehui + * @data 2026-02-09 + * @description 阿里云邮件配置 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Component +@ConfigurationProperties(prefix = "aliyun.mail") +public class AliYunMailSetting extends MailSetting { + private String accessKeyId; + private String accessKeySecret; + private String regionId; + private String endpoint; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/MailSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/MailSetting.java new file mode 100644 index 0000000..d77eaa0 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/mail/MailSetting.java @@ -0,0 +1,16 @@ +package com.njcn.msgpush.module.push.client.setting.mail; + +import com.njcn.msgpush.module.push.client.setting.BaseChannelSetting; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author caozehui + * @data 2026-02-09 + * @description 邮箱配置 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public abstract class MailSetting extends BaseChannelSetting { + +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/AliYunSmsSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/AliYunSmsSetting.java new file mode 100644 index 0000000..4294093 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/AliYunSmsSetting.java @@ -0,0 +1,22 @@ +package com.njcn.msgpush.module.push.client.setting.sms; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author caozehui + * @data 2026-02-09 + * @description 阿里云短信应用配置 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Component +@ConfigurationProperties(prefix = "aliyun.sms") +public class AliYunSmsSetting extends SmsSetting { + private String accessKeyId; + private String accessKeySecret; + private String regionId; + private String endpoint; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/SmsSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/SmsSetting.java new file mode 100644 index 0000000..2663c57 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/SmsSetting.java @@ -0,0 +1,15 @@ +package com.njcn.msgpush.module.push.client.setting.sms; + +import com.njcn.msgpush.module.push.client.setting.BaseChannelSetting; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author caozehui + * @data 2026-02-09 + * @description 短信配置抽象类 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public abstract class SmsSetting extends BaseChannelSetting { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/TelecomSmsSetting.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/TelecomSmsSetting.java new file mode 100644 index 0000000..02ab3fb --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/client/setting/sms/TelecomSmsSetting.java @@ -0,0 +1,20 @@ +package com.njcn.msgpush.module.push.client.setting.sms; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author caozehui + * @data 2026-02-10 + * @description 电信e企云短信服务应用配置 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Component +@ConfigurationProperties(prefix = "telecom.sms") +public class TelecomSmsSetting extends SmsSetting { + private String account; + private String password; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/ChannelProviderConfigController.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/ChannelProviderConfigController.java new file mode 100644 index 0000000..00eedff --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/ChannelProviderConfigController.java @@ -0,0 +1,22 @@ +package com.njcn.msgpush.module.push.controller.admin.channel; + +import com.njcn.msgpush.module.push.service.channel.ChannelProviderConfigService; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "管理后台 - 渠道服务商") +@Slf4j +@Validated +@RestController +@RequestMapping("/push/channel") +public class ChannelProviderConfigController { + + @Autowired + private ChannelProviderConfigService channelProviderConfigService; + + +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/vo/ChannelProviderConfigReqVO.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/vo/ChannelProviderConfigReqVO.java new file mode 100644 index 0000000..feb2038 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/channel/vo/ChannelProviderConfigReqVO.java @@ -0,0 +1,32 @@ +package com.njcn.msgpush.module.push.controller.admin.channel.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "管理后台 - 渠道服务商配置 Request VO") +public class ChannelProviderConfigReqVO { + @Schema(description = "渠道类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sms/email/app_push") + private String channel; + + @Schema(description = "服务商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "中国电信/阿里云/UniPush") + private String providerName; + + @Schema(description = "服务商类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "telecom/cmcc/aliyun/twilio/unipush") + private String providerType; + + @Schema(description = "API地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://api.example.com") + private String apiUrl; + + @Schema(description = "AppKey", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + private String appKey; + + @Schema(description = "AppSecret", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + private String appSecret; + + @Schema(description = "额外配置(JSON格式)", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private String extraConfig; + + @Schema(description = "优先级(数字越小优先级越高)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer priority; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/MessageRecordController.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/MessageRecordController.java new file mode 100644 index 0000000..04f0e06 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/MessageRecordController.java @@ -0,0 +1,35 @@ +package com.njcn.msgpush.module.push.controller.admin.message; + +import com.njcn.msgpush.framework.common.pojo.CommonResult; +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; +import com.njcn.msgpush.module.push.service.message.MessageRecordService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.security.PermitAll; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Tag(name = "管理后台 - 消息") +@Slf4j +@Validated +@RestController +@RequestMapping("/push/message") +public class MessageRecordController { + + @Autowired + private MessageRecordService messageRecordService; + + @PostMapping("send") + @PermitAll + @Operation(summary = "使用账号密码登录") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + public CommonResult send(MessageRecordSendReqVO messageRecordSendReqVO) { + Boolean result = messageRecordService.send(messageRecordSendReqVO); + return CommonResult.success(result); + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/vo/MessageRecordSendReqVO.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/vo/MessageRecordSendReqVO.java new file mode 100644 index 0000000..fd2df04 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/controller/admin/message/vo/MessageRecordSendReqVO.java @@ -0,0 +1,42 @@ +package com.njcn.msgpush.module.push.controller.admin.message.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +@Schema(description = "管理后台 - 消息记录发送 Request VO") +public class MessageRecordSendReqVO { + + @Schema(description = "消息唯一ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") + private String messageId; + + @Schema(description = "应用名称/来源系统标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "NPQS-9500") + private String appName; + + @Schema(description = "渠道类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "sms/email/app_push") + private String channel; + + @Schema(description = "消息类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "verify_code/order_notify/marketing/system_notify") + private String messageType; + + @Schema(description = "接收者", requiredMode = Schema.RequiredMode.REQUIRED, example = "15601691300") + private String receiver; + + @Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED) + private String title; + + @Schema(description = "消息内容", requiredMode = Schema.RequiredMode.REQUIRED) + private String content; + + @Schema(description = "模板编码", requiredMode = Schema.RequiredMode.REQUIRED) + private String templateCode; + + @Schema(description = "模板参数") + private String templateParams; + + @Schema(description = "服务商类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "telecom/cmcc/aliyun/twilio") + private String providerType; + + @Schema(description = "第三方消息ID") + private String thirdPartyId; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/channel/ChannelProviderConfigDO.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/channel/ChannelProviderConfigDO.java new file mode 100644 index 0000000..15cebab --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/channel/ChannelProviderConfigDO.java @@ -0,0 +1,84 @@ +package com.njcn.msgpush.module.push.dal.dataobject.channel; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.msgpush.framework.mybatis.core.dataobject.BaseDO; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * @author caozehui + * @data 2026-02-06 + * @description 渠道服务商配置表对应的数据对象 + */ +@Data +@TableName("push_channel_provider_config") +@EqualsAndHashCode(callSuper = true) +public class ChannelProviderConfigDO extends BaseDO { + /** + * 主键ID + */ + private Long id; + + /** + * 渠道类型:sms/email/app_push + */ + private String channel; + + /** + * 服务商名称:中国电信/阿里云/UniPush + */ + private String providerName; + + /** + * 服务商类型:telecom/cmcc/aliyun/twilio/unipush + */ + private String providerType; + + /** + * API地址 + */ + private String apiUrl; + + /** + * AppKey + */ + private String appKey; + + /** + * AppSecret + */ + private String appSecret; + + /** + * 额外配置(JSON格式) + */ + private String extraConfig; + + /** + * 优先级(数字越小优先级越高) + */ + private Integer priority; + + /** + * 是否启用:0-禁用 1-启用(手动控制) + */ + private Integer enabled; + + /** + * 健康状态:0-异常 1-正常(自动检测) + */ + private Integer healthStatus; + + /** + * 连续失败次数(自动统计) + */ + private Integer failureCount; + + /** + * 最后失败时间(自动记录) + */ + private LocalDateTime lastFailureTime; + +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/message/MessageRecordDO.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/message/MessageRecordDO.java new file mode 100644 index 0000000..d8bb550 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/dataobject/message/MessageRecordDO.java @@ -0,0 +1,123 @@ +package com.njcn.msgpush.module.push.dal.dataobject.message; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.njcn.msgpush.framework.mybatis.core.dataobject.BaseDO; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * @author caozehui + * @data 2026-02-06 + * @description 消息记录表对应的数据对象 + */ +@Data +@TableName("push_message_record") +@EqualsAndHashCode(callSuper = true) +public class MessageRecordDO extends BaseDO { + /** + * 主键ID + */ + private Long id; + + /** + * 消息唯一ID + */ + private String messageId; + + /** + * 应用名称/来源系统标识 + */ + private String appName; + + /** + * 渠道类型:sms/email/app_push + */ + private String channel; + + /** + * 消息类型:verify_code/order_notify/marketing/system_notify + */ + private String messageType; + + /** + * 接收者 + */ + private String receiver; + + /** + * 标题 + */ + private String title; + + /** + * 消息内容 + */ + private String content; + + /** + * 模板编码 + */ + private String templateCode; + + /** + * 模板参数 + */ + private String templateParams; + + /** + * 状态:pending/sending/success/failed/final_failed/blacklisted/quota_exceeded/rate_limited/abandoned + */ + private String status; + + /** + * 发送时间 + */ + private LocalDateTime sendTime; + + /** + * 发送耗时(毫秒) + */ + private Integer costTime; + + /** + * 已重试次数 + */ + private Integer retryCount; + + /** + * 最后重试时间 + */ + private LocalDateTime lastRetryTime; + + /** + * 下次重试时间 + */ + private LocalDateTime nextRetryTime; + + /** + * 服务商类型:telecom/cmcc/aliyun/twilio + */ + private String providerType; + + /** + * 第三方消息ID + */ + private String thirdPartyId; + + /** + * 统一错误码 + */ + private String errorCode; + + /** + * 错误信息 + */ + private String errorMsg; + + /** + * 过期时间 + */ + private LocalDateTime expireTime; +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/channel/ChannelProviderConfigMapper.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/channel/ChannelProviderConfigMapper.java new file mode 100644 index 0000000..88b6a03 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/channel/ChannelProviderConfigMapper.java @@ -0,0 +1,9 @@ +package com.njcn.msgpush.module.push.dal.mysql.channel; + +import com.njcn.msgpush.framework.mybatis.core.mapper.BaseMapperX; +import com.njcn.msgpush.module.push.dal.dataobject.channel.ChannelProviderConfigDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ChannelProviderConfigMapper extends BaseMapperX { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/message/MessageRecordMapper.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/message/MessageRecordMapper.java new file mode 100644 index 0000000..5ae71e3 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/dal/mysql/message/MessageRecordMapper.java @@ -0,0 +1,9 @@ +package com.njcn.msgpush.module.push.dal.mysql.message; + +import com.njcn.msgpush.framework.mybatis.core.mapper.BaseMapperX; +import com.njcn.msgpush.module.push.dal.dataobject.message.MessageRecordDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MessageRecordMapper extends BaseMapperX { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigService.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigService.java new file mode 100644 index 0000000..e9c49d9 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigService.java @@ -0,0 +1,4 @@ +package com.njcn.msgpush.module.push.service.channel; + +public interface ChannelProviderConfigService { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigServiceImpl.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigServiceImpl.java new file mode 100644 index 0000000..64dd91c --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/channel/ChannelProviderConfigServiceImpl.java @@ -0,0 +1,7 @@ +package com.njcn.msgpush.module.push.service.channel; + +import org.springframework.stereotype.Service; + +@Service +public class ChannelProviderConfigServiceImpl implements ChannelProviderConfigService { +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordService.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordService.java new file mode 100644 index 0000000..2d4a06b --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordService.java @@ -0,0 +1,14 @@ +package com.njcn.msgpush.module.push.service.message; + +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; + +public interface MessageRecordService { + + /** + * 发送消息(包括email、sms、app_push) + * + * @param messageRecordSendReqVO + * @return 发送是否成功的结果 + */ + Boolean send(MessageRecordSendReqVO messageRecordSendReqVO); +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordServiceImpl.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordServiceImpl.java new file mode 100644 index 0000000..c2533a6 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/service/message/MessageRecordServiceImpl.java @@ -0,0 +1,13 @@ +package com.njcn.msgpush.module.push.service.message; + + +import com.njcn.msgpush.module.push.controller.admin.message.vo.MessageRecordSendReqVO; +import org.springframework.stereotype.Service; + +@Service +public class MessageRecordServiceImpl implements MessageRecordService{ + @Override + public Boolean send(MessageRecordSendReqVO messageRecordSendReqVO) { + return null; + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/util/RestTemplateUtil.java b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/util/RestTemplateUtil.java new file mode 100644 index 0000000..c81a97a --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/main/java/com/njcn/msgpush/module/push/util/RestTemplateUtil.java @@ -0,0 +1,121 @@ +package com.njcn.msgpush.module.push.util; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +/** + * @author caozehui + * @data 2026-02-10 + * @description restTemplate工具类 + */ +@Slf4j +@Component +public class RestTemplateUtil { + + private final RestTemplate restTemplate; + + public RestTemplateUtil() { + this.restTemplate = new RestTemplate(); + } + + public ResponseEntity get(String url, Class responseType) { + return get(url, null, responseType); + } + + public ResponseEntity get(String url, HttpHeaders headers, Class responseType) { + try { + HttpEntity requestEntity = new HttpEntity<>(headers); + log.info("发送GET请求到: {}", url); + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, responseType); + log.info("GET请求响应状态: {}", response.getStatusCode()); + return response; + } catch (Exception e) { + log.error("GET请求异常: {}", e.getMessage(), e); + throw e; + } + } + + public ResponseEntity post(String url, Object requestBody, Class responseType) { + return post(url, requestBody, null, responseType); + } + + public ResponseEntity post(String url, Object requestBody, HttpHeaders headers, Class responseType) { + try { + if (headers == null) { + headers = new HttpHeaders(); + } + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity request = new HttpEntity<>(requestBody, headers); + log.info("发送POST请求到: {}", url); + ResponseEntity response = restTemplate.postForEntity(url, request, responseType); + log.info("POST请求响应状态: {}", response.getStatusCode()); + return response; + } catch (Exception e) { + log.error("POST请求异常: {}", e.getMessage(), e); + throw e; + } + } + + public ResponseEntity postForm(String url, Map formData, Class responseType) { + return postForm(url, formData, null, responseType); + } + + public ResponseEntity postForm(String url, Map formData, HttpHeaders headers, Class responseType) { + try { + if (headers == null) { + headers = new HttpHeaders(); + } + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + HttpEntity> request = new HttpEntity<>(formData, headers); + log.info("发送POST表单请求到: {}", url); + ResponseEntity response = restTemplate.postForEntity(url, request, responseType); + log.info("POST表单请求响应状态: {}", response.getStatusCode()); + return response; + } catch (Exception e) { + log.error("POST表单请求异常: {}", e.getMessage(), e); + throw e; + } + } + + public T getForObject(String url, Class responseType) { + try { + log.info("发送GET请求获取对象到: {}", url); + T result = restTemplate.getForObject(url, responseType); + log.info("GET请求成功获取对象"); + return result; + } catch (Exception e) { + log.error("GET请求获取对象异常: {}", e.getMessage(), e); + throw e; + } + } + + public T postForObject(String url, Object requestBody, Class responseType) { + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + HttpEntity request = new HttpEntity<>(requestBody, headers); + + log.info("发送POST请求获取对象到: {}", url); + T result = restTemplate.postForObject(url, request, responseType); + log.info("POST请求成功获取对象"); + return result; + } catch (Exception e) { + log.error("POST请求获取对象异常: {}", e.getMessage(), e); + throw e; + } + } + + public String getString(String url) { + return getForObject(url, String.class); + } + + public String postString(String url, Object requestBody) { + return postForObject(url, requestBody, String.class); + } +} \ No newline at end of file diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-dev.yaml b/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-dev.yaml index 3617d0e..ab32c94 100644 --- a/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-dev.yaml +++ b/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-dev.yaml @@ -7,13 +7,13 @@ spring: username: # Nacos 账号 password: # Nacos 密码 discovery: # 【配置中心】配置项 - namespace: dev # 命名空间。这里使用 dev 开发环境 - group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + namespace: msgCenter # 命名空间。这里使用 dev 开发环境 + group: DEV # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP metadata: version: 1.0.0 # 服务实例的版本号,可用于灰度发布 config: # 【注册中心】配置项 - namespace: dev # 命名空间。这里使用 dev 开发环境 - group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + namespace: msgCenter # 命名空间。这里使用 dev 开发环境 + group: DEV # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP --- #################### 数据库相关配置 #################### spring: diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-local.yaml b/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-local.yaml index 33985c3..772c066 100644 --- a/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-local.yaml +++ b/msgpush-module-push/msgpush-module-push-server/src/main/resources/application-local.yaml @@ -1,23 +1,30 @@ --- #################### 注册中心 + 配置中心相关配置 #################### +#spring: +# cloud: +# nacos: +# server-addr: 192.168.1.103:18848 # Nacos 服务器地址 +# username: # Nacos 账号 +# password: # Nacos 密码 +# discovery: # 【配置中心】配置项 +# namespace: msgCenter # 命名空间。这里使用 dev 开发环境 +# group: DEV # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP +# metadata: +# version: 1.0.0 # 服务实例的版本号,可用于灰度发布 +# config: # 【注册中心】配置项 +# namespace: msgCenter # 命名空间。这里使用 dev 开发环境 +# group: DEV # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP spring: cloud: nacos: - server-addr: 192.168.1.103:18848 # Nacos 服务器地址 - username: # Nacos 账号 - password: # Nacos 密码 - discovery: # 【配置中心】配置项 - namespace: dev # 命名空间。这里使用 dev 开发环境 - group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP - metadata: - version: 1.0.0 # 服务实例的版本号,可用于灰度发布 - config: # 【注册中心】配置项 - namespace: dev # 命名空间。这里使用 dev 开发环境 - group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP + discovery: + enabled: false + config: + enabled: false + --- #################### 数据库相关配置 #################### spring: - # 数据源配置项 autoconfigure: exclude: diff --git a/msgpush-module-push/msgpush-module-push-server/src/main/resources/application.yaml b/msgpush-module-push/msgpush-module-push-server/src/main/resources/application.yaml index b263e71..6358733 100644 --- a/msgpush-module-push/msgpush-module-push-server/src/main/resources/application.yaml +++ b/msgpush-module-push/msgpush-module-push-server/src/main/resources/application.yaml @@ -106,3 +106,20 @@ msgpush: debug: false +aliyun: + sms: + access-key-id: LTAI4FxsR76x2dq3w9c5puUe + access-key-secret: GxkTR8fsrvHtixTlD9UPmOGli35tZs + regionId: cn-hangzhou + endpoint: dysmsapi.aliyuncs.com + mail: + access-key-id: LTAI4FxsR76x2dq3w9c5puUe + access-key-secret: GxkTR8fsrvHtixTlD9UPmOGli35tZs + regionId: cn-hangzhou + endpoint: dm.aliyuncs.com + +telecom: + sms: + account: 925631 + password: AMW2pOVrdky + diff --git a/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/AliYunMailClientTest.java b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/AliYunMailClientTest.java new file mode 100644 index 0000000..558ff40 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/AliYunMailClientTest.java @@ -0,0 +1,18 @@ +package com.njcn.msgpush.module.push; + + +import com.njcn.msgpush.module.push.client.channel.mail.impl.AliYunMailClient; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class AliYunMailClientTest { + @Autowired + private AliYunMailClient aliYunMailClient; + + @Test + public void testQueryMailAddressByParam(){ + aliYunMailClient.queryMailAddressByParam(); + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/AliYumSmsClientTest.java b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/AliYumSmsClientTest.java new file mode 100644 index 0000000..e12d4b9 --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/AliYumSmsClientTest.java @@ -0,0 +1,49 @@ +package com.njcn.msgpush.module.push.sms; + +import com.njcn.msgpush.module.push.client.channel.sms.Impl.AliYunSmsClient; +import com.njcn.msgpush.module.push.client.channel.sms.SmsClient; +import com.njcn.msgpush.module.push.client.channel.sms.factory.SmsFactory; +import com.njcn.msgpush.module.push.client.constant.ClientConstant; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author caozehui + * @data 2026-02-06 + */ +@SpringBootTest +public class AliYumSmsClientTest { + + @Autowired + private SmsFactory smsFactory; + + @Test + public void testSendSms() throws Exception { + Map params = new HashMap<>(); + params.put(AliYunSmsClient.SIGN_NAME, "灿能云"); + params.put(AliYunSmsClient.TEMPLATE_CODE, "SMS_481710295"); + params.put(AliYunSmsClient.TEMPLATE_PARAM, "{\"code\":\"123456\"}"); + boolean b = smsFactory.getClient("阿里云").sendSms(params, "18839431215"); + System.out.println(System.currentTimeMillis() + " " + b); + } + + @Test + public void testSendBatchSms() { + Map params = new HashMap<>(); + params.put(AliYunSmsClient.SIGN_NAME, List.of("灿能云")); + params.put(AliYunSmsClient.TEMPLATE_CODE, "SMS_481710295"); + params.put(AliYunSmsClient.TEMPLATE_PARAM, List.of("{\"code\":\"123456\"}")); + smsFactory.getClient("阿里云").sendBatchSms(params, List.of("18839431215")); + } + + @Test + public void testQuerySmsTemplateListRequest() { + SmsClient client = smsFactory.getClient(ClientConstant.ALI_YUN); + client.querySmsTemplateList(); + } +} diff --git a/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/TelecomSmsClientTest.java b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/TelecomSmsClientTest.java new file mode 100644 index 0000000..62859de --- /dev/null +++ b/msgpush-module-push/msgpush-module-push-server/src/test/java/com/njcn/msgpush/module/push/sms/TelecomSmsClientTest.java @@ -0,0 +1,33 @@ +package com.njcn.msgpush.module.push.sms; + +import com.njcn.msgpush.module.push.client.channel.sms.Impl.TelecomSmsClient; +import com.njcn.msgpush.module.push.client.channel.sms.factory.SmsFactory; +import com.njcn.msgpush.module.push.client.constant.ClientConstant; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +/** + * @author caozehui + * @data 2026-02-10 + */ +@SpringBootTest +public class TelecomSmsClientTest { + + @Autowired + private SmsFactory smsFactory; + + @Test + public void testSendSms() throws Exception { + Map params = new HashMap<>(); +// params.put(TelecomSmsClient.ACCOUNT, "925631"); +// params.put(TelecomSmsClient.PASSWORD, "AMW2pOVrdky"); + params.put(TelecomSmsClient.CONTENT, "【南京灿能电力】这是JUnit群发短信测试,请忽略。时间:" + LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + + smsFactory.getClient(ClientConstant.TELECOM).sendSms(params, "18839431215"); + } +} diff --git a/msgpush-server/src/main/java/com/njcn/msgpush/server/MsgpushServerApplication.java b/msgpush-server/src/main/java/com/njcn/msgpush/server/MsgpushServerApplication.java index cd719af..9910173 100644 --- a/msgpush-server/src/main/java/com/njcn/msgpush/server/MsgpushServerApplication.java +++ b/msgpush-server/src/main/java/com/njcn/msgpush/server/MsgpushServerApplication.java @@ -9,9 +9,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author hongawen */ @SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${msgpush.info.base-package} -@SpringBootApplication(scanBasePackages = {"${msgpush.info.base-package}.server", "${msgpush.info.base-package}.module"}, - excludeName = { - }) +@SpringBootApplication(scanBasePackages = {"${msgpush.info.base-package}.server", "${msgpush.info.base-package}.module"}, excludeName = {}) public class MsgpushServerApplication { public static void main(String[] args) {