# Conflicts: # mallinkAdmin/src/main/java/com/iformall/config/RedisConfig.java # mallinkAdmin/src/main/java/com/iformall/controller/DataTowerController.java # mallinkAdmin/src/main/java/com/iformall/controller/HomeController.java # mallinkAdmin/src/main/java/com/iformall/controller/WechatLoginController.java # mallinkAdmin/src/main/java/com/iformall/controller/WxDeviceScreenAdController.java # mallinkAdmin/src/main/java/com/iformall/controller/WxFlowAbleController.java # mallinkAdmin/src/main/java/com/iformall/controller/WxScreenAdController.java # mallinkCApi/src/main/java/com/iformall/controller/WxOrderController.java # mallinkCApi/src/main/java/com/iformall/controller/WxOrderGroupController.java # mallinkSchedule/src/main/java/com/iformall/schedule/OrderExpiringSchedule.java # mallinkService/src/main/java/com/iformall/common/ErrorCode.java # mallinkService/src/main/java/com/iformall/domain/po/WxAuthorizerInfo.java # mallinkService/src/main/java/com/iformall/domain/po/WxScreenAd.java # mallinkService/src/main/java/com/iformall/domain/po/WxWeappAuditStatus.java # mallinkService/src/main/java/com/iformall/domain/po/WxWeappReleaseStatus.java # mallinkService/src/main/java/com/iformall/domain/vo/WxCouponChannelVo.java # mallinkService/src/main/java/com/iformall/domain/vo/WxOrderCouponVo.java # mallinkService/src/main/java/com/iformall/domain/vo/WxWeappInfo.java # mallinkService/src/main/java/com/iformall/service/WxAuthorizerInfoService.java # mallinkService/src/main/java/com/iformall/service/WxCouponOrderService.java # mallinkService/src/main/java/com/iformall/service/WxOrderGroupService.java # mallinkService/src/main/java/com/iformall/service/WxScreenAdService.java # mallinkService/src/main/java/com/iformall/service/impl/MallUserRoleServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxAuthorizerInfoServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxCouponOrderServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxFlowServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxMsgValidationcodeServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxOrderGroupServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxOrderServiceImpl.java # mallinkService/src/main/java/com/iformall/service/impl/WxScreenAdServiceImpl.java # mallinkService/src/main/resources/mapper/WxAuthorizerInfoMapper.xml # mallinkService/src/main/resources/mapper/WxCouponChannelMapper.xml # mallinkService/src/main/resources/mapper/WxOrderGroupMapper.xml # mallinkService/src/main/resources/mapper/WxOrderMapper.xml # mallinkService/src/main/resources/mapper/WxScreenAdMapper.xml # mallinkWechatOpen/src/main/java/com/iformall/controller/WechatCalllbackController.java # mallinkWechatOpen/src/main/java/com/iformall/controller/WechatWeappCodeController.java # mallinkWechatOpen/src/main/java/com/iformall/controller/WxWeappInfoController.java # pom.xmlrelease_toaliyun_real
| @@ -1,6 +1,7 @@ | |||||
| package com.iformall; | package com.iformall; | ||||
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | ||||
| import org.rocketmq.starter.annotation.EnableRocketMQ; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.boot.SpringApplication; | import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| @@ -18,6 +19,7 @@ import tk.mybatis.spring.annotation.MapperScan; | |||||
| @EnableSwagger2 | @EnableSwagger2 | ||||
| @EnableEncryptableProperties | @EnableEncryptableProperties | ||||
| @EnableAsync | @EnableAsync | ||||
| @EnableRocketMQ | |||||
| public class UserApplication { | public class UserApplication { | ||||
| @Value("${fm.exception}") | @Value("${fm.exception}") | ||||
| @@ -1,4 +1,6 @@ | |||||
| spring: | spring: | ||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | # JDBC | ||||
| datasource: | datasource: | ||||
| url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false | url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false | ||||
| @@ -51,6 +53,23 @@ spring: | |||||
| auth: true | auth: true | ||||
| starttls: | starttls: | ||||
| enable: true | enable: true | ||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: 202.165.179.86 | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | aws: | ||||
| clientRegion: cn-northwest-1 | clientRegion: cn-northwest-1 | ||||
| bucketName: iformall-net | bucketName: iformall-net | ||||
| @@ -1,4 +1,6 @@ | |||||
| spring: | spring: | ||||
| profiles: | |||||
| include: rocketMQ | |||||
| # JDBC | # JDBC | ||||
| datasource: | datasource: | ||||
| url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false | url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false | ||||
| @@ -1,4 +1,6 @@ | |||||
| spring: | spring: | ||||
| profiles: | |||||
| include: rocketMQ | |||||
| # JDBC | # JDBC | ||||
| datasource: | datasource: | ||||
| url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false | url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false | ||||
| @@ -21,6 +21,23 @@ spring: | |||||
| cache-names: redis_cache #缓存的名字(可以不指定) | cache-names: redis_cache #缓存的名字(可以不指定) | ||||
| redis: | redis: | ||||
| time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) | time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) | ||||
| rocketmq: | |||||
| nameServer: 202.165.179.86:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: 202.165.179.86 | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| # @{link} https://github.com/abel533 | # @{link} https://github.com/abel533 | ||||
| #Mybatis | #Mybatis | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.iformall; | package com.iformall; | ||||
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | ||||
| import org.rocketmq.starter.annotation.EnableRocketMQ; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.boot.SpringApplication; | import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| @@ -14,6 +15,7 @@ import tk.mybatis.spring.annotation.MapperScan; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| @MapperScan(basePackages = {"com.iformall.mapper"}) | @MapperScan(basePackages = {"com.iformall.mapper"}) | ||||
| @EnableEncryptableProperties | @EnableEncryptableProperties | ||||
| @EnableRocketMQ | |||||
| public class BApplication { | public class BApplication { | ||||
| @Value("${fm.exception}") | @Value("${fm.exception}") | ||||
| @@ -12,6 +12,15 @@ spring: | |||||
| date-format: yyyy-MM-dd HH:mm:ss | date-format: yyyy-MM-dd HH:mm:ss | ||||
| time-zone: GMT+8 | time-zone: GMT+8 | ||||
| default-property-inclusion: non_null | default-property-inclusion: non_null | ||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| # @{link} https://github.com/abel533 | # @{link} https://github.com/abel533 | ||||
| #Mybatis | #Mybatis | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.iformall; | package com.iformall; | ||||
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | ||||
| import org.rocketmq.starter.annotation.EnableRocketMQ; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.boot.SpringApplication; | import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| @@ -14,6 +15,7 @@ import tk.mybatis.spring.annotation.MapperScan; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| @MapperScan(basePackages = {"com.iformall.mapper"}) | @MapperScan(basePackages = {"com.iformall.mapper"}) | ||||
| @EnableEncryptableProperties | @EnableEncryptableProperties | ||||
| @EnableRocketMQ | |||||
| public class CApplication { | public class CApplication { | ||||
| @Value("${fm.exception}") | @Value("${fm.exception}") | ||||
| @@ -12,6 +12,15 @@ spring: | |||||
| date-format: yyyy-MM-dd HH:mm:ss | date-format: yyyy-MM-dd HH:mm:ss | ||||
| time-zone: GMT+8 | time-zone: GMT+8 | ||||
| default-property-inclusion: non_null | default-property-inclusion: non_null | ||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| # @{link} https://github.com/abel533 | # @{link} https://github.com/abel533 | ||||
| #Mybatis | #Mybatis | ||||
| @@ -0,0 +1,35 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | |||||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |||||
| <modelVersion>4.0.0</modelVersion> | |||||
| <parent> | |||||
| <artifactId>mallink</artifactId> | |||||
| <groupId>com.iformall</groupId> | |||||
| <version>1.0</version> | |||||
| </parent> | |||||
| <artifactId>mallinkMQConsumer</artifactId> | |||||
| <dependencies> | |||||
| <dependency> | |||||
| <groupId>com.iformall</groupId> | |||||
| <artifactId>mallinkService</artifactId> | |||||
| <version>1.0</version> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-maven-plugin</artifactId> | |||||
| <configuration> | |||||
| <executable>true</executable> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </project> | |||||
| @@ -0,0 +1,35 @@ | |||||
| package com.iformall; | |||||
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | |||||
| import org.rocketmq.starter.annotation.EnableRocketMQ; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.boot.SpringApplication; | |||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||||
| import tk.mybatis.spring.annotation.MapperScan; | |||||
| /** | |||||
| * @author chenkx | |||||
| * @date 2017-12-26 | |||||
| */ | |||||
| @SpringBootApplication | |||||
| @MapperScan(basePackages = {"com.iformall.mapper"}) | |||||
| @EnableSwagger2 | |||||
| @EnableRocketMQ | |||||
| @EnableEncryptableProperties | |||||
| public class ConsumerApplication { | |||||
| @Value("${fm.exception}") | |||||
| private boolean fmException; | |||||
| @Bean | |||||
| public boolean isFmException() { | |||||
| return fmException; | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(ConsumerApplication.class, args); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
| import org.springframework.stereotype.Component; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Component | |||||
| @ConfigurationProperties(prefix = "aws") | |||||
| public class AwsProperty { | |||||
| // AWS ACCESS KEY | |||||
| private String access; | |||||
| private String secret; | |||||
| private String clientRegion; | |||||
| private String bucketName; | |||||
| public String getAccess() { | |||||
| return access; | |||||
| } | |||||
| public void setAccess(String access) { | |||||
| this.access = access; | |||||
| } | |||||
| public String getSecret() { | |||||
| return secret; | |||||
| } | |||||
| public void setSecret(String secret) { | |||||
| this.secret = secret; | |||||
| } | |||||
| public String getClientRegion() { | |||||
| return clientRegion; | |||||
| } | |||||
| public void setClientRegion(String clientRegion) { | |||||
| this.clientRegion = clientRegion; | |||||
| } | |||||
| public String getBucketName() { | |||||
| return bucketName; | |||||
| } | |||||
| public void setBucketName(String bucketName) { | |||||
| this.bucketName = bucketName; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,24 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
| import org.springframework.stereotype.Component; | |||||
| /** | |||||
| * @author Stormeye | |||||
| */ | |||||
| @Component | |||||
| @ConfigurationProperties(prefix = "pay") | |||||
| public class PayProperty { | |||||
| /** | |||||
| * 真实支付 | |||||
| */ | |||||
| private boolean real; | |||||
| public boolean isReal() { | |||||
| return real; | |||||
| } | |||||
| public void setReal(boolean real) { | |||||
| this.real = real; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,111 @@ | |||||
| package com.iformall.config; | |||||
| import com.iformall.domain.po.PushLimit; | |||||
| import com.iformall.domain.po.WxScoreRules; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.cache.CacheManager; | |||||
| import org.springframework.cache.annotation.CachingConfigurerSupport; | |||||
| import org.springframework.cache.annotation.EnableCaching; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.data.redis.cache.RedisCacheConfiguration; | |||||
| import org.springframework.data.redis.cache.RedisCacheManager; | |||||
| import org.springframework.data.redis.connection.RedisConnectionFactory; | |||||
| import org.springframework.data.redis.core.RedisTemplate; | |||||
| import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; | |||||
| import org.springframework.data.redis.serializer.StringRedisSerializer; | |||||
| import java.time.Duration; | |||||
| import java.util.HashMap; | |||||
| import java.util.HashSet; | |||||
| import java.util.Map; | |||||
| import java.util.Set; | |||||
| /** | |||||
| * Created by Stormeye on 2018/10/1. | |||||
| */ | |||||
| @Configuration | |||||
| @EnableCaching | |||||
| public class RedisConfig extends CachingConfigurerSupport { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| //缓存管理器 | |||||
| @Bean | |||||
| public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { | |||||
| /* | |||||
| //user信息缓存配置 | |||||
| RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user"); | |||||
| Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>(); | |||||
| redisCacheConfigurationMap.put("user", userCacheConfiguration); | |||||
| //初始化一个RedisCacheWriter | |||||
| RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); | |||||
| // 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现 | |||||
| // ClassLoader loader = this.getClass().getClassLoader(); | |||||
| // JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader); | |||||
| // RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer); | |||||
| // RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); | |||||
| RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); | |||||
| //设置默认超过期时间是30秒 | |||||
| defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); | |||||
| //初始化RedisCacheManager | |||||
| RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); | |||||
| return cacheManager; | |||||
| */ | |||||
| RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置 | |||||
| config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置 | |||||
| .disableCachingNullValues(); // 不缓存空值 | |||||
| // 设置一个初始化的缓存空间set集合 | |||||
| Set<String> cacheNames = new HashSet<>(); | |||||
| cacheNames.add("my-redis-cache1"); | |||||
| cacheNames.add("my-redis-cache2"); | |||||
| // 对每个缓存空间应用不同的配置 | |||||
| Map<String, RedisCacheConfiguration> configMap = new HashMap<>(); | |||||
| configMap.put("my-redis-cache1", config); | |||||
| configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120))); | |||||
| RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory) // 使用自定义的缓存配置初始化一个cacheManager | |||||
| .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置 | |||||
| .withInitialCacheConfigurations(configMap) | |||||
| .build(); | |||||
| return cacheManager; | |||||
| } | |||||
| @Bean("pushLimitRedisTemplate") | |||||
| public RedisTemplate<String, PushLimit> getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, PushLimit> template = new RedisTemplate<String, PushLimit>(); | |||||
| Jackson2JsonRedisSerializer<PushLimit> j = new Jackson2JsonRedisSerializer<PushLimit>(PushLimit.class); | |||||
| // value值的序列化 | |||||
| template.setValueSerializer(j); | |||||
| template.setHashKeySerializer(j); | |||||
| // key的序列化 | |||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setConnectionFactory(connectionFactory); | |||||
| return template; | |||||
| } | |||||
| @Bean("scoreRuleRedisTemplate") | |||||
| public RedisTemplate<String, WxScoreRules> getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, WxScoreRules> template = new RedisTemplate<String, WxScoreRules>(); | |||||
| Jackson2JsonRedisSerializer<WxScoreRules> j = new Jackson2JsonRedisSerializer<WxScoreRules>(WxScoreRules.class); | |||||
| // value值的序列化 | |||||
| template.setValueSerializer(j); | |||||
| template.setHashKeySerializer(j); | |||||
| // key的序列化 | |||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setConnectionFactory(connectionFactory); | |||||
| return template; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.config; | |||||
| import javax.servlet.*; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | |||||
| import java.io.IOException; | |||||
| import java.util.Optional; | |||||
| /** | |||||
| * 前后端分离RESTful接口过滤器 | |||||
| * | |||||
| * @author xuguoqin | |||||
| * | |||||
| */ | |||||
| public class RestFilter implements Filter { | |||||
| @Override | |||||
| public void init(FilterConfig filterConfig) throws ServletException { | |||||
| } | |||||
| @Override | |||||
| public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | |||||
| throws IOException, ServletException { | |||||
| HttpServletRequest req = null; | |||||
| if (request instanceof HttpServletRequest) { | |||||
| req = (HttpServletRequest) request; | |||||
| } | |||||
| HttpServletResponse res = null; | |||||
| if (response instanceof HttpServletResponse) { | |||||
| res = (HttpServletResponse) response; | |||||
| } | |||||
| if (req != null && res != null) { | |||||
| //设置允许传递的参数 | |||||
| res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); | |||||
| //设置允许带上cookie | |||||
| res.setHeader("Access-Control-Allow-Credentials", "true"); | |||||
| String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer")); | |||||
| //设置允许的请求来源 | |||||
| res.setHeader("Access-Control-Allow-Origin", origin); | |||||
| //设置允许的请求方法 | |||||
| res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS"); | |||||
| } | |||||
| chain.doFilter(request, response); | |||||
| } | |||||
| @Override | |||||
| public void destroy() { | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,24 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.http.client.ClientHttpRequestFactory; | |||||
| import org.springframework.http.client.SimpleClientHttpRequestFactory; | |||||
| import org.springframework.web.client.RestTemplate; | |||||
| @Configuration | |||||
| public class RestTemplateConfig { | |||||
| @Bean | |||||
| public RestTemplate restTemplate(ClientHttpRequestFactory factory) { | |||||
| return new RestTemplate(factory); | |||||
| } | |||||
| @Bean | |||||
| public ClientHttpRequestFactory simpleClientHttpRequestFactory() { | |||||
| SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); | |||||
| factory.setReadTimeout(5000);//ms | |||||
| factory.setConnectTimeout(10000);//ms | |||||
| return factory; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,79 @@ | |||||
| package com.iformall.config; | |||||
| import com.fasterxml.jackson.annotation.JsonInclude; | |||||
| import com.fasterxml.jackson.databind.DeserializationConfig; | |||||
| import com.fasterxml.jackson.databind.DeserializationFeature; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import com.fasterxml.jackson.databind.module.SimpleModule; | |||||
| import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import org.springframework.http.converter.HttpMessageConverter; | |||||
| import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | |||||
| import org.springframework.web.servlet.config.annotation.CorsRegistry; | |||||
| import org.springframework.web.servlet.config.annotation.EnableWebMvc; | |||||
| import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | |||||
| import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||||
| import java.math.BigDecimal; | |||||
| import java.math.BigInteger; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.List; | |||||
| @Configuration | |||||
| @EnableWebMvc | |||||
| public class WebConfig implements WebMvcConfigurer { | |||||
| @Override | |||||
| public void addResourceHandlers(ResourceHandlerRegistry registry) { | |||||
| registry.addResourceHandler("swagger-ui.html") | |||||
| .addResourceLocations("classpath:/META-INF/resources/"); | |||||
| registry.addResourceHandler("/webjars/**") | |||||
| .addResourceLocations("classpath:/META-INF/resources/webjars/"); | |||||
| //registry.addResourceHandler("/app/**").addResourceLocations("classpath:/app/"); | |||||
| } | |||||
| @Override | |||||
| public void addCorsMappings(CorsRegistry registry) { | |||||
| registry.addMapping("/**") | |||||
| .allowedOrigins("*") | |||||
| .allowCredentials(true) | |||||
| .allowedMethods("GET", "POST", "DELETE", "PUT") | |||||
| .maxAge(3600); | |||||
| } | |||||
| @Override | |||||
| public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { | |||||
| MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); | |||||
| //ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然 | |||||
| ObjectMapper objectMapper = new ObjectMapper(); | |||||
| SimpleModule simpleModule = new SimpleModule(); | |||||
| //不显示为null的字段 | |||||
| objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); | |||||
| DeserializationConfig dc = objectMapper.getDeserializationConfig(); | |||||
| // 设置反序列化日期格式、忽略不存在get、set的属性 | |||||
| objectMapper.setConfig( | |||||
| dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) | |||||
| .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) | |||||
| ); | |||||
| //序列化将Long转String类型 | |||||
| simpleModule.addSerializer(Long.class, ToStringSerializer.instance); | |||||
| simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); | |||||
| SimpleModule bigIntegerModule = new SimpleModule(); | |||||
| //序列化将BigInteger转String类型 | |||||
| bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance); | |||||
| SimpleModule bigDecimalModule = new SimpleModule(); | |||||
| //序列化将BigDecimal转String类型 | |||||
| bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); | |||||
| objectMapper.registerModule(simpleModule); | |||||
| objectMapper.registerModule(bigDecimalModule); | |||||
| objectMapper.registerModule(bigIntegerModule); | |||||
| jackson2HttpMessageConverter.setObjectMapper(objectMapper); | |||||
| converters.add(jackson2HttpMessageConverter); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,93 @@ | |||||
| package com.iformall.controller; | |||||
| import com.iformall.common.ResultData; | |||||
| import com.iformall.domain.po.MailMsg; | |||||
| import com.iformall.domain.po.WxMsgRecord; | |||||
| import com.iformall.enums.EnumMsgRecordType; | |||||
| import com.iformall.mq.MQConfig; | |||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.mq.impl.RabbitMqMessageProducer; | |||||
| import com.iformall.mq.impl.RocketMqMessageProducer; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.apache.commons.collections.map.HashedMap; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.context.annotation.Profile; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import java.util.Map; | |||||
| @RestController | |||||
| @Api(description = "登录相关接口") | |||||
| public class HomeController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Value("${version}") | |||||
| private String version; | |||||
| @Autowired | |||||
| private MqBaseProducer mqBaseProducer; | |||||
| // @Autowired | |||||
| // private RabbitMqMessageProducer rabbitMqMessageProducer; | |||||
| @Value("${spring.mail.username}") | |||||
| private String from; | |||||
| @ApiOperation("获取后端版本号") | |||||
| @GetMapping("/version") | |||||
| public ResultData version() { | |||||
| return new ResultData(version); | |||||
| } | |||||
| @GetMapping("/mqtest") | |||||
| public ResultData mqtest() { | |||||
| WxMsgRecord wxMsgRecord = new WxMsgRecord(); | |||||
| wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode()); | |||||
| wxMsgRecord.setSender("aa"); | |||||
| wxMsgRecord.setModelType(4); | |||||
| wxMsgRecord.setReceiver("18601973448"); | |||||
| wxMsgRecord.setSignature("富茂科技"); | |||||
| wxMsgRecord.setTenantId("456"); | |||||
| Map<String,String> map = new HashedMap(); | |||||
| map.put("contract","A11111"); | |||||
| map.put("page","www.baidu.com"); | |||||
| wxMsgRecord.setDynamicContentMap(map); | |||||
| mqBaseProducer.sendMessage(wxMsgRecord, "topic-1", "tag-1", "key-1"); | |||||
| return new ResultData(); | |||||
| } | |||||
| @GetMapping("/mail") | |||||
| public ResultData mail() { | |||||
| MailMsg wxMsgRecord = new MailMsg(); | |||||
| wxMsgRecord.setMsgType(EnumMsgRecordType.EMAIL.getCode()); | |||||
| wxMsgRecord.setFrom(from); | |||||
| wxMsgRecord.setTo(new String[]{"luozukai@iformall.com"}); | |||||
| wxMsgRecord.setSubject("回家吃饭了"); | |||||
| wxMsgRecord.setMsg("大熊熊"); | |||||
| mqBaseProducer.sendMessage(wxMsgRecord, "topic-1", "tag-1", "key-1"); | |||||
| return new ResultData(); | |||||
| } | |||||
| /** | |||||
| * 重发 | |||||
| * @return | |||||
| */ | |||||
| @GetMapping("/resend") | |||||
| public ResultData resend() { | |||||
| MailMsg wxMsgRecord = new MailMsg(); | |||||
| wxMsgRecord.setMsgType(EnumMsgRecordType.EMAIL.getCode()); | |||||
| wxMsgRecord.setFrom(from); | |||||
| wxMsgRecord.setTo(new String[]{"luozukai@iformall.com"}); | |||||
| wxMsgRecord.setSubject("回家吃饭了"); | |||||
| wxMsgRecord.setMsg("大熊熊"); | |||||
| mqBaseProducer.sendMessage(wxMsgRecord, "topic-1", "tag-1", "key-1"); | |||||
| return new ResultData(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,72 @@ | |||||
| package com.iformall.mq; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.mapper.WxMsgRecordMapper; | |||||
| import com.iformall.service.impl.SendCallBackSmsServiceImpl; | |||||
| import com.iformall.service.impl.SendEmailServiceImpl; | |||||
| import com.iformall.service.impl.SendSmartAppMsgServiceImpl; | |||||
| import com.iformall.service.impl.SendSmsServiceImpl; | |||||
| import com.iformall.utils.JsonUtil; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| /** | |||||
| * 消息消费入口 | |||||
| */ | |||||
| @Service | |||||
| public class MqBaseConsumer { | |||||
| private final Logger log = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxMsgRecordMapper wxMsgRecordMapper; | |||||
| @Autowired | |||||
| private SendSmsServiceImpl sendSmsService; | |||||
| @Autowired | |||||
| private SendCallBackSmsServiceImpl sendCallBackSmsService; | |||||
| @Autowired | |||||
| private SendEmailServiceImpl sendEmailService; | |||||
| @Autowired | |||||
| private SendSmartAppMsgServiceImpl sendSmartAppMsgService; | |||||
| @Autowired | |||||
| private MqBaseProducer mqBaseProducer; | |||||
| public void doMessage(String message) { | |||||
| log.info("received message: {}", message); | |||||
| BaseMsg baseMsg = null; | |||||
| try { | |||||
| baseMsg = (BaseMsg)JsonUtil.readValue(message,BaseMsg.class); | |||||
| if(EnumMsgRecordType.SMS.getCode().equals(baseMsg.getMsgType())){ | |||||
| //短信 | |||||
| sendSmsService.send((WxMsgRecord)JsonUtil.readValue(message,WxMsgRecord.class)); | |||||
| }else if(EnumMsgRecordType.SMS_CALLBACK.getCode().equals(baseMsg.getMsgType())){ | |||||
| //业务短信 | |||||
| sendCallBackSmsService.send((WxMsg)JsonUtil.readValue(message,WxMsg.class)); | |||||
| }else if(EnumMsgRecordType.EMAIL.getCode().equals(baseMsg.getMsgType())){ | |||||
| //邮件 | |||||
| sendEmailService.send((MailMsg)JsonUtil.readValue(message,MailMsg.class)); | |||||
| }else if(EnumMsgRecordType.SMART_APP.getCode().equals(baseMsg.getMsgType())){ | |||||
| //微信小程序 | |||||
| sendSmartAppMsgService.send((SmartAppMsg)JsonUtil.readValue(message,SmartAppMsg.class)); | |||||
| } | |||||
| baseMsg.setMsgStatus(EnumMsgRecordStatus.CONSUME_SUCC.getCode()); | |||||
| wxMsgRecordMapper.update(baseMsg); | |||||
| }catch (Exception e){ | |||||
| if(null != baseMsg){ | |||||
| if(baseMsg.getDelayTimeLevel() < 3){ | |||||
| baseMsg.setDelayTimeLevel(3); //10s后重试 | |||||
| mqBaseProducer.sendMessage(baseMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| }else{ | |||||
| baseMsg.setStatusMessage(e.getMessage()); | |||||
| baseMsg.setMsgStatus(EnumMsgRecordStatus.CONSUME_FAIL.getCode()); | |||||
| wxMsgRecordMapper.update(baseMsg); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,42 @@ | |||||
| package com.iformall.mq.impl; | |||||
| import com.iformall.mq.MqBaseConsumer; | |||||
| import com.iformall.mq.MQConfig; | |||||
| import org.springframework.amqp.core.*; | |||||
| import org.springframework.amqp.rabbit.annotation.RabbitListener; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.context.annotation.Profile; | |||||
| import org.springframework.stereotype.Component; | |||||
| import javax.annotation.PostConstruct; | |||||
| @Component | |||||
| @Profile(MQConfig.Impl.RABBIT_MQ) | |||||
| public class RabbitMqConsumer extends MqBaseConsumer { | |||||
| String queueName = "topic-1"; | |||||
| @Autowired | |||||
| private AmqpAdmin amqpAdmin; | |||||
| @PostConstruct | |||||
| public void init() { | |||||
| DirectExchange exchange = new DirectExchange(queueName); | |||||
| Queue queue = new Queue(queueName); | |||||
| Binding binding = BindingBuilder.bind(queue).to(exchange).withQueueName(); | |||||
| amqpAdmin.declareExchange(exchange); | |||||
| amqpAdmin.declareQueue(queue); | |||||
| amqpAdmin.declareBinding(binding); | |||||
| } | |||||
| @Autowired | |||||
| private AmqpTemplate rabbitTemplate; | |||||
| public void send(String msg) { | |||||
| rabbitTemplate.convertAndSend(queueName, msg); | |||||
| } | |||||
| @RabbitListener(queues = "topic-1") | |||||
| public void onMessage(String message) { | |||||
| doMessage(message); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,19 @@ | |||||
| package com.iformall.mq.impl; | |||||
| import com.iformall.mq.MqBaseConsumer; | |||||
| import com.iformall.mq.MQConfig; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.rocketmq.starter.annotation.RocketMQListener; | |||||
| import org.rocketmq.starter.annotation.RocketMQMessage; | |||||
| import org.springframework.context.annotation.Profile; | |||||
| @Slf4j | |||||
| @Profile(MQConfig.Impl.ROCKET_MQ) | |||||
| @RocketMQListener(topic = "topic-1",consumeThreadMax=100,consumeThreadMin = 20) | |||||
| public class RocketMqConsumer extends MqBaseConsumer { | |||||
| @RocketMQMessage(messageClass = String.class, tag = "tag-1") | |||||
| public void onMessage(String message) { | |||||
| doMessage(message); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,89 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false | |||||
| username: ENC(dZ8fmrtuBMQYaRytKQgTqg==) | |||||
| password: ENC(WGu0+1DPIHrqorDhrbq1+7wr7xNG53mN) | |||||
| type: com.alibaba.druid.pool.DruidDataSource | |||||
| driver-class-name: com.mysql.cj.jdbc.Driver | |||||
| filters: stat | |||||
| maxActive: 20 | |||||
| initialSize: 1 | |||||
| maxWait: 60000 | |||||
| minIdle: 1 | |||||
| timeBetweenEvictionRunsMillis: 28000 | |||||
| minEvictableIdleTimeMillis: 28000 | |||||
| validationQuery: select 'x' | |||||
| testWhileIdle: true | |||||
| testOnBorrow: false | |||||
| testOnReturn: false | |||||
| poolPreparedStatements: true | |||||
| maxOpenPreparedStatements: 20 | |||||
| connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" | |||||
| #jackson: | |||||
| #date-format: yyyy-MM-dd HH:mm:ss | |||||
| # REDIS | |||||
| redis: | |||||
| host: 202.165.179.86 | |||||
| port: 6379 | |||||
| password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 50 | |||||
| max-idle: 50 | |||||
| max-wait: -1 | |||||
| min-idle: 10 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(R0bER9E9OB9/YQcpNXMyYDwofNVb8/pFl4nrApS8mi0=) | |||||
| password: ENC(50YqJd0iK/2r2YnmEd5RKaki3ktU73UDapBJrVYfqmc=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: 202.165.179.86 | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) | |||||
| secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) | |||||
| jasypt: | |||||
| encryptor: | |||||
| password: oRqdnDbK5pj3eMmB | |||||
| fm: | |||||
| exception: false | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall.mapper: debug | |||||
| path: ./logs/s | |||||
| @@ -0,0 +1,65 @@ | |||||
| spring: | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false | |||||
| username: ENC(NUzgQOdJnCbVLKT6BaX0aw==) | |||||
| password: ENC(mvuoDRiu0jqYaKNRwwTuXZ6U7aoIaqsjdiPqTLgi/nY=) | |||||
| type: com.alibaba.druid.pool.DruidDataSource | |||||
| driver-class-name: com.mysql.cj.jdbc.Driver | |||||
| filters: stat | |||||
| maxActive: 20 | |||||
| initialSize: 1 | |||||
| maxWait: 60000 | |||||
| minIdle: 1 | |||||
| timeBetweenEvictionRunsMillis: 28000 | |||||
| minEvictableIdleTimeMillis: 28000 | |||||
| validationQuery: select 'x' | |||||
| testWhileIdle: true | |||||
| testOnBorrow: false | |||||
| testOnReturn: false | |||||
| poolPreparedStatements: true | |||||
| maxOpenPreparedStatements: 20 | |||||
| connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" | |||||
| # REDIS | |||||
| redis: | |||||
| host: 127.0.0.1 | |||||
| port: 6379 | |||||
| password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 8 | |||||
| max-idle: 8 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(I2YKxnRVPY7J1r/bwzwHOhQCjj3nVqCWEbVTJvBq7y0=) | |||||
| password: ENC(APQMO9XQRzMKd0eap+oSSOYH9MQe/r5K0YFF9A9mizU=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) | |||||
| secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) | |||||
| fm: | |||||
| exception: true | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall: debug | |||||
| path: ./logs/s | |||||
| @@ -0,0 +1,63 @@ | |||||
| spring: | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false | |||||
| username: ENC(Uc0AjgkytxHHCwZrmDASWg==) | |||||
| password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=) | |||||
| type: com.alibaba.druid.pool.DruidDataSource | |||||
| driver-class-name: com.mysql.cj.jdbc.Driver | |||||
| filters: stat | |||||
| maxActive: 20 | |||||
| initialSize: 1 | |||||
| maxWait: 60000 | |||||
| minIdle: 1 | |||||
| timeBetweenEvictionRunsMillis: 28000 | |||||
| minEvictableIdleTimeMillis: 28000 | |||||
| validationQuery: select 'x' | |||||
| testWhileIdle: true | |||||
| testOnBorrow: false | |||||
| testOnReturn: false | |||||
| poolPreparedStatements: true | |||||
| maxOpenPreparedStatements: 20 | |||||
| connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" | |||||
| # REDIS | |||||
| redis: | |||||
| host: 127.0.0.1 | |||||
| port: 6379 | |||||
| password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 8 | |||||
| max-idle: 8 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(HFbRXtAFVxU36Hk0yT3reyvRuLrw3RhMlbxFj9Ev/VY=) | |||||
| password: ENC(pk4+/3C5n2hMYmgi+VTqI4P1m77DllW8y4KElMXXmIo=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) | |||||
| secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) | |||||
| fm: | |||||
| exception: true | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall: debug | |||||
| path: ./logs/s | |||||
| @@ -0,0 +1,73 @@ | |||||
| server: | |||||
| port: 5001 | |||||
| servlet: | |||||
| context-path: /mq | |||||
| spring: | |||||
| application: | |||||
| name: mallink | |||||
| profiles: | |||||
| active: dev | |||||
| jackson: | |||||
| date-format: yyyy-MM-dd HH:mm:ss | |||||
| time-zone: GMT+8 | |||||
| default-property-inclusion: non_null | |||||
| servlet: | |||||
| multipart: | |||||
| max-file-size: 2MB | |||||
| max-request-size: 2MB | |||||
| cache: | |||||
| type: REDIS | |||||
| cache-names: redis_cache #缓存的名字(可以不指定) | |||||
| redis: | |||||
| time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) | |||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: 202.165.179.86 | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| # @{link} https://github.com/abel533 | |||||
| #Mybatis | |||||
| mybatis: | |||||
| type-aliases-package: com.iformall.domain.po | |||||
| mapper-locations: classpath:mapper/*Mapper.xml | |||||
| configuration: | |||||
| map-underscore-to-camel-case: true | |||||
| cache-enabled: true | |||||
| lazy-loading-enabled: true | |||||
| use-generated-keys: true | |||||
| default-fetch-size: 100 | |||||
| default-statement-timeout: 10 | |||||
| #PageHelper | |||||
| pagehelper: | |||||
| helperDialect: mysql | |||||
| reasonable: false | |||||
| supportMethodsArguments: true | |||||
| params: count=countSql | |||||
| offset-as-page-num: true | |||||
| page-size-zero: true | |||||
| row-bounds-with-count: true | |||||
| mapper: | |||||
| mappers: | |||||
| - com.iformall.common.CommonMapper | |||||
| pay: | |||||
| real: true | |||||
| version: @project.version@ | |||||
| @@ -0,0 +1,100 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <configuration scan="true" scanPeriod="10 seconds"> | |||||
| <!-- 外部指定路径 --> | |||||
| <springProperty scop="context" name="logPath" source="logging.path" /> | |||||
| <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | |||||
| <encoder> | |||||
| <Pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] --%mdc{client}%msg%n</Pattern> | |||||
| </encoder> | |||||
| </appender> | |||||
| <appender name="TRACE_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/trace.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/trace.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| </appender> | |||||
| <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/info.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/info.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>INFO</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/debug.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/debug.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>DEBUG</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/warn.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/warn.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>WARN</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |||||
| <file>${logPath}/error.log</file> | |||||
| <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | |||||
| <FileNamePattern>${logPath}/daily/error.%d{yyyy-MM-dd}.log</FileNamePattern> | |||||
| <maxHistory>180</maxHistory> <!-- 保留180天 --> | |||||
| </rollingPolicy> | |||||
| <layout> | |||||
| <pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] [%logger:%line]--%mdc{client} %msg%n</pattern> | |||||
| </layout> | |||||
| <filter class="ch.qos.logback.classic.filter.LevelFilter"> | |||||
| <level>ERROR</level> | |||||
| <onMatch>ACCEPT</onMatch> | |||||
| <onMismatch>DENY</onMismatch> | |||||
| </filter> | |||||
| </appender> | |||||
| <root level="TRACE"> | |||||
| <appender-ref ref="TRACE_FILE" /> | |||||
| <appender-ref ref="INFO_FILE" /> | |||||
| <!-- <appender-ref ref="DEBUG_FILE" /> --> | |||||
| <!-- <appender-ref ref="WARN_FILE" /> --> | |||||
| <appender-ref ref="ERROR_FILE" /> | |||||
| </root> | |||||
| <root level="INFO"> | |||||
| <appender-ref ref="STDOUT" /> | |||||
| </root> | |||||
| </configuration> | |||||
| @@ -1,6 +1,7 @@ | |||||
| package com.iformall; | package com.iformall; | ||||
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; | ||||
| import org.rocketmq.starter.annotation.EnableRocketMQ; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.boot.SpringApplication; | import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| @@ -15,6 +16,7 @@ import tk.mybatis.spring.annotation.MapperScan; | |||||
| @SpringBootApplication | @SpringBootApplication | ||||
| @MapperScan(basePackages = {"com.iformall.mapper"}) | @MapperScan(basePackages = {"com.iformall.mapper"}) | ||||
| @EnableSwagger2 | @EnableSwagger2 | ||||
| @EnableRocketMQ | |||||
| @EnableEncryptableProperties | @EnableEncryptableProperties | ||||
| public class ScheduleApplication { | public class ScheduleApplication { | ||||
| @@ -1,11 +1,18 @@ | |||||
| package com.iformall.controller; | package com.iformall.controller; | ||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.domain.po.WxMsgRecord; | |||||
| import com.iformall.mq.MQConfig; | |||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.mq.impl.RabbitMqMessageProducer; | |||||
| import com.iformall.mq.impl.RocketMqMessageProducer; | |||||
| import io.swagger.annotations.Api; | import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | import io.swagger.annotations.ApiOperation; | ||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.context.annotation.Profile; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | import org.springframework.web.bind.annotation.RestController; | ||||
| @@ -18,10 +25,22 @@ public class HomeController { | |||||
| @Value("${version}") | @Value("${version}") | ||||
| private String version; | private String version; | ||||
| @Autowired | |||||
| private MqBaseProducer mqBaseProducer; | |||||
| @Autowired | |||||
| private RabbitMqMessageProducer rabbitMqMessageProducer; | |||||
| @ApiOperation("获取后端版本号") | @ApiOperation("获取后端版本号") | ||||
| @GetMapping("/version") | @GetMapping("/version") | ||||
| public ResultData version() { | public ResultData version() { | ||||
| return new ResultData(version); | return new ResultData(version); | ||||
| } | } | ||||
| @GetMapping("/mqtest") | |||||
| public ResultData mqtest() { | |||||
| mqBaseProducer.sendMessage(new WxMsgRecord(), "topic-1", "tag-1", "key-1"); | |||||
| return new ResultData(); | |||||
| } | |||||
| } | } | ||||
| @@ -1,25 +1,18 @@ | |||||
| package com.iformall.schedule; | package com.iformall.schedule; | ||||
| import com.alibaba.fastjson.JSONObject; | import com.alibaba.fastjson.JSONObject; | ||||
| import com.iformall.common.IdWorker; | |||||
| import com.iformall.domain.po.WxMsgCallback; | |||||
| import com.iformall.domain.po.WxMsgConfig; | |||||
| import com.iformall.domain.po.WxMsgValidationcode; | |||||
| import com.iformall.domain.po.WxMsgValidationcodeModel; | |||||
| import com.iformall.enums.EnumMsgModel; | |||||
| import com.iformall.enums.EnumMsgSendStatus; | |||||
| import com.iformall.enums.EnumVerifyCode; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.mapper.*; | import com.iformall.mapper.*; | ||||
| import com.iformall.utils.WiwideUtil; | |||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import org.apache.commons.collections.map.HashedMap; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.scheduling.annotation.Scheduled; | import org.springframework.scheduling.annotation.Scheduled; | ||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| import java.math.BigDecimal; | import java.math.BigDecimal; | ||||
| import java.math.RoundingMode; | import java.math.RoundingMode; | ||||
| import java.util.Date; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | import java.util.Map; | ||||
| @@ -46,6 +39,9 @@ public class BillNotificationSchedule { | |||||
| @Autowired | @Autowired | ||||
| private WxMsgCallbackMapper wxMsgCallbackMapper; | private WxMsgCallbackMapper wxMsgCallbackMapper; | ||||
| @Autowired | |||||
| private MqBaseProducer mqBaseProducer; | |||||
| /** | /** | ||||
| * 每天9点执行 | * 每天9点执行 | ||||
| @@ -69,22 +65,17 @@ public class BillNotificationSchedule { | |||||
| String phone = bill.get("linkPhone").toString(); | String phone = bill.get("linkPhone").toString(); | ||||
| String appname = bill.get("appname").toString(); | String appname = bill.get("appname").toString(); | ||||
| logger.info("欠缴账单检验短信配置信息"); | logger.info("欠缴账单检验短信配置信息"); | ||||
| WxMsgConfig wxMsgConfig = checkMsgConfig(tenantId); | |||||
| if (wxMsgConfig != null) { | |||||
| logger.info("欠缴账单获取模板内容"); | |||||
| WxMsgValidationcodeModel wxMsgValidationcodeModel = getMsgModel(tenantId, EnumMsgModel.BILL_OWE.getCode()); | |||||
| if (wxMsgValidationcodeModel != null) { | |||||
| String signature = wxMsgValidationcodeModel.getSignature(); | |||||
| String msg = wxMsgValidationcodeModel.getContent(). | |||||
| replace("{price}", price.toString()). | |||||
| replace("{app}", appname); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| sendWaitPayBillMsg(phone, signature, msg, notifyUrl, secret, bid, publickey); | |||||
| } | |||||
| } | |||||
| WxMsgRecord wxMsgRecord = new WxMsgRecord(); | |||||
| wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode()); | |||||
| wxMsgRecord.setModelType(EnumMsgModel.BILL_OWE.getCode()); | |||||
| wxMsgRecord.setReceiver(phone); | |||||
| wxMsgRecord.setTenantId(tenantId); | |||||
| Map<String,String> map = new HashedMap(); | |||||
| map.put("price",price.toString()); | |||||
| map.put("app",appname); | |||||
| wxMsgRecord.setDynamicContentMap(map); | |||||
| mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } | } | ||||
| } | } | ||||
| @@ -100,87 +91,38 @@ public class BillNotificationSchedule { | |||||
| String phone = bill.get("linkPhone").toString(); | String phone = bill.get("linkPhone").toString(); | ||||
| String appname = bill.get("appname").toString(); | String appname = bill.get("appname").toString(); | ||||
| logger.info("待缴账单检验短信配置信息"); | logger.info("待缴账单检验短信配置信息"); | ||||
| WxMsgConfig wxMsgConfig = checkMsgConfig(tenantId); | |||||
| if (wxMsgConfig != null) { | |||||
| logger.info("待缴账单获取模板内容"); | |||||
| WxMsgValidationcodeModel wxMsgValidationcodeModel = getMsgModel(tenantId, EnumMsgModel.BILL_WAIT_PAY.getCode()); | |||||
| if (wxMsgValidationcodeModel != null) { | |||||
| String signature = wxMsgValidationcodeModel.getSignature(); | |||||
| String msg = wxMsgValidationcodeModel.getContent(). | |||||
| replace("{price}", price.toString()). | |||||
| replace("{date}", receiveDate). | |||||
| replace("{app}", appname); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| sendWaitPayBillMsg(phone, signature, msg, notifyUrl, secret, bid, publickey); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| private WxMsgConfig checkMsgConfig(String tenantId) { | |||||
| WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| wxMsgConfig.setTenantId(tenantId); | |||||
| List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| if (wxMsgConfigs.size() == 0) { | |||||
| logger.info("缺少系统短信配置"); | |||||
| return null; | |||||
| } | |||||
| wxMsgConfig = wxMsgConfigs.get(0); | |||||
| if (wxMsgConfig.getRemains() == 0) { | |||||
| logger.info("短信数量为0"); | |||||
| return null; | |||||
| } | |||||
| return wxMsgConfigs.get(0); | |||||
| } | |||||
| private WxMsgValidationcodeModel getMsgModel(String tenantId, Integer type) { | |||||
| logger.info("获取通知模板-租户:" + tenantId + ",类型:" + type); | |||||
| WxMsgValidationcodeModel wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); | |||||
| wxMsgValidationcodeModel.setTenantId(tenantId); | |||||
| wxMsgValidationcodeModel.setType(type); | |||||
| List<WxMsgValidationcodeModel> list = wxMsgValidationcodelModelMapper.findList(wxMsgValidationcodeModel); | |||||
| if (!list.isEmpty()) { | |||||
| return wxMsgValidationcodelModelMapper.findList(wxMsgValidationcodeModel).get(0); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private void sendWaitPayBillMsg(String phone, String signature, String msg, String notifyUrl, String secret, String bid, String publickey) { | |||||
| logger.info("开始调用迈外迪短信接口"); | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.YES.getCode().toString(), null); | |||||
| logger.info("迈外迪短信接口返回值:" + result); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| String batchNo = jsonObjectResult.get("data").toString(); | |||||
| if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode())) { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); | |||||
| wxMsgValidationcode.setId(idWorker.nextId()); | |||||
| wxMsgValidationcode.setCreatetime(new Date()); | |||||
| wxMsgValidationcodeMapper.insertSelective(wxMsgValidationcode); | |||||
| addMsgCallback(wxMsgValidationcode, batchNo); | |||||
| // WxMsgConfig wxMsgConfig = checkMsgConfig(tenantId); | |||||
| // if (wxMsgConfig != null) { | |||||
| // logger.info("待缴账单获取模板内容"); | |||||
| // WxMsgValidationcodeModel wxMsgValidationcodeModel = getMsgModel(tenantId, EnumMsgModel.BILL_WAIT_PAY.getCode()); | |||||
| // if (wxMsgValidationcodeModel != null) { | |||||
| // String signature = wxMsgValidationcodeModel.getSignature(); | |||||
| // String msg = wxMsgValidationcodeModel.getContent(). | |||||
| // replace("{price}", price.toString()). | |||||
| // replace("{date}", receiveDate). | |||||
| // replace("{app}", appname); | |||||
| // String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| // String secret = wxMsgConfig.getSecret(); | |||||
| // String bid = wxMsgConfig.getBid(); | |||||
| // String publickey = wxMsgConfig.getPublickey(); | |||||
| // sendWaitPayBillMsg(phone, signature, msg, notifyUrl, secret, bid, publickey); | |||||
| // } | |||||
| // } | |||||
| WxMsgRecord wxMsgRecord = new WxMsgRecord(); | |||||
| wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode()); | |||||
| wxMsgRecord.setModelType(EnumMsgModel.BILL_OWE.getCode()); | |||||
| wxMsgRecord.setReceiver(phone); | |||||
| wxMsgRecord.setTenantId(tenantId); | |||||
| Map<String,String> map = new HashedMap(); | |||||
| map.put("price",price.toString()); | |||||
| map.put("app",appname); | |||||
| map.put("date",receiveDate); | |||||
| wxMsgRecord.setDynamicContentMap(map); | |||||
| mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } | } | ||||
| } | |||||
| public void addMsgCallback(WxMsgValidationcode wxmsg, String batchNo) { | |||||
| logger.info("验证码发送时主动添加回调记录开始..."); | |||||
| String phone = wxmsg.getPhone(); | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| WxMsgCallback wxMsgCallback = new WxMsgCallback(); | |||||
| wxMsgCallback.setId(idWorker.nextId()); | |||||
| wxMsgCallback.setPhone(phone); | |||||
| wxMsgCallback.setTenantId(wxmsg.getTenantId()); | |||||
| wxMsgCallback.setBatchNo(batchNo); | |||||
| wxMsgCallback.setMsgId(wxmsg.getId()); | |||||
| wxMsgCallback.setStatus(EnumMsgSendStatus.MSG_SENDING.getCode()); | |||||
| wxMsgCallback.setCreatetime(new Date()); | |||||
| wxMsgCallbackMapper.insertSelective(wxMsgCallback); | |||||
| logger.info("验证码发送时主动添加回调记录结束..."); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,24 +1,18 @@ | |||||
| package com.iformall.schedule; | package com.iformall.schedule; | ||||
| import com.alibaba.fastjson.JSONArray; | import com.alibaba.fastjson.JSONArray; | ||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.domain.po.WxMsg; | import com.iformall.domain.po.WxMsg; | ||||
| import com.iformall.domain.po.WxMsgConfig; | |||||
| import com.iformall.domain.po.WxMsgModel; | |||||
| import com.iformall.enums.EnumMsgSendStatus; | |||||
| import com.iformall.enums.EnumMsgStatus; | |||||
| import com.iformall.enums.EnumVerifyCode; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.mapper.WxMsgConfigMapper; | import com.iformall.mapper.WxMsgConfigMapper; | ||||
| import com.iformall.mapper.WxMsgMapper; | import com.iformall.mapper.WxMsgMapper; | ||||
| import com.iformall.mapper.WxMsgModelMapper; | import com.iformall.mapper.WxMsgModelMapper; | ||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| import com.iformall.utils.WiwideUtil; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.scheduling.annotation.Scheduled; | import org.springframework.scheduling.annotation.Scheduled; | ||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||
| import java.util.List; | import java.util.List; | ||||
| /** | /** | ||||
| @@ -38,6 +32,9 @@ public class MsgSendingSchedule { | |||||
| @Autowired | @Autowired | ||||
| private WxMsgModelMapper wxMsgModelMapper; | private WxMsgModelMapper wxMsgModelMapper; | ||||
| @Autowired | |||||
| private MqBaseProducer mqBaseProducer; | |||||
| /** | /** | ||||
| * 每小时第一分钟执行 | * 每小时第一分钟执行 | ||||
| */ | */ | ||||
| @@ -51,55 +48,57 @@ public class MsgSendingSchedule { | |||||
| List<WxMsg> list = wxMsgMapper.findList(wxMsg); | List<WxMsg> list = wxMsgMapper.findList(wxMsg); | ||||
| logger.info("将要发送的短信列表:" + JSONArray.toJSONString(list)); | logger.info("将要发送的短信列表:" + JSONArray.toJSONString(list)); | ||||
| for (WxMsg msg : list) { | for (WxMsg msg : list) { | ||||
| sendmsg(msg); | |||||
| //sendmsg(msg); | |||||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(),null); | |||||
| } | } | ||||
| logger.info("sendmsg定时任务结束"); | logger.info("sendmsg定时任务结束"); | ||||
| } | } | ||||
| public void sendmsg(WxMsg wxMsg) { | |||||
| logger.info("发送短信开始----------"); | |||||
| //从短信配置中查询密钥 bid 等信息 | |||||
| WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| wxMsgConfig.setTenantId(wxMsg.getTenantId()); | |||||
| List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| if (wxMsgConfigs.size() == 0) { | |||||
| logger.info("短信相关配置不存在"); | |||||
| return; | |||||
| } | |||||
| wxMsgConfig = wxMsgConfigs.get(0); | |||||
| if (wxMsgConfig.getRemains() == 0) { | |||||
| logger.info("短信数量为0"); | |||||
| return; | |||||
| } | |||||
| if (wxMsgConfig.getRemains() < wxMsg.getExpectSendNumber()) { | |||||
| logger.info("短信数量不足"); | |||||
| return; | |||||
| } | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| String phone = wxMsg.getPhones(); | |||||
| String signature = wxMsg.getSignature(); | |||||
| String msg = wxMsg.getMsg(); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| Integer modelId = null; | |||||
| Long modelIdParam = wxMsg.getModelId(); | |||||
| if (modelIdParam != null) { | |||||
| WxMsgModel wxMsgModel = wxMsgModelMapper.selectByPrimaryKey(modelIdParam); | |||||
| modelId = wxMsgModel.getModelId(); | |||||
| } | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.NO.getCode().toString(), modelId); | |||||
| logger.info("短信返回结果:" + result); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| if (ret.equals("1")) { | |||||
| wxMsg.setSendstatus(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode()); | |||||
| } else { | |||||
| wxMsg.setSendstatus(EnumMsgSendStatus.MSG_SEND_FAIL.getCode()); | |||||
| } | |||||
| wxMsg.setStatus(EnumMsgStatus.MSG_STATUS_SENDED.getCode()); | |||||
| wxMsgMapper.updateByPrimaryKeySelective(wxMsg); | |||||
| logger.info("短信发送结束:" + jsonObjectResult.toJSONString()); | |||||
| } | |||||
| // @Deprecated | |||||
| // public void sendmsg(WxMsg wxMsg) { | |||||
| // logger.info("发送短信开始----------"); | |||||
| // //从短信配置中查询密钥 bid 等信息 | |||||
| // WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| // wxMsgConfig.setTenantId(wxMsg.getTenantId()); | |||||
| // List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| // if (wxMsgConfigs.size() == 0) { | |||||
| // logger.info("短信相关配置不存在"); | |||||
| // return; | |||||
| // } | |||||
| // wxMsgConfig = wxMsgConfigs.get(0); | |||||
| // if (wxMsgConfig.getRemains() == 0) { | |||||
| // logger.info("短信数量为0"); | |||||
| // return; | |||||
| // } | |||||
| // if (wxMsgConfig.getRemains() < wxMsg.getExpectSendNumber()) { | |||||
| // logger.info("短信数量不足"); | |||||
| // return; | |||||
| // } | |||||
| // String secret = wxMsgConfig.getSecret(); | |||||
| // String bid = wxMsgConfig.getBid(); | |||||
| // String publickey = wxMsgConfig.getPublickey(); | |||||
| // String phone = wxMsg.getPhones(); | |||||
| // String signature = wxMsg.getSignature(); | |||||
| // String msg = wxMsg.getMsg(); | |||||
| // String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| // Integer modelId = null; | |||||
| // Long modelIdParam = wxMsg.getModelId(); | |||||
| // if (modelIdParam != null) { | |||||
| // WxMsgModel wxMsgModel = wxMsgModelMapper.selectByPrimaryKey(modelIdParam); | |||||
| // modelId = wxMsgModel.getModelId(); | |||||
| // } | |||||
| // String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.NO.getCode().toString(), modelId); | |||||
| // logger.info("短信返回结果:" + result); | |||||
| // JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| // String ret = jsonObjectResult.get("ret").toString(); | |||||
| // if (ret.equals("1")) { | |||||
| // wxMsg.setSendstatus(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode()); | |||||
| // } else { | |||||
| // wxMsg.setSendstatus(EnumMsgSendStatus.MSG_SEND_FAIL.getCode()); | |||||
| // } | |||||
| // wxMsg.setStatus(EnumMsgStatus.MSG_STATUS_SENDED.getCode()); | |||||
| // wxMsgMapper.updateByPrimaryKeySelective(wxMsg); | |||||
| // logger.info("短信发送结束:" + jsonObjectResult.toJSONString()); | |||||
| // } | |||||
| } | } | ||||
| @@ -1,4 +1,6 @@ | |||||
| spring: | spring: | ||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | # JDBC | ||||
| datasource: | datasource: | ||||
| url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false | url: jdbc:mysql://202.165.179.86:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false | ||||
| @@ -21,7 +21,22 @@ spring: | |||||
| cache-names: redis_cache #缓存的名字(可以不指定) | cache-names: redis_cache #缓存的名字(可以不指定) | ||||
| redis: | redis: | ||||
| time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) | time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) | ||||
| rocketmq: | |||||
| nameServer: 127.0.0.1:9876 | |||||
| producer: | |||||
| retry-times-when-send-async-failed: 0 | |||||
| send-msg-timeout: 300000 | |||||
| compress-msg-body-over-howmuch: 4096 | |||||
| max-message-size: 4194304 | |||||
| retry-another-broker-when-not-store-ok: false | |||||
| retry-times-when-send-failed: 2 | |||||
| rabbitmq: | |||||
| host: 127.0.0.1 | |||||
| port: 5672 | |||||
| username: guest | |||||
| password: guest | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| # @{link} https://github.com/abel533 | # @{link} https://github.com/abel533 | ||||
| @@ -0,0 +1,66 @@ | |||||
| package com.iformall.domain.po; | |||||
| import java.io.Serializable; | |||||
| /** | |||||
| * @author luozukai | |||||
| * @date 2019/3/7 10:05 | |||||
| */ | |||||
| public class BaseMsg implements Serializable { | |||||
| private static final long serialVersionUID = 923764283764823L; | |||||
| //唯一标识 | |||||
| private String uuid; | |||||
| //消息类型 1短信 2回调短信 3邮件 4微信小程序模板 5微信公众号模板 6系统通知 | |||||
| private Integer msgType; | |||||
| //消息状态 0默认1发送成功2消费成功3消费失败 | |||||
| private Integer msgStatus; | |||||
| //结果信息 | |||||
| private String statusMessage; | |||||
| //延迟消息1s,5s,10s,30s,1m,2m,3m,4m,5m,6m,7m,8m,9m,10m,20m,30m,1h,2h | |||||
| private Integer delayTimeLevel = 0; | |||||
| public Integer getDelayTimeLevel() { | |||||
| return delayTimeLevel; | |||||
| } | |||||
| public void setDelayTimeLevel(Integer delayTimeLevel) { | |||||
| this.delayTimeLevel = delayTimeLevel; | |||||
| } | |||||
| public String getStatusMessage() { | |||||
| return statusMessage; | |||||
| } | |||||
| public void setStatusMessage(String statusMessage) { | |||||
| this.statusMessage = statusMessage; | |||||
| } | |||||
| public String getUuid() { | |||||
| return uuid; | |||||
| } | |||||
| public void setUuid(String uuid) { | |||||
| this.uuid = uuid; | |||||
| } | |||||
| public Integer getMsgStatus() { | |||||
| return msgStatus; | |||||
| } | |||||
| public void setMsgStatus(Integer msgStatus) { | |||||
| this.msgStatus = msgStatus; | |||||
| } | |||||
| public Integer getMsgType() { | |||||
| return msgType; | |||||
| } | |||||
| public void setMsgType(Integer msgType) { | |||||
| this.msgType = msgType; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,87 @@ | |||||
| package com.iformall.domain.po; | |||||
| /** | |||||
| * @author luozukai | |||||
| * @date 2019/3/7 10:05 | |||||
| */ | |||||
| public class MailMsg extends BaseMsg { | |||||
| private static final long serialVersionUID = 923764283760321L; | |||||
| private String[] to; | |||||
| private String from; | |||||
| private String msg; | |||||
| //标题 | |||||
| private String subject; | |||||
| //是否html格式 | |||||
| private boolean isHtml; | |||||
| //附件 | |||||
| private String filePath; | |||||
| //嵌入静态资源 | |||||
| private String rscPath; | |||||
| private String rscI; | |||||
| public String[] getTo() { | |||||
| return to; | |||||
| } | |||||
| public void setTo(String[] to) { | |||||
| this.to = to; | |||||
| } | |||||
| public String getFrom() { | |||||
| return from; | |||||
| } | |||||
| public void setFrom(String from) { | |||||
| this.from = from; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public String getSubject() { | |||||
| return subject; | |||||
| } | |||||
| public void setSubject(String subject) { | |||||
| this.subject = subject; | |||||
| } | |||||
| public boolean isHtml() { | |||||
| return isHtml; | |||||
| } | |||||
| public void setHtml(boolean html) { | |||||
| isHtml = html; | |||||
| } | |||||
| public String getFilePath() { | |||||
| return filePath; | |||||
| } | |||||
| public void setFilePath(String filePath) { | |||||
| this.filePath = filePath; | |||||
| } | |||||
| public String getRscPath() { | |||||
| return rscPath; | |||||
| } | |||||
| public void setRscPath(String rscPath) { | |||||
| this.rscPath = rscPath; | |||||
| } | |||||
| public String getRscI() { | |||||
| return rscI; | |||||
| } | |||||
| public void setRscI(String rscI) { | |||||
| this.rscI = rscI; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,87 @@ | |||||
| package com.iformall.domain.po; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaTemplateData; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 微信小程序消息 | |||||
| * @author luozukai | |||||
| * @date 2019/3/7 10:05 | |||||
| */ | |||||
| public class SmartAppMsg extends BaseMsg { | |||||
| private static final long serialVersionUID = 223232132183760321L; | |||||
| //小程序的appId | |||||
| private String appId; | |||||
| private String tenantId; | |||||
| private String to; | |||||
| private String from; | |||||
| private Integer templateType; | |||||
| private String gotopage; | |||||
| private String emphasisKeyword; | |||||
| private List<WxMaTemplateData> templateDataList; | |||||
| public String getAppId() { | |||||
| return appId; | |||||
| } | |||||
| public void setAppId(String appId) { | |||||
| this.appId = appId; | |||||
| } | |||||
| public String getEmphasisKeyword() { | |||||
| return emphasisKeyword; | |||||
| } | |||||
| public void setEmphasisKeyword(String emphasisKeyword) { | |||||
| this.emphasisKeyword = emphasisKeyword; | |||||
| } | |||||
| public String getGotopage() { | |||||
| return gotopage; | |||||
| } | |||||
| public void setGotopage(String gotopage) { | |||||
| this.gotopage = gotopage; | |||||
| } | |||||
| public String getTenantId() { | |||||
| return tenantId; | |||||
| } | |||||
| public void setTenantId(String tenantId) { | |||||
| this.tenantId = tenantId; | |||||
| } | |||||
| public String getTo() { | |||||
| return to; | |||||
| } | |||||
| public void setTo(String to) { | |||||
| this.to = to; | |||||
| } | |||||
| public String getFrom() { | |||||
| return from; | |||||
| } | |||||
| public void setFrom(String from) { | |||||
| this.from = from; | |||||
| } | |||||
| public Integer getTemplateType() { | |||||
| return templateType; | |||||
| } | |||||
| public void setTemplateType(Integer templateType) { | |||||
| this.templateType = templateType; | |||||
| } | |||||
| public List<WxMaTemplateData> getTemplateDataList() { | |||||
| return templateDataList; | |||||
| } | |||||
| public void setTemplateDataList(List<WxMaTemplateData> templateDataList) { | |||||
| this.templateDataList = templateDataList; | |||||
| } | |||||
| } | |||||
| @@ -8,7 +8,7 @@ import java.util.Date; | |||||
| import java.util.List; | import java.util.List; | ||||
| @Table(name = "wx_msg") | @Table(name = "wx_msg") | ||||
| public class WxMsg implements Serializable { | |||||
| public class WxMsg extends BaseMsg { | |||||
| private static final long serialVersionUID = 1L; | private static final long serialVersionUID = 1L; | ||||
| @Id | @Id | ||||
| @@ -39,7 +39,6 @@ public class WxMsg implements Serializable { | |||||
| this.ids = ids; | this.ids = ids; | ||||
| } | } | ||||
| /*租户ID**/ | /*租户ID**/ | ||||
| @io.swagger.annotations.ApiModelProperty(value = "租户ID", name = "tenantId") | @io.swagger.annotations.ApiModelProperty(value = "租户ID", name = "tenantId") | ||||
| private String tenantId; | private String tenantId; | ||||
| @@ -101,6 +100,27 @@ public class WxMsg implements Serializable { | |||||
| @Transient | @Transient | ||||
| List<WxTags> tagsList; | List<WxTags> tagsList; | ||||
| //用于mq发送消息 | |||||
| private WxMsgConfig wxMsgConfig; | |||||
| private WxCouponInject couponInject; | |||||
| public WxMsgConfig getWxMsgConfig() { | |||||
| return wxMsgConfig; | |||||
| } | |||||
| public void setWxMsgConfig(WxMsgConfig wxMsgConfig) { | |||||
| this.wxMsgConfig = wxMsgConfig; | |||||
| } | |||||
| public WxCouponInject getCouponInject() { | |||||
| return couponInject; | |||||
| } | |||||
| public void setCouponInject(WxCouponInject couponInject) { | |||||
| this.couponInject = couponInject; | |||||
| } | |||||
| public String getTenantId() { | public String getTenantId() { | ||||
| return tenantId; | return tenantId; | ||||
| } | } | ||||
| @@ -0,0 +1,199 @@ | |||||
| package com.iformall.domain.po; | |||||
| import javax.persistence.Id; | |||||
| import javax.persistence.Table; | |||||
| import java.util.Date; | |||||
| import java.util.Map; | |||||
| @Table(name = "wx_msg_record") | |||||
| public class WxMsgRecord extends BaseMsg { | |||||
| private static final long serialVersionUID = 18957895653478L; | |||||
| @Id | |||||
| protected Long id; | |||||
| //租户id | |||||
| private String tenantId; | |||||
| //域1sys 2a端 3c端 4b端 | |||||
| private Integer domain; | |||||
| //msg 消息类型1短信 2回调短信 邮件 3微信小程序模板 4微信公众号模板 5系统通 | |||||
| private String msg; | |||||
| //发送时间 | |||||
| private String sendTime; | |||||
| //model_id | |||||
| private Long modelId; | |||||
| //from,手机号邮件地址等 | |||||
| private String sender; | |||||
| //发送人id | |||||
| private Long senderUserId; | |||||
| //发送人姓名 | |||||
| private String senderUserName; | |||||
| //接收人,手机号邮件地址等 | |||||
| private String receiver; | |||||
| //接收人用户id | |||||
| private Long receiverUserId; | |||||
| //接收人姓名 | |||||
| private String receiverUserName; | |||||
| //签名 | |||||
| private String signature; | |||||
| //模板类型 | |||||
| private Integer modelType; | |||||
| //消息json | |||||
| private String msgJson; | |||||
| private Date createtime; | |||||
| private Date updatetime; | |||||
| //动态替换内容 | |||||
| private Map<String,String> dynamicContentMap; | |||||
| public String getMsgJson() { | |||||
| return msgJson; | |||||
| } | |||||
| public void setMsgJson(String msgJson) { | |||||
| this.msgJson = msgJson; | |||||
| } | |||||
| public Map<String, String> getDynamicContentMap() { | |||||
| return dynamicContentMap; | |||||
| } | |||||
| public void setDynamicContentMap(Map<String, String> dynamicContentMap) { | |||||
| this.dynamicContentMap = dynamicContentMap; | |||||
| } | |||||
| public Long getId() { | |||||
| return id; | |||||
| } | |||||
| public void setId(Long id) { | |||||
| this.id = id; | |||||
| } | |||||
| public Integer getDomain() { | |||||
| return domain; | |||||
| } | |||||
| public void setDomain(Integer domain) { | |||||
| this.domain = domain; | |||||
| } | |||||
| public String getSender() { | |||||
| return sender; | |||||
| } | |||||
| public void setSender(String sender) { | |||||
| this.sender = sender; | |||||
| } | |||||
| public Long getSenderUserId() { | |||||
| return senderUserId; | |||||
| } | |||||
| public void setSenderUserId(Long senderUserId) { | |||||
| this.senderUserId = senderUserId; | |||||
| } | |||||
| public String getSenderUserName() { | |||||
| return senderUserName; | |||||
| } | |||||
| public void setSenderUserName(String senderUserName) { | |||||
| this.senderUserName = senderUserName; | |||||
| } | |||||
| public String getReceiver() { | |||||
| return receiver; | |||||
| } | |||||
| public void setReceiver(String receiver) { | |||||
| this.receiver = receiver; | |||||
| } | |||||
| public Long getReceiverUserId() { | |||||
| return receiverUserId; | |||||
| } | |||||
| public void setReceiverUserId(Long receiverUserId) { | |||||
| this.receiverUserId = receiverUserId; | |||||
| } | |||||
| public String getReceiverUserName() { | |||||
| return receiverUserName; | |||||
| } | |||||
| public void setReceiverUserName(String receiverUserName) { | |||||
| this.receiverUserName = receiverUserName; | |||||
| } | |||||
| public Integer getModelType() { | |||||
| return modelType; | |||||
| } | |||||
| public void setModelType(Integer modelType) { | |||||
| this.modelType = modelType; | |||||
| } | |||||
| public String getSignature() { | |||||
| return signature; | |||||
| } | |||||
| public void setSignature(String signature) { | |||||
| this.signature = signature; | |||||
| } | |||||
| public String getTenantId() { | |||||
| return tenantId; | |||||
| } | |||||
| public void setTenantId(String tenantId) { | |||||
| this.tenantId = tenantId; | |||||
| } | |||||
| public String getMsg() { | |||||
| return msg; | |||||
| } | |||||
| public void setMsg(String msg) { | |||||
| this.msg = msg; | |||||
| } | |||||
| public String getSendTime() { | |||||
| return sendTime; | |||||
| } | |||||
| public void setSendTime(String sendTime) { | |||||
| this.sendTime = sendTime; | |||||
| } | |||||
| public Long getModelId() { | |||||
| return modelId; | |||||
| } | |||||
| public void setModelId(Long modelId) { | |||||
| this.modelId = modelId; | |||||
| } | |||||
| public Date getCreatetime() { | |||||
| return createtime; | |||||
| } | |||||
| public void setCreatetime(Date createtime) { | |||||
| this.createtime = createtime; | |||||
| } | |||||
| public Date getUpdatetime() { | |||||
| return updatetime; | |||||
| } | |||||
| public void setUpdatetime(Date updatetime) { | |||||
| this.updatetime = updatetime; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by luozukai | |||||
| */ | |||||
| public enum EnumMsgMqKey { | |||||
| DEFAULT("key-1", "默认"), | |||||
| ; | |||||
| public static EnumMsgMqKey getEnum(String code) { | |||||
| for (EnumMsgMqKey value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private String code; | |||||
| private String message; | |||||
| EnumMsgMqKey(String code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public String getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by luozukai | |||||
| */ | |||||
| public enum EnumMsgMqTag { | |||||
| DEFAULT("tag-1", "默认"), | |||||
| ; | |||||
| public static EnumMsgMqTag getEnum(String code) { | |||||
| for (EnumMsgMqTag value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private String code; | |||||
| private String message; | |||||
| EnumMsgMqTag(String code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public String getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,34 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by luozukai | |||||
| */ | |||||
| public enum EnumMsgMqTopic { | |||||
| DEFAULT("topic-1", "默认"), | |||||
| ; | |||||
| public static EnumMsgMqTopic getEnum(String code) { | |||||
| for (EnumMsgMqTopic value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private String code; | |||||
| private String message; | |||||
| EnumMsgMqTopic(String code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public String getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,38 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by luozukai | |||||
| */ | |||||
| public enum EnumMsgRecordStatus { | |||||
| DEFAULT(0, "默认"), | |||||
| SEND_SUCC(1, "发送成功"), | |||||
| CONSUME_SUCC(2, "消费成功"), | |||||
| CONSUME_FAIL(3, "消费失败"), | |||||
| ; | |||||
| public static EnumMsgRecordStatus getEnum(Integer code) { | |||||
| for (EnumMsgRecordStatus value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumMsgRecordStatus(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,39 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by luozukai | |||||
| */ | |||||
| public enum EnumMsgRecordType { | |||||
| SMS(1, "短信"), | |||||
| SMS_CALLBACK(2, "业务短信"), | |||||
| EMAIL(3, "邮件"), | |||||
| SMART_APP(4, "小程序"), | |||||
| PUBLIC(5, "公众号"), | |||||
| SYSTEM(6, "系统通知"), | |||||
| ; | |||||
| public static EnumMsgRecordType getEnum(Integer code) { | |||||
| for (EnumMsgRecordType value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumMsgRecordType(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| package com.iformall.mapper; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| import com.iformall.domain.po.WxMsgRecord; | |||||
| import java.util.List; | |||||
| public interface WxMsgRecordMapper extends CommonMapper<WxMsgRecord, String> { | |||||
| void update(BaseMsg record); | |||||
| List<WxMsgRecord> findList(WxMsgRecord record); | |||||
| void update(WxMsgRecord record); | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| package com.iformall.mq; | |||||
| public class MQConfig { | |||||
| public static class Impl { | |||||
| public static final String RABBIT_MQ = "rabbitMQ"; | |||||
| public static final String ROCKET_MQ = "rocketMQ"; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,8 @@ | |||||
| package com.iformall.mq; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| public interface MqBaseProducer { | |||||
| void sendMessage(BaseMsg record, String topic, String tags, String keys); | |||||
| } | |||||
| @@ -0,0 +1,52 @@ | |||||
| package com.iformall.mq.impl; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| import com.iformall.domain.po.WxMsg; | |||||
| import com.iformall.domain.po.WxMsgRecord; | |||||
| import com.iformall.enums.EnumMsgRecordStatus; | |||||
| import com.iformall.mapper.WxMsgRecordMapper; | |||||
| import com.iformall.mq.MQConfig; | |||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.service.WxMsgRecordService; | |||||
| import com.iformall.utils.JsonUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.amqp.core.AmqpTemplate; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.context.annotation.Profile; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.util.UUID; | |||||
| /** | |||||
| * @Auther: Stormeye | |||||
| * @Date: 2019-01-31 | |||||
| * @Description: RocketMQ消息生产者 | |||||
| */ | |||||
| @Service | |||||
| @Profile(MQConfig.Impl.RABBIT_MQ) | |||||
| public class RabbitMqMessageProducer implements MqBaseProducer { | |||||
| private final Logger log = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private AmqpTemplate rabbitTemplate; | |||||
| @Autowired | |||||
| private WxMsgRecordMapper wxMsgRecordMapper; | |||||
| @Autowired | |||||
| private WxMsgRecordService wxMsgRecordService; | |||||
| @Override | |||||
| public void sendMessage(BaseMsg data, String topic, String tags, String keys) { | |||||
| try { | |||||
| wxMsgRecordService.save(data); | |||||
| rabbitTemplate.convertAndSend(topic, JsonUtil.obj2Json(data)); | |||||
| data.setMsgStatus(EnumMsgRecordStatus.SEND_SUCC.getCode()); | |||||
| wxMsgRecordMapper.update(data); | |||||
| } catch (Exception e) { | |||||
| log.error("RabbitMqMessageProducer: Send Message Error ", e); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,90 @@ | |||||
| package com.iformall.mq.impl; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| import com.iformall.domain.po.WxMsg; | |||||
| import com.iformall.domain.po.WxMsgRecord; | |||||
| import com.iformall.enums.EnumMsgRecordStatus; | |||||
| import com.iformall.mapper.WxMsgRecordMapper; | |||||
| import com.iformall.mq.MQConfig; | |||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.service.WxMsgRecordService; | |||||
| import com.iformall.utils.JsonUtil; | |||||
| import lombok.extern.slf4j.Slf4j; | |||||
| import org.apache.rocketmq.client.producer.DefaultMQProducer; | |||||
| import org.apache.rocketmq.client.producer.SendCallback; | |||||
| import org.apache.rocketmq.client.producer.SendResult; | |||||
| import org.apache.rocketmq.common.message.Message; | |||||
| import org.apache.rocketmq.remoting.common.RemotingHelper; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.context.annotation.Profile; | |||||
| import org.springframework.stereotype.Service; | |||||
| import javax.annotation.PostConstruct; | |||||
| import java.util.UUID; | |||||
| /** | |||||
| * @Auther: Stormeye | |||||
| * @Date: 2019-01-31 | |||||
| * @Description: RocketMQ消息生产者 | |||||
| */ | |||||
| @Service | |||||
| @Profile(MQConfig.Impl.ROCKET_MQ) | |||||
| public class RocketMqMessageProducer implements MqBaseProducer { | |||||
| private final Logger log = LoggerFactory.getLogger(this.getClass()); | |||||
| @Value("${spring.rocketmq.nameServer}") | |||||
| private String namesrvAddr; | |||||
| private static final DefaultMQProducer producer = new DefaultMQProducer("DefaultProducer"); | |||||
| @Autowired | |||||
| private WxMsgRecordMapper wxMsgRecordMapper; | |||||
| @Autowired | |||||
| private WxMsgRecordService wxMsgRecordService; | |||||
| @PostConstruct | |||||
| public void start(){ | |||||
| try { | |||||
| producer.setNamesrvAddr(namesrvAddr); | |||||
| producer.start(); | |||||
| log.info("Message Producer Start..."); | |||||
| }catch (Exception e){ | |||||
| log.error("Message Producer Start Error!!",e); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void sendMessage(BaseMsg data, String topic, String tags, String keys) { | |||||
| try { | |||||
| wxMsgRecordService.save(data); | |||||
| byte[] messageBody = JsonUtil.obj2Json(data).getBytes(RemotingHelper.DEFAULT_CHARSET); | |||||
| Message mqMsg = new Message(topic, tags, keys, messageBody); | |||||
| if(data.getDelayTimeLevel() > 0){ | |||||
| mqMsg.setDelayTimeLevel(data.getDelayTimeLevel()); | |||||
| } | |||||
| producer.send(mqMsg, new SendCallback() { | |||||
| @Override | |||||
| public void onSuccess(SendResult sendResult) { | |||||
| log.info("Message Producer: Send Message Success {}", sendResult); | |||||
| data.setMsgStatus(EnumMsgRecordStatus.SEND_SUCC.getCode()); | |||||
| wxMsgRecordMapper.update(data); | |||||
| } | |||||
| @Override | |||||
| public void onException(Throwable throwable) { | |||||
| log.error("Message Producer: Send Message Error ", throwable); | |||||
| } | |||||
| }); | |||||
| } catch (Exception e) { | |||||
| log.error("Message Producer: Send Message Error ", e); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,10 @@ | |||||
| package com.iformall.service; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| /** | |||||
| * 发送消息 | |||||
| */ | |||||
| public interface MsgSendService { | |||||
| void send(BaseMsg baseMsg) throws Exception; | |||||
| } | |||||
| @@ -0,0 +1,13 @@ | |||||
| package com.iformall.service; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| import com.iformall.domain.po.WxMsgRecord; | |||||
| import java.util.List; | |||||
| public interface WxMsgRecordService { | |||||
| void save(BaseMsg baseMsg); | |||||
| List<WxMsgRecord> findList(WxMsgRecord record); | |||||
| void update(WxMsgRecord record); | |||||
| } | |||||
| @@ -43,4 +43,5 @@ public interface WxMsgService { | |||||
| void sendMsgFromCouponInject(WxMsg wxmsg, WxMsgConfig wxMsgConfig, WxCouponInject record); | void sendMsgFromCouponInject(WxMsg wxmsg, WxMsgConfig wxMsgConfig, WxCouponInject record); | ||||
| void addMsgCallback(WxMsg wxmsg, String batchNo); | |||||
| } | } | ||||
| @@ -7,21 +7,10 @@ import com.iformall.domain.po.WxMsgValidationcode; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| public interface WxMsgValidationcodeService { | public interface WxMsgValidationcodeService { | ||||
| /** | |||||
| * 发送审批流通知短信 | |||||
| * @param wxMsgValidationcode | |||||
| * @param dynamicContentMap 动态替换的内容 | |||||
| * @return | |||||
| */ | |||||
| ResultData sendWorkFlowNodify(WxMsgValidationcode wxMsgValidationcode, Map<String,String> dynamicContentMap); | |||||
| /** | /** | ||||
| * 根据实体查询分页列表 | * 根据实体查询分页列表 | ||||
| * | * | ||||
| * @param record | * @param record | ||||
| * @param offset | |||||
| * @param limit | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| PageInfo<WxMsgValidationcode> listAsPage(WxMsgValidationcode record, Integer pageIndex, Integer pageSize); | PageInfo<WxMsgValidationcode> listAsPage(WxMsgValidationcode record, Integer pageIndex, Integer pageSize); | ||||
| @@ -54,7 +43,7 @@ public interface WxMsgValidationcodeService { | |||||
| ResultData hasvalidationcode(WxMsgValidationcode record); | ResultData hasvalidationcode(WxMsgValidationcode record); | ||||
| void addMsgCallback(WxMsgValidationcode wxmsg, String batchNo); | |||||
| } | } | ||||
| @@ -0,0 +1,120 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.IdWorker; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.EnumMsgSendStatus; | |||||
| import com.iformall.enums.EnumVerifyCode; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.*; | |||||
| import com.iformall.service.MsgSendService; | |||||
| import com.iformall.service.WxMsgService; | |||||
| import com.iformall.service.WxMsgValidationcodeService; | |||||
| import com.iformall.utils.DateUtils; | |||||
| import com.iformall.utils.WiwideUtil; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.util.List; | |||||
| /** | |||||
| * @author luozukai | |||||
| * 业务短信发送实现 | |||||
| */ | |||||
| @Service | |||||
| public class SendCallBackSmsServiceImpl implements MsgSendService { | |||||
| @Autowired | |||||
| private WxMsgConfigMapper wxMsgConfigMapper; | |||||
| @Autowired | |||||
| private WxMsgValidationcodeModelMapper wxMsgValidationcodeModelMapper; | |||||
| @Autowired | |||||
| private WxMsgValidationcodeMapper wxMsgValidationcodeMapper; | |||||
| @Autowired | |||||
| private WxMsgValidationcodeService wxMsgValidationcodeService; | |||||
| @Autowired | |||||
| private WxMsgModelMapper wxMsgModelMapper; | |||||
| @Autowired | |||||
| private WxMsgMapper wxMsgMapper; | |||||
| @Autowired | |||||
| private WxMsgService wxMsgService; | |||||
| @Override | |||||
| public void send(BaseMsg baseMsg) { | |||||
| WxMsg record = (WxMsg)baseMsg; | |||||
| WxMsgConfig wxMsgConfig = record.getWxMsgConfig(); | |||||
| if(wxMsgConfig == null){ | |||||
| wxMsgConfig.setTenantId(record.getTenantId()); | |||||
| List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| if (wxMsgConfigs.size() == 0) { | |||||
| throw new MallinkException(ErrorCode.MSG_CONFIG_NOT_FOUND); | |||||
| } | |||||
| wxMsgConfig = wxMsgConfigs.get(0); | |||||
| if (wxMsgConfig.getRemains() == 0) { | |||||
| throw new MallinkException(ErrorCode.MSG_SUM_ZERO); | |||||
| } | |||||
| if (wxMsgConfig.getRemains() < record.getExpectSendNumber()) { | |||||
| throw new MallinkException(ErrorCode.MSG_SUM_INSUFFICENT); | |||||
| } | |||||
| } | |||||
| WxCouponInject couponInject = record.getCouponInject(); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| String phone = record.getPhones(); | |||||
| String signature = record.getSignature(); | |||||
| String msg = record.getMsg(); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| WxMsgModel wxMsgModel = wxMsgModelMapper.selectByPrimaryKey(record.getModelId()); | |||||
| Integer modelId = null; | |||||
| if (wxMsgModel != null) { | |||||
| modelId = wxMsgModel.getModelId(); | |||||
| } | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.NO.getCode().toString(), modelId); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| String batchNo = jsonObjectResult.get("data").toString(); | |||||
| //String resultMsg = jsonObjectResult.get("msg").toString(); | |||||
| record.setReturnResult(jsonObjectResult.toJSONString()); | |||||
| if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode().toString())) { | |||||
| record.setSendstatus(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode()); | |||||
| } else { | |||||
| record.setSendstatus(EnumMsgSendStatus.MSG_SEND_FAIL.getCode()); | |||||
| } | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| long id = idWorker.nextId(); | |||||
| WxMsg wxMsg = new WxMsg(); | |||||
| wxMsg.setTenantId(record.getTenantId()); | |||||
| wxMsg.setModelId(record.getModelId()); | |||||
| wxMsg.setMsg(record.getMsg()); | |||||
| wxMsg.setExpectSendNumber(record.getExpectSendNumber()); | |||||
| wxMsg.setPhones(record.getPhones()); | |||||
| wxMsg.setSignature(record.getSignature()); | |||||
| wxMsg.setIsright(record.getIsright()); | |||||
| wxMsg.setName(record.getName()); | |||||
| wxMsg.setSendstatus(record.getSendstatus()); | |||||
| wxMsg.setLabel(record.getLabel()); | |||||
| wxMsg.setStatus(record.getStatus()); | |||||
| wxMsg.setWay(record.getWay()); | |||||
| wxMsg.setId(id); | |||||
| String systemTime = DateUtils.getSystemTime("yyyy-MM-dd HH:mm:ss"); | |||||
| wxMsg.setSendtime(systemTime); | |||||
| wxMsg.setCreatetime(DateUtils.stringToDate(systemTime, "yyyy-MM-dd HH:mm:ss")); | |||||
| //精准投放 | |||||
| if (couponInject != null) { | |||||
| wxMsg.setCouponInjectId(couponInject.getId()); | |||||
| } | |||||
| wxMsgMapper.insertSelective(wxMsg); | |||||
| if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode().toString())) { | |||||
| wxMsgService.addMsgCallback(wxMsg, batchNo); | |||||
| } else { | |||||
| throw new MallinkException(1001,"运营商返回失败:"+result); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,82 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.iformall.domain.po.BaseMsg; | |||||
| import com.iformall.domain.po.MailMsg; | |||||
| import com.iformall.service.MsgSendService; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.core.io.FileSystemResource; | |||||
| import org.springframework.mail.SimpleMailMessage; | |||||
| import org.springframework.mail.javamail.JavaMailSender; | |||||
| import org.springframework.mail.javamail.MimeMessageHelper; | |||||
| import org.springframework.stereotype.Service; | |||||
| import javax.mail.internet.MimeMessage; | |||||
| import java.io.File; | |||||
| /** | |||||
| * 发送邮件 | |||||
| * @author luozukai | |||||
| * @date 2019/3/7 16:03 | |||||
| */ | |||||
| @Service | |||||
| public class SendEmailServiceImpl implements MsgSendService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private JavaMailSender sender; | |||||
| @Value("${spring.mail.username}") | |||||
| private String from; | |||||
| @Override | |||||
| public void send(BaseMsg baseMsg) throws Exception{ | |||||
| MailMsg mailMsg = (MailMsg)baseMsg; | |||||
| if(mailMsg.isHtml()){ | |||||
| MimeMessage message = sender.createMimeMessage(); | |||||
| MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||||
| helper.setFrom(from); | |||||
| helper.setTo(mailMsg.getTo()); | |||||
| helper.setSubject(mailMsg.getSubject()); | |||||
| helper.setText(mailMsg.getMsg(), true); | |||||
| sender.send(message); | |||||
| }else if(StringUtils.isNotBlank(mailMsg.getFilePath())){ | |||||
| MimeMessage message = sender.createMimeMessage(); | |||||
| String filePath = mailMsg.getFilePath(); | |||||
| MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||||
| helper.setFrom(from); | |||||
| helper.setTo(mailMsg.getTo()); | |||||
| helper.setSubject(mailMsg.getSubject()); | |||||
| helper.setText(mailMsg.getMsg(), true); | |||||
| FileSystemResource file = new FileSystemResource(new File(filePath)); | |||||
| String fileName = filePath.substring(filePath.lastIndexOf(File.separator)); | |||||
| helper.addAttachment(fileName, file); | |||||
| sender.send(message); | |||||
| }else if(StringUtils.isNotBlank(mailMsg.getRscI()) && StringUtils.isNotBlank(mailMsg.getRscPath())){ | |||||
| MimeMessage message = sender.createMimeMessage(); | |||||
| MimeMessageHelper helper = new MimeMessageHelper(message, true); | |||||
| helper.setFrom(from); | |||||
| helper.setTo(mailMsg.getTo()); | |||||
| helper.setSubject(mailMsg.getSubject()); | |||||
| helper.setText(mailMsg.getMsg(), true); | |||||
| FileSystemResource res = new FileSystemResource(new File(mailMsg.getRscPath())); | |||||
| helper.addInline(mailMsg.getRscI(), res); | |||||
| sender.send(message); | |||||
| }else{ | |||||
| SimpleMailMessage message = new SimpleMailMessage(); | |||||
| message.setFrom(from); | |||||
| message.setTo(mailMsg.getTo()); | |||||
| message.setSubject(mailMsg.getSubject()); | |||||
| message.setText(mailMsg.getMsg()); | |||||
| sender.send(message); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,69 @@ | |||||
| package com.iformall.service.impl; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.WxTemplateMsgMapper; | |||||
| import com.iformall.service.MsgSendService; | |||||
| import com.iformall.service.WxAppinfoService; | |||||
| import com.iformall.utils.MaUtil; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.util.List; | |||||
| /** | |||||
| * 发送微信小程序消息 | |||||
| * @author luozukai | |||||
| * @date 2019/3/7 16:03 | |||||
| */ | |||||
| @Service | |||||
| public class SendSmartAppMsgServiceImpl implements MsgSendService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxTemplateMsgMapper wxTemplateMsgMapper; | |||||
| @Autowired | |||||
| private WxAppinfoService wxAppinfoService; | |||||
| @Override | |||||
| public void send(BaseMsg baseMsg) throws Exception{ | |||||
| SmartAppMsg smartAppMsg = (SmartAppMsg)baseMsg; | |||||
| WxTemplateMsg msg = null; | |||||
| WxMaTemplateMessage templateMessage; | |||||
| WxAppinfo appInfo = wxAppinfoService.getByAppId(smartAppMsg.getAppId()); | |||||
| WxMaService wxMaService = MaUtil.getWeappService(appInfo); | |||||
| //查询信息模板 | |||||
| WxTemplateMsg msgQ = new WxTemplateMsg(); | |||||
| msgQ.setTenantId(smartAppMsg.getTenantId()); | |||||
| msgQ.setType(smartAppMsg.getTemplateType()); | |||||
| List<WxTemplateMsg> list = wxTemplateMsgMapper.select(msgQ); | |||||
| if (list.size() > 0) { | |||||
| msg = list.get(0); | |||||
| } | |||||
| if (msg == null) { | |||||
| logger.error("找不到模板Id"); | |||||
| throw new MallinkException(ErrorCode.TEMPLATE_NOT_FOUND); | |||||
| } | |||||
| /** | |||||
| * 核销失败 | |||||
| * 商品名称 {{keyword1.DATA}} | |||||
| * 核销时间 {{keyword2.DATA}} | |||||
| * 失败原因 {{keyword3.DATA}} | |||||
| * 备注 {{keyword4.DATA}} | |||||
| */ | |||||
| templateMessage = WxMaTemplateMessage.builder() | |||||
| .toUser(smartAppMsg.getTo()) | |||||
| .formId(smartAppMsg.getFrom()) // 微信支付的formId是prepayId | |||||
| .page(smartAppMsg.getGotopage()) | |||||
| .data(smartAppMsg.getTemplateDataList()) | |||||
| .templateId(msg.getTemplateId()) | |||||
| .emphasisKeyword(smartAppMsg.getEmphasisKeyword()) | |||||
| .build(); | |||||
| wxMaService.getMsgService().sendTemplateMsg(templateMessage); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,107 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.IdWorker; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.EnumVerifyCode; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.WxMsgConfigMapper; | |||||
| import com.iformall.mapper.WxMsgValidationcodeMapper; | |||||
| import com.iformall.mapper.WxMsgValidationcodeModelMapper; | |||||
| import com.iformall.service.MsgSendService; | |||||
| import com.iformall.service.WxMsgValidationcodeService; | |||||
| import com.iformall.utils.WiwideUtil; | |||||
| import org.apache.commons.collections.CollectionUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * @author luozukai | |||||
| * 短信发送实现 | |||||
| */ | |||||
| @Service | |||||
| public class SendSmsServiceImpl implements MsgSendService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| private WxMsgConfigMapper wxMsgConfigMapper; | |||||
| @Autowired | |||||
| private WxMsgValidationcodeModelMapper wxMsgValidationcodeModelMapper; | |||||
| @Autowired | |||||
| private WxMsgValidationcodeMapper wxMsgValidationcodeMapper; | |||||
| @Autowired | |||||
| private WxMsgValidationcodeService wxMsgValidationcodeService; | |||||
| @Override | |||||
| public void send(BaseMsg baseMsg) { | |||||
| WxMsgRecord record = (WxMsgRecord)baseMsg; | |||||
| WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); | |||||
| wxMsgValidationcode.setPhone(record.getReceiver()); | |||||
| wxMsgValidationcode.setTenantId(record.getTenantId()); | |||||
| wxMsgValidationcode.setType(record.getModelType()); | |||||
| //3、从短信配置中查询密钥 bid 等信息 | |||||
| WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| wxMsgConfig.setTenantId(record.getTenantId()); | |||||
| List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| if(CollectionUtils.isEmpty(wxMsgConfigs)){ | |||||
| throw new MallinkException(ErrorCode.MSG_CONFIG_NOT_FOUND); | |||||
| } | |||||
| wxMsgConfig = wxMsgConfigs.get(0); | |||||
| WxMsgValidationcodeModel wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); | |||||
| wxMsgValidationcodeModel.setTenantId(record.getTenantId()); | |||||
| wxMsgValidationcodeModel.setType(record.getModelType()); | |||||
| List<WxMsgValidationcodeModel> modelList = wxMsgValidationcodeModelMapper.findList(wxMsgValidationcodeModel); | |||||
| if(CollectionUtils.isEmpty(modelList)){ | |||||
| throw new MallinkException(ErrorCode.MSG_MODEL_NOT_FOUND); | |||||
| } | |||||
| wxMsgValidationcodeModel = wxMsgValidationcodeModelMapper.findList(wxMsgValidationcodeModel).get(0); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| String phone = record.getReceiver(); | |||||
| String signature = wxMsgValidationcodeModel.getSignature(); | |||||
| wxMsgValidationcode.setSignature(signature); | |||||
| //替换内容 | |||||
| String msg = wxMsgValidationcodeModel.getContent(); | |||||
| for (Map.Entry<String, String> entry : record.getDynamicContentMap().entrySet()) { | |||||
| msg = msg.replace("{"+entry.getKey()+"}", entry.getValue()); | |||||
| } | |||||
| wxMsgValidationcode.setMsg(msg); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| Integer modelId = wxMsgValidationcodeModel.getModelId(); | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.YES.getCode().toString(), modelId); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| String batchNo = jsonObjectResult.get("data").toString(); | |||||
| if (ret.equals("1")) { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| wxMsgValidationcode.setId(idWorker.nextId()); | |||||
| long currentTime = System.currentTimeMillis() ; | |||||
| Date createtime=new Date(currentTime); | |||||
| wxMsgValidationcode.setCreatetime(createtime); | |||||
| Integer minutes = wxMsgValidationcodeModel.getMinutes(); | |||||
| if(minutes >0) { | |||||
| currentTime += minutes * 60 * 1000; | |||||
| Date expiredate = new Date(currentTime); | |||||
| wxMsgValidationcode.setExpiretime(expiredate); | |||||
| } | |||||
| wxMsgValidationcodeMapper.insertSelective(wxMsgValidationcode); | |||||
| wxMsgValidationcodeService.addMsgCallback(wxMsgValidationcode,batchNo); | |||||
| }else{ | |||||
| throw new MallinkException(1001,"运营商返回失败:"+result); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -19,6 +19,7 @@ import com.iformall.domain.vo.*; | |||||
| import com.iformall.enums.*; | import com.iformall.enums.*; | ||||
| import com.iformall.exception.MallinkException; | import com.iformall.exception.MallinkException; | ||||
| import com.iformall.mapper.*; | import com.iformall.mapper.*; | ||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.service.*; | import com.iformall.service.*; | ||||
| import com.iformall.utils.Constant; | import com.iformall.utils.Constant; | ||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| @@ -100,6 +101,9 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| @Autowired | @Autowired | ||||
| WxCouponChannelMapper wxCouponChannelMapper; | WxCouponChannelMapper wxCouponChannelMapper; | ||||
| @Autowired | |||||
| MqBaseProducer mqBaseProducer; | |||||
| @Override | @Override | ||||
| public PageInfo<WxCouponOrder> listAsPage(WxCouponOrder record, Integer pageIndex, Integer pageSize) { | public PageInfo<WxCouponOrder> listAsPage(WxCouponOrder record, Integer pageIndex, Integer pageSize) { | ||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponOrderMapper.findList(record)); | return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponOrderMapper.findList(record)); | ||||
| @@ -193,13 +197,13 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public PageInfo<WxCouponOrderCVo> listCUserVoAsPage(WxCouponOrder record, Integer pageIndex, Integer pageSize) { | |||||
| public ResultData listCUserVoAsPage(WxCouponOrder record, Integer pageIndex, Integer pageSize) { | |||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponOrderMapper.findListOfCUser(record)); | |||||
| return new ResultData(PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxCouponOrderMapper.findListOfCUser(record))); | |||||
| } | } | ||||
| @Override | @Override | ||||
| public WxCouponOrderCVo detailCUserVo(Long cUserId, String couponOrderId) { | |||||
| public ResultData detailCUserVo(Long cUserId, String couponOrderId) { | |||||
| WxCUser wxCuser = wxCUserMapper.selectByPrimaryKey(cUserId); | WxCUser wxCuser = wxCUserMapper.selectByPrimaryKey(cUserId); | ||||
| if (wxCuser == null) { | if (wxCuser == null) { | ||||
| logger.error("用户不存在:" + cUserId); | logger.error("用户不存在:" + cUserId); | ||||
| @@ -208,8 +212,8 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| WxCouponOrderCVo wxCouponOrderCVo = wxCouponOrderMapper.findDetailOfCUser(Long.valueOf(couponOrderId)); | WxCouponOrderCVo wxCouponOrderCVo = wxCouponOrderMapper.findDetailOfCUser(Long.valueOf(couponOrderId)); | ||||
| if (wxCouponOrderCVo == null) | if (wxCouponOrderCVo == null) | ||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL); | |||||
| return wxCouponOrderCVo; | |||||
| return new ResultData(ErrorCode.COUPON_ORDER_IS_NULL); | |||||
| return new ResultData(wxCouponOrderCVo); | |||||
| } | } | ||||
| @@ -403,7 +407,7 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| wxSharingOrderDto.setTenantId(wxPayOrder.getTenantId()); | wxSharingOrderDto.setTenantId(wxPayOrder.getTenantId()); | ||||
| wxSharingOrderDto.setTransactionId(wxPayOrder.getTransactionId()); | wxSharingOrderDto.setTransactionId(wxPayOrder.getTransactionId()); | ||||
| wxSharingOrderDto.setShareAmount(wxPayOrder.getShareAmount()); | wxSharingOrderDto.setShareAmount(wxPayOrder.getShareAmount()); | ||||
| wxProfitSharingOrderService.finishSharingOrder(wxSharingOrderDto); | |||||
| wxProfitSharingOrderService.createSharingOrder(wxSharingOrderDto); | |||||
| } | } | ||||
| } catch (Exception e) { | } catch (Exception e) { | ||||
| logger.error("微信分账: " + e.getMessage()); | logger.error("微信分账: " + e.getMessage()); | ||||
| @@ -547,7 +551,7 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| } | } | ||||
| // 5. get app info | // 5. get app info | ||||
| WxAppinfo appInfo = wxAppinfoService.getByAppId(user.getAppId()); | |||||
| // WxAppinfo appInfo = wxAppinfoService.getByAppId(user.getAppId()); | |||||
| // 6. get payOrder info | // 6. get payOrder info | ||||
| WxPayOrder payOrder = null; | WxPayOrder payOrder = null; | ||||
| @@ -568,7 +572,7 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| throw new MallinkException(ErrorCode.PREPAY_ID_IS_EMPTY); | throw new MallinkException(ErrorCode.PREPAY_ID_IS_EMPTY); | ||||
| } | } | ||||
| WxMaService wxMaService = MaUtil.getWeappService(appInfo); | |||||
| // WxMaService wxMaService = MaUtil.getWeappService(appInfo); | |||||
| SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); | ||||
| String couponDetail = ""; | String couponDetail = ""; | ||||
| @@ -576,91 +580,51 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| couponDetail = "满" + coupon.getUsePriceStr() + "减" + coupon.getPriceStr(); | couponDetail = "满" + coupon.getUsePriceStr() + "减" + coupon.getPriceStr(); | ||||
| } | } | ||||
| WxTemplateMsg msg = null; | |||||
| WxMaTemplateMessage templateMessage = null; | |||||
| SmartAppMsg smartAppMsg; | |||||
| if (couponOrder.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) { | if (couponOrder.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) { | ||||
| WxTemplateMsg msgQ = new WxTemplateMsg(); | |||||
| msgQ.setTenantId(couponOrder.getTenantId()); | |||||
| msgQ.setType(EnumTemplateType.VERIFY_SUCCESS.getCode()); | |||||
| List<WxTemplateMsg> list = wxTemplateMsgMapper.select(msgQ); | |||||
| if (list.size() > 0) { | |||||
| msg = list.get(0); | |||||
| } | |||||
| if (msg == null) { | |||||
| logger.error("找不到模板Id"); | |||||
| throw new MallinkException(ErrorCode.TEMPLATE_NOT_FOUND); | |||||
| } | |||||
| String gotopage = "pages/index/index"; | String gotopage = "pages/index/index"; | ||||
| String notes = ""; | String notes = ""; | ||||
| if (hadSentCoupon) { | if (hadSentCoupon) { | ||||
| gotopage = "pages/couponorder/index/index"; | gotopage = "pages/couponorder/index/index"; | ||||
| notes = "您有新的券"; | notes = "您有新的券"; | ||||
| } | } | ||||
| /** | |||||
| * 核销成功 | |||||
| * 核销金额 {{keyword1.DATA}} | |||||
| * 商家名称 {{keyword2.DATA}} | |||||
| * 商品 {{keyword3.DATA}} | |||||
| * 商品描述 {{keyword4.DATA}} | |||||
| * 订单金额 {{keyword5.DATA}} | |||||
| * 核销时间 {{keyword6.DATA}} | |||||
| * 温馨提示 {{keyword7.DATA}} | |||||
| * | |||||
| */ | |||||
| templateMessage = WxMaTemplateMessage.builder() | |||||
| .toUser(user.getOpenId()) | |||||
| .formId(payOrder.getPrepayId()) // 微信支付的formId是prepayId | |||||
| .page(gotopage) | |||||
| .data(Lists.newArrayList( | |||||
| new WxMaTemplateData("keyword1", coupon.getPriceStr() + "元", "#173177"), | |||||
| new WxMaTemplateData("keyword2", merchant.getName(), "#173177"), | |||||
| new WxMaTemplateData("keyword3", coupon.getTitle(), "#173177"), | |||||
| new WxMaTemplateData("keyword4", couponDetail, "#173177"), | |||||
| new WxMaTemplateData("keyword5", coupon.getSalePriceStr() + "元", "#173177"), | |||||
| new WxMaTemplateData("keyword6", dateFormat.format(new Date()), "#173177"), | |||||
| new WxMaTemplateData("keyword7", notes, "#173177")) | |||||
| ) | |||||
| .templateId(msg.getTemplateId()) | |||||
| .emphasisKeyword("keyword1.DATA") | |||||
| .build(); | |||||
| //mq发送小程序消息 | |||||
| smartAppMsg = new SmartAppMsg(); | |||||
| smartAppMsg.setAppId(user.getAppId()); | |||||
| smartAppMsg.setTenantId(couponOrder.getTenantId()); | |||||
| smartAppMsg.setTemplateType(EnumTemplateType.VERIFY_SUCCESS.getCode()); | |||||
| smartAppMsg.setGotopage(gotopage); | |||||
| smartAppMsg.setTo(user.getOpenId()); | |||||
| smartAppMsg.setFrom(payOrder.getPrepayId()); | |||||
| smartAppMsg.setTemplateDataList(Lists.newArrayList( | |||||
| new WxMaTemplateData("keyword1", coupon.getPriceStr() + "元", "#173177"), | |||||
| new WxMaTemplateData("keyword2", merchant.getName(), "#173177"), | |||||
| new WxMaTemplateData("keyword3", coupon.getTitle(), "#173177"), | |||||
| new WxMaTemplateData("keyword4", couponDetail, "#173177"), | |||||
| new WxMaTemplateData("keyword5", coupon.getSalePriceStr() + "元", "#173177"), | |||||
| new WxMaTemplateData("keyword6", dateFormat.format(new Date()), "#173177"), | |||||
| new WxMaTemplateData("keyword7", notes, "#173177"))); | |||||
| smartAppMsg.setEmphasisKeyword("keyword1.DATA"); | |||||
| } else { | } else { | ||||
| WxTemplateMsg msgQ = new WxTemplateMsg(); | |||||
| msgQ.setTenantId(couponOrder.getTenantId()); | |||||
| msgQ.setType(EnumTemplateType.VERIFY_FAIL.getCode()); | |||||
| List<WxTemplateMsg> list = wxTemplateMsgMapper.select(msgQ); | |||||
| if (list.size() > 0) { | |||||
| msg = list.get(0); | |||||
| } | |||||
| if (msg == null) { | |||||
| logger.error("找不到模板Id"); | |||||
| throw new MallinkException(ErrorCode.TEMPLATE_NOT_FOUND); | |||||
| } | |||||
| /** | |||||
| * 核销失败 | |||||
| * 商品名称 {{keyword1.DATA}} | |||||
| * 核销时间 {{keyword2.DATA}} | |||||
| * 失败原因 {{keyword3.DATA}} | |||||
| * 备注 {{keyword4.DATA}} | |||||
| */ | |||||
| templateMessage = WxMaTemplateMessage.builder() | |||||
| .toUser(user.getOpenId()) | |||||
| .formId(payOrder.getPrepayId()) // 微信支付的formId是prepayId | |||||
| .page("pages/index/index") | |||||
| .data(Lists.newArrayList( | |||||
| new WxMaTemplateData("keyword1", coupon.getTitle(), "#173177"), | |||||
| new WxMaTemplateData("keyword2", dateFormat.format(new Date()), "#173177"), | |||||
| new WxMaTemplateData("keyword3", "未知"), | |||||
| new WxMaTemplateData("keyword4", couponDetail)) | |||||
| ) | |||||
| .templateId(msg.getTemplateId()) | |||||
| .emphasisKeyword("keyword1.DATA") | |||||
| .build(); | |||||
| } | |||||
| //templateMessage.addData( new WxMaTemplateMessage.Data("keyword1", "339208499", "#173177")); | |||||
| //mq发送小程序消息 | |||||
| smartAppMsg = new SmartAppMsg(); | |||||
| smartAppMsg.setAppId(user.getAppId()); | |||||
| smartAppMsg.setTenantId(couponOrder.getTenantId()); | |||||
| smartAppMsg.setTemplateType(EnumTemplateType.VERIFY_FAIL.getCode()); | |||||
| smartAppMsg.setGotopage("pages/index/index"); | |||||
| smartAppMsg.setTo(user.getOpenId()); | |||||
| smartAppMsg.setFrom(payOrder.getPrepayId()); | |||||
| smartAppMsg.setTemplateDataList(Lists.newArrayList( | |||||
| new WxMaTemplateData("keyword1", coupon.getTitle(), "#173177"), | |||||
| new WxMaTemplateData("keyword2", dateFormat.format(new Date()), "#173177"), | |||||
| new WxMaTemplateData("keyword3", "未知"), | |||||
| new WxMaTemplateData("keyword4", couponDetail))); | |||||
| smartAppMsg.setEmphasisKeyword("keyword1.DATA"); | |||||
| } | |||||
| try { | try { | ||||
| wxMaService.getMsgService().sendTemplateMsg(templateMessage); | |||||
| } catch (WxErrorException e) { | |||||
| mqBaseProducer.sendMessage(smartAppMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } catch (Exception e) { | |||||
| logger.error("支付通知发送失败: " + e.getMessage()); | logger.error("支付通知发送失败: " + e.getMessage()); | ||||
| throw new MallinkException(ErrorCode.TEMPLATE_SEND_FAILED); | throw new MallinkException(ErrorCode.TEMPLATE_SEND_FAILED); | ||||
| } | } | ||||
| @@ -7,17 +7,16 @@ import com.iformall.common.ErrorCode; | |||||
| import com.iformall.common.IdWorker; | import com.iformall.common.IdWorker; | ||||
| import com.iformall.common.Result; | import com.iformall.common.Result; | ||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.domain.po.WxMallApply; | |||||
| import com.iformall.domain.po.WxMsgConfig; | |||||
| import com.iformall.domain.po.WxMsgValidationcode; | |||||
| import com.iformall.domain.po.WxMsgValidationcodeModel; | |||||
| import com.iformall.enums.EnumVerifyCode; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.mapper.WxMallApplyMapper; | import com.iformall.mapper.WxMallApplyMapper; | ||||
| import com.iformall.mapper.WxMsgConfigMapper; | import com.iformall.mapper.WxMsgConfigMapper; | ||||
| import com.iformall.mapper.WxMsgValidationcodeMapper; | import com.iformall.mapper.WxMsgValidationcodeMapper; | ||||
| import com.iformall.mapper.WxMsgValidationcodeModelMapper; | import com.iformall.mapper.WxMsgValidationcodeModelMapper; | ||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.service.WxMallApplyService; | import com.iformall.service.WxMallApplyService; | ||||
| import com.iformall.utils.*; | import com.iformall.utils.*; | ||||
| import org.apache.commons.collections.map.HashedMap; | |||||
| import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
| @@ -42,6 +41,8 @@ public class WxMallApplyServiceImpl implements WxMallApplyService { | |||||
| @Autowired | @Autowired | ||||
| WxMsgValidationcodeModelMapper wxMsgValidationcodeModelMapper; | WxMsgValidationcodeModelMapper wxMsgValidationcodeModelMapper; | ||||
| @Autowired | |||||
| private MqBaseProducer mqBaseProducer; | |||||
| @Override | @Override | ||||
| public PageInfo<WxMallApply> listAsPage(WxMallApply record, Integer pageIndex, Integer pageSize) { | public PageInfo<WxMallApply> listAsPage(WxMallApply record, Integer pageIndex, Integer pageSize) { | ||||
| @@ -83,7 +84,7 @@ public class WxMallApplyServiceImpl implements WxMallApplyService { | |||||
| } | } | ||||
| @Override | @Override | ||||
| public ResultData sendvalidationcode(WxMsgValidationcode wxMsgValidationcode) { | |||||
| public ResultData sendvalidationcode(WxMsgValidationcode wxMsgValidationcode){ | |||||
| //1、查看是否存在未过期的短信,有返回成功 没有继续 | //1、查看是否存在未过期的短信,有返回成功 没有继续 | ||||
| List<WxMsgValidationcode> wxmsgvalidationcodelist = wxMsgValidationcodeMapper.findList(wxMsgValidationcode); | List<WxMsgValidationcode> wxmsgvalidationcodelist = wxMsgValidationcodeMapper.findList(wxMsgValidationcode); | ||||
| Date currentdate = new Date(); | Date currentdate = new Date(); | ||||
| @@ -91,54 +92,65 @@ public class WxMallApplyServiceImpl implements WxMallApplyService { | |||||
| validationcode.getExpiretime().after(currentdate)).collect(Collectors.toList()); | validationcode.getExpiretime().after(currentdate)).collect(Collectors.toList()); | ||||
| if(wxmsgvalidationcodelist.size()>0) return new ResultData(ErrorCode.MSG_REPEAT_SEND.getCode(),ErrorCode.MSG_REPEAT_SEND.getMessage()); | if(wxmsgvalidationcodelist.size()>0) return new ResultData(ErrorCode.MSG_REPEAT_SEND.getCode(),ErrorCode.MSG_REPEAT_SEND.getMessage()); | ||||
| //3、从短信配置中查询密钥 bid 等信息 | //3、从短信配置中查询密钥 bid 等信息 | ||||
| WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| wxMsgConfig.setTenantId(wxMsgValidationcode.getTenantId()); | |||||
| List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| if (wxMsgConfigs.size() == 0) new ResultData(500,"发送失败"); | |||||
| wxMsgConfig = wxMsgConfigs.get(0); | |||||
| WxMsgValidationcodeModel wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); | |||||
| wxMsgValidationcodeModel.setTenantId(wxMsgConfig.getTenantId()); | |||||
| wxMsgValidationcodeModel.setType(wxMsgValidationcode.getType()); | |||||
| wxMsgValidationcodeModel.setName("验证码"); | |||||
| wxMsgValidationcodeModel = wxMsgValidationcodeModelMapper.findList(wxMsgValidationcodeModel).get(0); | |||||
| wxMsgValidationcode.setSignature(wxMsgValidationcodeModel.getSignature()); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| // WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| // wxMsgConfig.setTenantId(wxMsgValidationcode.getTenantId()); | |||||
| // List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| // if (wxMsgConfigs.size() == 0) new ResultData(500,"发送失败"); | |||||
| // wxMsgConfig = wxMsgConfigs.get(0); | |||||
| // | |||||
| // WxMsgValidationcodeModel wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); | |||||
| // wxMsgValidationcodeModel.setTenantId(wxMsgConfig.getTenantId()); | |||||
| // wxMsgValidationcodeModel.setType(wxMsgValidationcode.getType()); | |||||
| // wxMsgValidationcodeModel.setName("验证码"); | |||||
| // wxMsgValidationcodeModel = wxMsgValidationcodeModelMapper.findList(wxMsgValidationcodeModel).get(0); | |||||
| // wxMsgValidationcode.setSignature(wxMsgValidationcodeModel.getSignature()); | |||||
| // | |||||
| // String secret = wxMsgConfig.getSecret(); | |||||
| // String bid = wxMsgConfig.getBid(); | |||||
| // String publickey = wxMsgConfig.getPublickey(); | |||||
| // //验证码 | |||||
| // int code = (int) ((Math.random() * 9 + 1) * 100000); | |||||
| // String phone = wxMsgValidationcode.getPhone(); | |||||
| // String signature = wxMsgValidationcode.getSignature(); | |||||
| // //内容 | |||||
| // String msg = wxMsgValidationcodeModel.getContent().replace("{s6}", String.valueOf(code)); | |||||
| // wxMsgValidationcode.setCode(String.valueOf(code)); | |||||
| // wxMsgValidationcode.setMsg(msg); | |||||
| // | |||||
| // String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| // Integer modelId = wxMsgValidationcodeModel.getModelId(); | |||||
| // String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.YES.getCode().toString(), modelId); | |||||
| // JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| // String ret = jsonObjectResult.get("ret").toString(); | |||||
| // | |||||
| // if (ret.equals("1")) { | |||||
| // final IdWorker idWorker = IdWorker.get(); | |||||
| // wxMsgValidationcode.setId(idWorker.nextId()); | |||||
| // long currentTime = System.currentTimeMillis() ; | |||||
| // Date createtime=new Date(currentTime); | |||||
| // Integer minutes = wxMsgValidationcodeModel.getMinutes(); | |||||
| // currentTime +=minutes*60*1000; | |||||
| // Date expiredate=new Date(currentTime); | |||||
| // wxMsgValidationcode.setExpiretime(expiredate); | |||||
| // wxMsgValidationcode.setCreatetime(createtime); | |||||
| // wxMsgValidationcodeMapper.insertSelective(wxMsgValidationcode); | |||||
| // return new ResultData(Result.SUCCESS,"发送成功"); | |||||
| // } | |||||
| //验证码 | //验证码 | ||||
| int code = (int) ((Math.random() * 9 + 1) * 100000); | int code = (int) ((Math.random() * 9 + 1) * 100000); | ||||
| String phone = wxMsgValidationcode.getPhone(); | |||||
| String signature = wxMsgValidationcode.getSignature(); | |||||
| //内容 | |||||
| String msg = wxMsgValidationcodeModel.getContent().replace("{s6}", String.valueOf(code)); | |||||
| wxMsgValidationcode.setCode(String.valueOf(code)); | |||||
| wxMsgValidationcode.setMsg(msg); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| Integer modelId = wxMsgValidationcodeModel.getModelId(); | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.YES.getCode().toString(), modelId); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| if (ret.equals("1")) { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| wxMsgValidationcode.setId(idWorker.nextId()); | |||||
| long currentTime = System.currentTimeMillis() ; | |||||
| Date createtime=new Date(currentTime); | |||||
| Integer minutes = wxMsgValidationcodeModel.getMinutes(); | |||||
| currentTime +=minutes*60*1000; | |||||
| Date expiredate=new Date(currentTime); | |||||
| wxMsgValidationcode.setExpiretime(expiredate); | |||||
| wxMsgValidationcode.setCreatetime(createtime); | |||||
| wxMsgValidationcodeMapper.insertSelective(wxMsgValidationcode); | |||||
| return new ResultData(Result.SUCCESS,"发送成功"); | |||||
| } | |||||
| return new ResultData(500,"发送失败"); | |||||
| WxMsgRecord wxMsgRecord = new WxMsgRecord(); | |||||
| wxMsgRecord.setMsgType(EnumMsgRecordType.SMS.getCode()); | |||||
| wxMsgRecord.setModelType(wxMsgValidationcode.getType()); | |||||
| wxMsgRecord.setReceiver(wxMsgValidationcode.getPhone()); | |||||
| wxMsgRecord.setTenantId(wxMsgValidationcode.getTenantId()); | |||||
| Map<String,String> map = new HashedMap(); | |||||
| map.put("s6",String.valueOf(code)); | |||||
| wxMsgRecord.setDynamicContentMap(map); | |||||
| mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); | |||||
| return new ResultData(Result.SUCCESS,"发送成功"); | |||||
| } | } | ||||
| @@ -0,0 +1,44 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.mapper.*; | |||||
| import com.iformall.service.WxMsgRecordService; | |||||
| import com.iformall.utils.JsonUtil; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import java.util.List; | |||||
| import java.util.UUID; | |||||
| /** | |||||
| * @author luozukai | |||||
| * 业务短信发送实现 | |||||
| */ | |||||
| @Service | |||||
| public class WxMsgRecordServiceImpl implements WxMsgRecordService { | |||||
| @Autowired | |||||
| private WxMsgRecordMapper wxMsgRecordMapper; | |||||
| @Override | |||||
| public void save(BaseMsg data) { | |||||
| data.setUuid(UUID.randomUUID().toString()); | |||||
| if(data instanceof WxMsgRecord){ | |||||
| WxMsgRecord msgRecord = (WxMsgRecord)data; | |||||
| msgRecord.setMsgJson(JsonUtil.obj2Json(data)); | |||||
| wxMsgRecordMapper.insertSelective(msgRecord); | |||||
| }else if(data instanceof WxMsg || data instanceof MailMsg){ | |||||
| WxMsgRecord msgRecord = new WxMsgRecord(); | |||||
| msgRecord.setMsgJson(JsonUtil.obj2Json(data)); | |||||
| wxMsgRecordMapper.insertSelective(msgRecord); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public List<WxMsgRecord> findList(WxMsgRecord record) { | |||||
| return wxMsgRecordMapper.findList(record); | |||||
| } | |||||
| @Override | |||||
| public void update(WxMsgRecord record) { | |||||
| wxMsgRecordMapper.update(record); | |||||
| } | |||||
| } | |||||
| @@ -8,11 +8,9 @@ import com.iformall.common.IdWorker; | |||||
| import com.iformall.common.Result; | import com.iformall.common.Result; | ||||
| import com.iformall.common.ResultData; | import com.iformall.common.ResultData; | ||||
| import com.iformall.domain.po.*; | import com.iformall.domain.po.*; | ||||
| import com.iformall.enums.EnumMsgSend; | |||||
| import com.iformall.enums.EnumMsgSendStatus; | |||||
| import com.iformall.enums.EnumMsgStatus; | |||||
| import com.iformall.enums.EnumVerifyCode; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.mapper.*; | import com.iformall.mapper.*; | ||||
| import com.iformall.mq.MqBaseProducer; | |||||
| import com.iformall.service.WxCUserTagsService; | import com.iformall.service.WxCUserTagsService; | ||||
| import com.iformall.service.WxMsgService; | import com.iformall.service.WxMsgService; | ||||
| import com.iformall.utils.DateUtils; | import com.iformall.utils.DateUtils; | ||||
| @@ -52,6 +50,9 @@ public class WxMsgServiceImpl implements WxMsgService { | |||||
| @Autowired | @Autowired | ||||
| WxMsgModelMapper wxMsgModelMapper; | WxMsgModelMapper wxMsgModelMapper; | ||||
| @Autowired | |||||
| MqBaseProducer mqBaseProducer; | |||||
| @Override | @Override | ||||
| public PageInfo<WxMsg> listAsPage(WxMsg record, Integer pageIndex, Integer pageSize) { | public PageInfo<WxMsg> listAsPage(WxMsg record, Integer pageIndex, Integer pageSize) { | ||||
| PageHelper.startPage(pageIndex, pageSize); | PageHelper.startPage(pageIndex, pageSize); | ||||
| @@ -110,7 +111,10 @@ public class WxMsgServiceImpl implements WxMsgService { | |||||
| if (wxMsg.getExpectSendNumber().intValue() > 1000) { | if (wxMsg.getExpectSendNumber().intValue() > 1000) { | ||||
| batchSendMsg(wxMsg, wxMsgConfig, null); | batchSendMsg(wxMsg, wxMsgConfig, null); | ||||
| } else { | } else { | ||||
| sendmsg(wxMsg, wxMsgConfig, null); | |||||
| //sendmsg(wxMsg, wxMsgConfig, null); | |||||
| wxMsg.setWxMsgConfig(wxMsgConfig); | |||||
| wxMsg.setCouponInject(null); | |||||
| mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),null); | |||||
| } | } | ||||
| return new ResultData(Result.SUCCESS, "短信已发送"); | return new ResultData(Result.SUCCESS, "短信已发送"); | ||||
| } else { | } else { | ||||
| @@ -136,7 +140,9 @@ public class WxMsgServiceImpl implements WxMsgService { | |||||
| if (wxMsg.getExpectSendNumber().intValue() > 1000) { | if (wxMsg.getExpectSendNumber().intValue() > 1000) { | ||||
| batchSendMsg(wxMsg, wxMsgConfig, null); | batchSendMsg(wxMsg, wxMsgConfig, null); | ||||
| } else { | } else { | ||||
| sendmsg(wxMsg, wxMsgConfig, null); | |||||
| //sendmsg(wxMsg, wxMsgConfig, null); | |||||
| wxMsg.setWxMsgConfig(wxMsgConfig); | |||||
| mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } | } | ||||
| return new ResultData(Result.SUCCESS, "短信已发送"); | return new ResultData(Result.SUCCESS, "短信已发送"); | ||||
| } else { | } else { | ||||
| @@ -175,83 +181,93 @@ public class WxMsgServiceImpl implements WxMsgService { | |||||
| String phones = StringUtils.join(phoneList, ","); | String phones = StringUtils.join(phoneList, ","); | ||||
| wxMsg.setPhones(phones); | wxMsg.setPhones(phones); | ||||
| wxMsg.setExpectSendNumber(extra); | wxMsg.setExpectSendNumber(extra); | ||||
| sendmsg(wxMsg, wxMsgConfig, couponInject); | |||||
| //sendmsg(wxMsg, wxMsgConfig, couponInject); | |||||
| wxMsg.setWxMsgConfig(wxMsgConfig); | |||||
| wxMsg.setCouponInject(couponInject); | |||||
| mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } else { | } else { | ||||
| List<String> phoneList = Arrays.asList(split).subList(i * 1000, (i + 1) * 1000); | List<String> phoneList = Arrays.asList(split).subList(i * 1000, (i + 1) * 1000); | ||||
| String phones = StringUtils.join(phoneList, ","); | String phones = StringUtils.join(phoneList, ","); | ||||
| wxMsg.setExpectSendNumber(1000); | wxMsg.setExpectSendNumber(1000); | ||||
| wxMsg.setPhones(phones); | wxMsg.setPhones(phones); | ||||
| sendmsg(wxMsg, wxMsgConfig, couponInject); | |||||
| //sendmsg(wxMsg, wxMsgConfig, couponInject); | |||||
| wxMsg.setWxMsgConfig(wxMsgConfig); | |||||
| wxMsg.setCouponInject(couponInject); | |||||
| mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(),EnumMsgMqTag.DEFAULT.getCode(),EnumMsgMqKey.DEFAULT.getCode()); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| public ResultData sendmsg(WxMsg record, WxMsgConfig wxMsgConfig, WxCouponInject couponInject) { | |||||
| logger.info("发送短信开始..."); | |||||
| logger.info("couponInject:" + couponInject); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| String phone = record.getPhones(); | |||||
| String signature = record.getSignature(); | |||||
| String msg = record.getMsg(); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| WxMsgModel wxMsgModel = wxMsgModelMapper.selectByPrimaryKey(record.getModelId()); | |||||
| Integer modelId = null; | |||||
| if (wxMsgModel != null) { | |||||
| modelId = wxMsgModel.getModelId(); | |||||
| } | |||||
| logger.info("=============迈外迪API开始调用"); | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.NO.getCode().toString(), modelId); | |||||
| logger.info("=============迈外迪API返回结果:" + result); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| String batchNo = jsonObjectResult.get("data").toString(); | |||||
| String resultMsg = jsonObjectResult.get("msg").toString(); | |||||
| record.setReturnResult(jsonObjectResult.toJSONString()); | |||||
| if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode().toString())) { | |||||
| record.setSendstatus(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode()); | |||||
| } else { | |||||
| record.setSendstatus(EnumMsgSendStatus.MSG_SEND_FAIL.getCode()); | |||||
| } | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| long id = idWorker.nextId(); | |||||
| WxMsg wxMsg = new WxMsg(); | |||||
| wxMsg.setTenantId(record.getTenantId()); | |||||
| wxMsg.setModelId(record.getModelId()); | |||||
| wxMsg.setMsg(record.getMsg()); | |||||
| wxMsg.setExpectSendNumber(record.getExpectSendNumber()); | |||||
| wxMsg.setPhones(record.getPhones()); | |||||
| wxMsg.setSignature(record.getSignature()); | |||||
| wxMsg.setIsright(record.getIsright()); | |||||
| wxMsg.setName(record.getName()); | |||||
| wxMsg.setSendstatus(record.getSendstatus()); | |||||
| wxMsg.setLabel(record.getLabel()); | |||||
| wxMsg.setStatus(record.getStatus()); | |||||
| wxMsg.setWay(record.getWay()); | |||||
| wxMsg.setId(id); | |||||
| String systemTime = DateUtils.getSystemTime("yyyy-MM-dd HH:mm:ss"); | |||||
| wxMsg.setSendtime(systemTime); | |||||
| wxMsg.setCreatetime(DateUtils.stringToDate(systemTime, "yyyy-MM-dd HH:mm:ss")); | |||||
| //精准投放 | |||||
| if (couponInject != null) { | |||||
| wxMsg.setCouponInjectId(couponInject.getId()); | |||||
| } | |||||
| wxMsgMapper.insertSelective(wxMsg); | |||||
| logger.info("发送短信结束..."); | |||||
| if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode().toString())) { | |||||
| addMsgCallback(wxMsg, batchNo); | |||||
| return new ResultData(Result.SUCCESS, "短信发送中,您可在短信明细中查看发送状态", id); | |||||
| } else { | |||||
| return new ResultData(ErrorCode.MSG_SEND_INTERFACE_ERROR.getCode(), | |||||
| ErrorCode.MSG_SEND_INTERFACE_ERROR.getMessage() + ":" + resultMsg); | |||||
| } | |||||
| } | |||||
| // @Deprecated | |||||
| // public ResultData sendmsg(WxMsg record, WxMsgConfig wxMsgConfig, WxCouponInject couponInject) { | |||||
| // logger.info("发送短信开始..."); | |||||
| // logger.info("couponInject:" + couponInject); | |||||
| // String secret = wxMsgConfig.getSecret(); | |||||
| // String bid = wxMsgConfig.getBid(); | |||||
| // String publickey = wxMsgConfig.getPublickey(); | |||||
| // | |||||
| // String phone = record.getPhones(); | |||||
| // String signature = record.getSignature(); | |||||
| // String msg = record.getMsg(); | |||||
| // String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| // WxMsgModel wxMsgModel = wxMsgModelMapper.selectByPrimaryKey(record.getModelId()); | |||||
| // Integer modelId = null; | |||||
| // if (wxMsgModel != null) { | |||||
| // modelId = wxMsgModel.getModelId(); | |||||
| // } | |||||
| // logger.info("=============迈外迪API开始调用"); | |||||
| // String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.NO.getCode().toString(), modelId); | |||||
| // logger.info("=============迈外迪API返回结果:" + result); | |||||
| // JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| // String ret = jsonObjectResult.get("ret").toString(); | |||||
| // String batchNo = jsonObjectResult.get("data").toString(); | |||||
| // String resultMsg = jsonObjectResult.get("msg").toString(); | |||||
| // record.setReturnResult(jsonObjectResult.toJSONString()); | |||||
| // | |||||
| // | |||||
| // if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode().toString())) { | |||||
| // record.setSendstatus(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode()); | |||||
| // } else { | |||||
| // record.setSendstatus(EnumMsgSendStatus.MSG_SEND_FAIL.getCode()); | |||||
| // } | |||||
| // | |||||
| // final IdWorker idWorker = IdWorker.get(); | |||||
| // long id = idWorker.nextId(); | |||||
| // WxMsg wxMsg = new WxMsg(); | |||||
| // wxMsg.setTenantId(record.getTenantId()); | |||||
| // wxMsg.setModelId(record.getModelId()); | |||||
| // wxMsg.setMsg(record.getMsg()); | |||||
| // wxMsg.setExpectSendNumber(record.getExpectSendNumber()); | |||||
| // wxMsg.setPhones(record.getPhones()); | |||||
| // wxMsg.setSignature(record.getSignature()); | |||||
| // wxMsg.setIsright(record.getIsright()); | |||||
| // wxMsg.setName(record.getName()); | |||||
| // wxMsg.setSendstatus(record.getSendstatus()); | |||||
| // wxMsg.setLabel(record.getLabel()); | |||||
| // wxMsg.setStatus(record.getStatus()); | |||||
| // wxMsg.setWay(record.getWay()); | |||||
| // wxMsg.setId(id); | |||||
| // String systemTime = DateUtils.getSystemTime("yyyy-MM-dd HH:mm:ss"); | |||||
| // wxMsg.setSendtime(systemTime); | |||||
| // wxMsg.setCreatetime(DateUtils.stringToDate(systemTime, "yyyy-MM-dd HH:mm:ss")); | |||||
| // //精准投放 | |||||
| // if (couponInject != null) { | |||||
| // wxMsg.setCouponInjectId(couponInject.getId()); | |||||
| // } | |||||
| // wxMsgMapper.insertSelective(wxMsg); | |||||
| // | |||||
| // logger.info("发送短信结束..."); | |||||
| // if (ret.equals(EnumMsgSendStatus.MSG_SEND_SUCCESS.getCode().toString())) { | |||||
| // addMsgCallback(wxMsg, batchNo); | |||||
| // return new ResultData(Result.SUCCESS, "短信发送中,您可在短信明细中查看发送状态", id); | |||||
| // } else { | |||||
| // return new ResultData(ErrorCode.MSG_SEND_INTERFACE_ERROR.getCode(), | |||||
| // ErrorCode.MSG_SEND_INTERFACE_ERROR.getMessage() + ":" + resultMsg); | |||||
| // } | |||||
| // | |||||
| // } | |||||
| @Override | |||||
| public void addMsgCallback(WxMsg wxmsg, String batchNo) { | public void addMsgCallback(WxMsg wxmsg, String batchNo) { | ||||
| logger.info("营销短信发送时主动添加回调记录开始..."); | logger.info("营销短信发送时主动添加回调记录开始..."); | ||||
| String phones = wxmsg.getPhones(); | String phones = wxmsg.getPhones(); | ||||
| @@ -42,68 +42,12 @@ public class WxMsgValidationcodeServiceImpl implements WxMsgValidationcodeServic | |||||
| @Autowired | @Autowired | ||||
| WxMerchantBUserMapper wxMerchantBUserMapper; | WxMerchantBUserMapper wxMerchantBUserMapper; | ||||
| @Autowired | @Autowired | ||||
| WxMerchantMapper wxMerchantMapper; | WxMerchantMapper wxMerchantMapper; | ||||
| @Autowired | @Autowired | ||||
| WxMsgCallbackMapper wxMsgCallbackMapper; | WxMsgCallbackMapper wxMsgCallbackMapper; | ||||
| @Override | |||||
| public ResultData sendWorkFlowNodify(WxMsgValidationcode wxMsgValidationcode,Map<String,String> dynamicContentMap) { | |||||
| //3、从短信配置中查询密钥 bid 等信息 | |||||
| WxMsgConfig wxMsgConfig = new WxMsgConfig(); | |||||
| wxMsgConfig.setTenantId(wxMsgValidationcode.getTenantId()); | |||||
| List<WxMsgConfig> wxMsgConfigs = wxMsgConfigMapper.findList(wxMsgConfig); | |||||
| if (wxMsgConfigs.size() == 0) new ResultData(ErrorCode.MSG_SEND_ERROR.getCode(),"发送失败"); | |||||
| wxMsgConfig = wxMsgConfigs.get(0); | |||||
| WxMsgValidationcodeModel wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); | |||||
| wxMsgValidationcodeModel.setTenantId(wxMsgConfig.getTenantId()); | |||||
| wxMsgValidationcodeModel.setType(wxMsgValidationcode.getType()); | |||||
| wxMsgValidationcodeModel = wxMsgValidationcodeModelMapper.findList(wxMsgValidationcodeModel).get(0); | |||||
| wxMsgValidationcode.setSignature(wxMsgValidationcodeModel.getSignature()); | |||||
| String secret = wxMsgConfig.getSecret(); | |||||
| String bid = wxMsgConfig.getBid(); | |||||
| String publickey = wxMsgConfig.getPublickey(); | |||||
| // 验证码 | |||||
| String phone = wxMsgValidationcode.getPhone(); | |||||
| String signature = wxMsgValidationcode.getSignature(); | |||||
| //替换内容 | |||||
| String msg = wxMsgValidationcodeModel.getContent(); | |||||
| for (Map.Entry<String, String> entry : dynamicContentMap.entrySet()) { | |||||
| msg = msg.replace("{"+entry.getKey()+"}", entry.getValue()); | |||||
| } | |||||
| // wxMsgValidationcode.setCode(String.valueOf(code)); | |||||
| wxMsgValidationcode.setMsg(msg); | |||||
| String notifyUrl = wxMsgConfig.getNotifyurl(); | |||||
| Integer modelId = wxMsgValidationcodeModel.getModelId(); | |||||
| String result = WiwideUtil.sendMsg(secret, bid, publickey, phone, signature, msg, notifyUrl, EnumVerifyCode.YES.getCode().toString(), modelId); | |||||
| JSONObject jsonObjectResult = JSONObject.parseObject(result); | |||||
| String ret = jsonObjectResult.get("ret").toString(); | |||||
| String batchNo = jsonObjectResult.get("data").toString(); | |||||
| if (ret.equals("1")) { | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| wxMsgValidationcode.setId(idWorker.nextId()); | |||||
| long currentTime = System.currentTimeMillis() ; | |||||
| Date createtime=new Date(currentTime); | |||||
| // Integer minutes = wxMsgValidationcodeModel.getMinutes(); | |||||
| // currentTime +=minutes*60*1000; | |||||
| // Date expiredate=new Date(currentTime); | |||||
| // wxMsgValidationcode.setExpiretime(expiredate); | |||||
| wxMsgValidationcode.setCreatetime(createtime); | |||||
| wxMsgValidationcodeMapper.insertSelective(wxMsgValidationcode); | |||||
| addMsgCallback(wxMsgValidationcode,batchNo); | |||||
| return new ResultData(Result.SUCCESS,"发送成功"); | |||||
| }else{ | |||||
| logger.error("短信运营商返回失败,手机号:{},返回信息:{}",phone,result); | |||||
| } | |||||
| return new ResultData(ErrorCode.MSG_SEND_ERROR.getCode(),"发送失败"); | |||||
| } | |||||
| @Override | @Override | ||||
| public PageInfo<WxMsgValidationcode> listAsPage(WxMsgValidationcode record, Integer pageIndex, Integer pageSize) { | public PageInfo<WxMsgValidationcode> listAsPage(WxMsgValidationcode record, Integer pageIndex, Integer pageSize) { | ||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxMsgValidationcodeMapper.findList(record)); | return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> wxMsgValidationcodeMapper.findList(record)); | ||||
| @@ -199,6 +143,7 @@ public class WxMsgValidationcodeServiceImpl implements WxMsgValidationcodeServic | |||||
| } | } | ||||
| @Override | |||||
| public void addMsgCallback(WxMsgValidationcode wxmsg, String batchNo){ | public void addMsgCallback(WxMsgValidationcode wxmsg, String batchNo){ | ||||
| logger.info("验证码发送时主动添加回调记录开始..."); | logger.info("验证码发送时主动添加回调记录开始..."); | ||||
| String phone = wxmsg.getPhone(); | String phone = wxmsg.getPhone(); | ||||
| @@ -0,0 +1,128 @@ | |||||
| package com.iformall.utils; | |||||
| import com.fasterxml.jackson.annotation.JsonInclude; | |||||
| import com.fasterxml.jackson.core.JsonGenerator; | |||||
| import com.fasterxml.jackson.core.JsonParser; | |||||
| import com.fasterxml.jackson.core.JsonProcessingException; | |||||
| import com.fasterxml.jackson.databind.DeserializationFeature; | |||||
| import com.fasterxml.jackson.databind.JsonSerializer; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import com.fasterxml.jackson.databind.SerializerProvider; | |||||
| import com.fasterxml.jackson.databind.module.SimpleModule; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import java.io.IOException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.HashMap; | |||||
| import java.util.Iterator; | |||||
| import java.util.Map; | |||||
| public final class JsonUtil { | |||||
| private static Logger log = LoggerFactory.getLogger(JsonUtil.class); | |||||
| public static final ObjectMapper mapper = new ObjectMapper(); | |||||
| private JsonUtil() { | |||||
| } | |||||
| public static String obj2Json(Object obj) { | |||||
| if(obj != null) { | |||||
| try { | |||||
| return mapper.writeValueAsString(obj); | |||||
| } catch (JsonProcessingException var2) { | |||||
| throw new RuntimeException(var2); | |||||
| } | |||||
| } else { | |||||
| return null; | |||||
| } | |||||
| } | |||||
| public static byte[] obj2Byte(Object obj) { | |||||
| if(obj != null) { | |||||
| try { | |||||
| return mapper.writeValueAsBytes(obj); | |||||
| } catch (JsonProcessingException var2) { | |||||
| var2.printStackTrace(); | |||||
| } | |||||
| } | |||||
| return new byte[0]; | |||||
| } | |||||
| public static Object readValue(String json, Class<?> clazz) { | |||||
| Object t = null; | |||||
| try { | |||||
| return mapper.readValue(json, clazz); | |||||
| } catch (Exception var4) { | |||||
| log.info("解析对象:{}", json); | |||||
| log.error("json解析错误:{}", var4.getMessage(), var4); | |||||
| return t; | |||||
| } | |||||
| } | |||||
| // public static <T> T readValue(String json, TypeReference type) { | |||||
| // Object object = null; | |||||
| // | |||||
| // try { | |||||
| // object = mapper.readValue(json, type); | |||||
| // } catch (Exception var4) { | |||||
| // log.info("解析对象:{}", json); | |||||
| // log.error("json解析错误:{}", var4.getMessage(), var4); | |||||
| // } | |||||
| // | |||||
| // return object; | |||||
| // } | |||||
| // | |||||
| // public static <T> T readValue(byte[] json, TypeReference type) { | |||||
| // Object object = null; | |||||
| // | |||||
| // try { | |||||
| // object = mapper.readValue(json, type); | |||||
| // } catch (Exception var4) { | |||||
| // log.info("解析对象:{}", json); | |||||
| // log.error("json解析错误:{}", var4.getMessage(), var4); | |||||
| // } | |||||
| // | |||||
| // return object; | |||||
| // } | |||||
| // | |||||
| // public static Map<String, Object> readValueAsMap(String json) { | |||||
| // return (Map)readValue(json, new TypeReference<HashMap<String, Object>>() { | |||||
| // }); | |||||
| // } | |||||
| static { | |||||
| mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | |||||
| mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); | |||||
| mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); | |||||
| mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); | |||||
| mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); | |||||
| SimpleModule module = new SimpleModule(); | |||||
| module.addSerializer(HashMap.class, new JsonUtil.HashMapSerializer()); | |||||
| mapper.registerModule(module); | |||||
| } | |||||
| public static class HashMapSerializer extends JsonSerializer<HashMap> { | |||||
| public HashMapSerializer() { | |||||
| } | |||||
| public void serialize(HashMap value, JsonGenerator jgen, SerializerProvider provider) throws IOException { | |||||
| jgen.writeStartObject(); | |||||
| Iterator var4 = value.entrySet().iterator(); | |||||
| while(var4.hasNext()) { | |||||
| Object entry = var4.next(); | |||||
| if(entry instanceof Map.Entry) { | |||||
| Map.Entry en = (Map.Entry)entry; | |||||
| if(en.getValue() != null && en.getKey() != null) { | |||||
| jgen.writeObjectField(en.getKey().toString(), en.getValue()); | |||||
| } | |||||
| } | |||||
| } | |||||
| jgen.writeEndObject(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,81 @@ | |||||
| <?xml version="1.0" encoding="UTF-8"?> | |||||
| <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||||
| <mapper namespace="com.iformall.mapper.WxMsgRecordMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.WxMsgRecord"> | |||||
| <id column="id" property="id" /> | |||||
| <result column="tenant_id" property="tenantId" /> | |||||
| <result column="domain" property="domain" /> | |||||
| <result column="msg_type" property="msgType" /> | |||||
| <result column="msg" property="msg" /> | |||||
| <result column="send_time" property="sendTime" /> | |||||
| <result column="model_id" property="modelId" /> | |||||
| <result column="sender" property="from" /> | |||||
| <result column="sender_user_id" property="fromUserId" /> | |||||
| <result column="sender_user_name" property="fromUserName" /> | |||||
| <result column="receiver" property="to" /> | |||||
| <result column="receiver_user_id" property="toUserId" /> | |||||
| <result column="receiver_user_name" property="toUserName" /> | |||||
| <result column="msg_status" property="msgStatus" /> | |||||
| <result column="status_message" property="statusMessage" /> | |||||
| <result column="createtime" property="createtime" /> | |||||
| <result column="updatetime" property="updatetime" /> | |||||
| <result column="uuid" property="uuid" /> | |||||
| <result column="signature" property="signature" /> | |||||
| <result column="model_type" property="modelType" /> | |||||
| <result column="msg_json" property="msgJson" /> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| id,tenant_id,domain,msg_type,msg,send_time,model_id,sender,sender_user_id,sender_user_name,receiver,receiver_user_id, | |||||
| receiver_user_name,msg_status,status_message,createtime,updatetime,uuid,signature,model_type,msg_json | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != tenantId "> | |||||
| and `tenant_id` = #{tenantId} | |||||
| </if> | |||||
| <if test=" null != receiverUserId "> | |||||
| and `receiver_user_id` = #{receiverUserId} | |||||
| </if> | |||||
| <if test=" null != receiver "> | |||||
| and `receiver` = #{receiver} | |||||
| </if> | |||||
| <if test=" null != msgStatus "> | |||||
| and `msg_status` = #{msgStatus} | |||||
| </if> | |||||
| <if test=" null != domain "> | |||||
| and `domain` = #{domain} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| order by createtime desc | |||||
| </sql> | |||||
| <update id="update" parameterType="com.iformall.domain.po.BaseMsg"> | |||||
| update wx_msg_record set updatetime = now() | |||||
| <if test=" null != msgStatus ">,msg_status = #{msgStatus}</if> | |||||
| <if test=" null != statusMessage ">,status_message = #{statusMessage}</if> | |||||
| <where> | |||||
| <if test=" null != uuid ">and uuid = #{uuid}</if> | |||||
| </where> | |||||
| </update> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.WxMsgRecord" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from wx_msg_model | |||||
| <include refid="dynamicWhereConditions" /> | |||||
| </select> | |||||
| </mapper> | |||||
| @@ -18,6 +18,7 @@ | |||||
| <module>mallinkBApi</module> | <module>mallinkBApi</module> | ||||
| <module>mallinkSchedule</module> | <module>mallinkSchedule</module> | ||||
| <module>mallinkWechatOpen</module> | <module>mallinkWechatOpen</module> | ||||
| <module>mallinkMQConsumer</module> | |||||
| </modules> | </modules> | ||||
| <parent> | <parent> | ||||
| @@ -119,6 +120,18 @@ | |||||
| <scope>test</scope> | <scope>test</scope> | ||||
| </dependency> | </dependency> | ||||
| <!-- rocketmq --> | |||||
| <dependency> | |||||
| <groupId>org.rocketmq.spring.boot</groupId> | |||||
| <artifactId>rocketmq-spring-boot-starter</artifactId> | |||||
| <version>1.0.0.RELEASE</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.apache.rocketmq</groupId> | |||||
| <artifactId>rocketmq-client</artifactId> | |||||
| <version>4.4.0</version> | |||||
| </dependency> | |||||
| <dependency> | <dependency> | ||||
| <groupId>org.apache.commons</groupId> | <groupId>org.apache.commons</groupId> | ||||
| <artifactId>commons-lang3</artifactId> | <artifactId>commons-lang3</artifactId> | ||||