| @@ -0,0 +1,154 @@ | |||||
| <?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>mallinkPosApi</artifactId> | |||||
| <dependencies> | |||||
| <dependency> | |||||
| <groupId>com.iformall</groupId> | |||||
| <artifactId>mallinkService</artifactId> | |||||
| <version>1.0</version> | |||||
| </dependency> | |||||
| <dependency> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-starter-test</artifactId> | |||||
| <scope>test</scope> | |||||
| </dependency> | |||||
| </dependencies> | |||||
| <build> | |||||
| <plugins> | |||||
| <plugin> | |||||
| <groupId>org.springframework.boot</groupId> | |||||
| <artifactId>spring-boot-maven-plugin</artifactId> | |||||
| <configuration> | |||||
| <executable>true</executable> | |||||
| <layout>ZIP</layout> | |||||
| <excludeGroupIds> | |||||
| antlr, | |||||
| cn.afterturn, | |||||
| ch.qos.logback, | |||||
| com.alibaba, | |||||
| com.amazonaws, | |||||
| com.mchange, | |||||
| com.fasterxml.jackson.core, | |||||
| com.fasterxml.jackson.dataformat, | |||||
| com.fasterxml.jackson.datatype, | |||||
| com.fasterxml.jackson.module, | |||||
| com.fasterxml.uuid, | |||||
| com.fasterxml, | |||||
| com.github.axet, | |||||
| com.github.binarywang, | |||||
| com.github.jsqlparser, | |||||
| com.github.pagehelper, | |||||
| com.github.ulisesbocchio, | |||||
| com.github.virtuald, | |||||
| com.google.code.findbugs, | |||||
| com.google.code.gson, | |||||
| com.google.errorprone, | |||||
| com.google.guava, | |||||
| com.google.protobuf, | |||||
| com.google.zxing, | |||||
| com.jayway.jsonpath, | |||||
| com.jhlabs, | |||||
| com.puppycrawl.tools, | |||||
| com.rabbitmq, | |||||
| com.squareup.okhttp3, | |||||
| com.squareup.okio, | |||||
| com.sun, | |||||
| com.sun.mail, | |||||
| com.thoughtworks.xstream, | |||||
| com.zaxxer, | |||||
| commons-beanutils, | |||||
| commons-cli, | |||||
| commons-codec, | |||||
| commons-collections, | |||||
| commons-fileupload, | |||||
| commons-io, | |||||
| commons-logging, | |||||
| io.lettuce, | |||||
| io.netty, | |||||
| io.projectreactor, | |||||
| io.springfox, | |||||
| io.swagger, | |||||
| io.undertow, | |||||
| javax.activation, | |||||
| javax.annotation, | |||||
| javax.mail, | |||||
| javax.persistence, | |||||
| javax.servlet, | |||||
| javax.validation, | |||||
| javax.xml.bind, | |||||
| joda-time, | |||||
| junit, | |||||
| mysql, | |||||
| net.bytebuddy, | |||||
| net.minidev, | |||||
| net.sf.dozer, | |||||
| net.sf.saxon, | |||||
| ognl, | |||||
| org.antlr, | |||||
| org.apache.commons, | |||||
| org.apache.httpcomponents, | |||||
| org.apache.logging.log4j, | |||||
| org.apache.poi, | |||||
| org.apache.poi.wso2, | |||||
| org.apache.rocketmq, | |||||
| org.apache.shiro, | |||||
| org.apache.tomcat.embed, | |||||
| org.apache.xmlbeans, | |||||
| org.aspectj, | |||||
| org.assertj, | |||||
| org.bouncycastle, | |||||
| org.checkerframework, | |||||
| org.codehaus.mojo, | |||||
| org.crazycake, | |||||
| org.dom4j, | |||||
| org.flowable, | |||||
| org.flywaydb, | |||||
| org.glassfish, | |||||
| org.hibernate.validator, | |||||
| org.jasypt, | |||||
| org.javassist, | |||||
| org.jboss.logging, | |||||
| org.jboss.spec.javax.annotation, | |||||
| org.jboss.spec.javax.websocket, | |||||
| org.jboss.xnio, | |||||
| org.jdom, | |||||
| org.jodd, | |||||
| org.mapstruct, | |||||
| org.mockito, | |||||
| org.mybatis, | |||||
| org.mybatis.generator, | |||||
| org.mybatis.spring.boot, | |||||
| org.ow2.asm, | |||||
| org.projectlombok, | |||||
| org.quartz-scheduler, | |||||
| org.reflections, | |||||
| org.rocketmq.spring.boot, | |||||
| org.slf4j, | |||||
| org.springframework, | |||||
| org.springframework.amqp, | |||||
| org.springframework.boot, | |||||
| org.springframework.data, | |||||
| org.springframework.retry, | |||||
| org.springframework.ws, | |||||
| org.yaml, | |||||
| redis.clients, | |||||
| software.amazon.ion, | |||||
| tk.mybatis, | |||||
| xmlpull, | |||||
| xpp3 | |||||
| </excludeGroupIds> | |||||
| </configuration> | |||||
| </plugin> | |||||
| </plugins> | |||||
| </build> | |||||
| </project> | |||||
| @@ -0,0 +1,49 @@ | |||||
| 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 tk.mybatis.spring.annotation.MapperScan; | |||||
| /** | |||||
| * @author chenkx | |||||
| * @date 2017-12-26 | |||||
| */ | |||||
| @SpringBootApplication | |||||
| @MapperScan(basePackages = {"com.iformall.mapper"}) | |||||
| @EnableEncryptableProperties | |||||
| @EnableRocketMQ | |||||
| public class PosApplication { | |||||
| @Value("${fm.exception}") | |||||
| private boolean fmException; | |||||
| @Value("${fm.exception_emails}") | |||||
| private String fmExceptionEmails; | |||||
| @Value("${fm.open}") | |||||
| private boolean fmOpen; | |||||
| @Bean | |||||
| public boolean isFmException() { | |||||
| return fmException; | |||||
| } | |||||
| @Bean | |||||
| public String fmExceptionEmails() { | |||||
| return fmExceptionEmails; | |||||
| } | |||||
| @Bean | |||||
| public boolean isFmOpen() { | |||||
| return fmOpen; | |||||
| } | |||||
| public static void main(String[] args) { | |||||
| SpringApplication.run(PosApplication.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,125 @@ | |||||
| package com.iformall.config; | |||||
| import com.iformall.domain.po.PushLimit; | |||||
| import com.iformall.domain.po.WxCUser; | |||||
| import com.iformall.domain.po.WxMall; | |||||
| 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.cache.RedisCacheWriter; | |||||
| 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.Map; | |||||
| /** | |||||
| * 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; | |||||
| } | |||||
| @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; | |||||
| } | |||||
| @Bean("cuserTokenRedisTemplate") | |||||
| public RedisTemplate<String, WxCUser> getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, WxCUser> template = new RedisTemplate<String, WxCUser>(); | |||||
| Jackson2JsonRedisSerializer<WxCUser> j = new Jackson2JsonRedisSerializer<WxCUser>(WxCUser.class); | |||||
| // value值的序列化 | |||||
| template.setValueSerializer(j); | |||||
| template.setHashKeySerializer(j); | |||||
| // key的序列化 | |||||
| template.setKeySerializer(new StringRedisSerializer()); | |||||
| template.setHashKeySerializer(new StringRedisSerializer()); | |||||
| template.setConnectionFactory(connectionFactory); | |||||
| return template; | |||||
| } | |||||
| @Bean("mallRedisTemplate") | |||||
| public RedisTemplate<String, WxMall> getMallRedisTemplate(RedisConnectionFactory connectionFactory) { | |||||
| RedisTemplate<String, WxMall> template = new RedisTemplate<String, WxMall>(); | |||||
| Jackson2JsonRedisSerializer<WxMall> j = new Jackson2JsonRedisSerializer<WxMall>(WxMall.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,49 @@ | |||||
| package com.iformall.config; | |||||
| import org.springframework.context.annotation.Bean; | |||||
| import org.springframework.context.annotation.Configuration; | |||||
| import springfox.documentation.builders.ApiInfoBuilder; | |||||
| import springfox.documentation.builders.ParameterBuilder; | |||||
| import springfox.documentation.builders.PathSelectors; | |||||
| import springfox.documentation.builders.RequestHandlerSelectors; | |||||
| import springfox.documentation.schema.ModelRef; | |||||
| import springfox.documentation.service.ApiInfo; | |||||
| import springfox.documentation.service.Parameter; | |||||
| import springfox.documentation.spi.DocumentationType; | |||||
| import springfox.documentation.spring.web.plugins.Docket; | |||||
| import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||||
| import java.util.ArrayList; | |||||
| import java.util.List; | |||||
| //参考:http://blog.csdn.net/catoop/article/details/50668896 | |||||
| @Configuration | |||||
| @EnableSwagger2 | |||||
| public class Swagger2Config { | |||||
| @Bean | |||||
| public Docket createRestApi() { | |||||
| ParameterBuilder tokenPar = new ParameterBuilder(); | |||||
| List<Parameter> pars = new ArrayList<Parameter>(); | |||||
| //增加一个request的header参数 | |||||
| tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); | |||||
| pars.add(tokenPar.build()); | |||||
| return new Docket(DocumentationType.SWAGGER_2) | |||||
| .apiInfo(apiInfo()) | |||||
| .select() | |||||
| .apis(RequestHandlerSelectors.basePackage("com.iformall.controller")) | |||||
| .paths(PathSelectors.any()) | |||||
| .build() | |||||
| .globalOperationParameters(pars); | |||||
| } | |||||
| private ApiInfo apiInfo() { | |||||
| return new ApiInfoBuilder() | |||||
| .title("b端 api") | |||||
| .description("b端 api") | |||||
| .termsOfServiceUrl("http://localhost:8000") | |||||
| .version("2.0") | |||||
| .build(); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,80 @@ | |||||
| 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.*; | |||||
| import java.math.BigDecimal; | |||||
| import java.math.BigInteger; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.List; | |||||
| /** | |||||
| * MVC配置 | |||||
| * | |||||
| * @author stormeye.wu | |||||
| * @email wugq@mippoint.com | |||||
| * @date 2017-04-20 22:30 | |||||
| */ | |||||
| @Configuration | |||||
| @EnableWebMvc | |||||
| public class WebMvcConfig 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,83 @@ | |||||
| package com.iformall.controller; | |||||
| import java.beans.PropertyEditorSupport; | |||||
| import java.text.ParseException; | |||||
| import java.text.SimpleDateFormat; | |||||
| import java.util.Date; | |||||
| import cn.binarywang.wx.miniapp.api.WxMaService; | |||||
| import com.iformall.domain.po.WxAppinfo; | |||||
| import com.iformall.service.WxAppinfoService; | |||||
| import com.iformall.service.wechat.FmOpenService; | |||||
| import com.iformall.utils.IPUtil; | |||||
| import com.iformall.utils.MaUtil; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.web.bind.WebDataBinder; | |||||
| import org.springframework.web.bind.annotation.InitBinder; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import org.springframework.web.context.request.RequestContextHolder; | |||||
| import org.springframework.web.context.request.ServletRequestAttributes; | |||||
| import javax.servlet.http.HttpServletRequest; | |||||
| @RestController | |||||
| public class BaseController { | |||||
| @Autowired | |||||
| private boolean isFmOpen; | |||||
| @Autowired | |||||
| private WxAppinfoService wxAppinfoService; | |||||
| @Autowired | |||||
| private FmOpenService openService; | |||||
| @InitBinder | |||||
| public void InitBinder(WebDataBinder dataBinder) { | |||||
| dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { | |||||
| public void setAsText(String value) { | |||||
| try { | |||||
| setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)); | |||||
| } catch (ParseException e) { | |||||
| try { | |||||
| setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value)); | |||||
| } catch (ParseException e1) { | |||||
| setValue(null); | |||||
| } | |||||
| } | |||||
| } | |||||
| public String getAsText() { | |||||
| return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue()); | |||||
| } | |||||
| }); | |||||
| } | |||||
| public WxAppinfo getAppInfo(String appId) { | |||||
| return wxAppinfoService.getByAppId(appId); | |||||
| } | |||||
| public WxMaService getWeappService(String appId) { | |||||
| if(isFmOpen) { | |||||
| return openService.getWxOpenComponentService().getWxMaServiceByAppid(appId); | |||||
| } else { | |||||
| WxAppinfo appinfo = wxAppinfoService.getByAppId(appId); | |||||
| WxMaService service = MaUtil.getWeappService(appinfo); | |||||
| return service; | |||||
| } | |||||
| } | |||||
| public WxMaService getWeappServiceByAppInfo(WxAppinfo appinfo) { | |||||
| if(!isFmOpen) { | |||||
| WxMaService service = MaUtil.getWeappService(appinfo); | |||||
| return service; | |||||
| } | |||||
| return null; | |||||
| } | |||||
| public String getIpAddr() { | |||||
| HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); | |||||
| String ipaddress = IPUtil.getIpAddr(request); | |||||
| return ipaddress; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| package com.iformall.controller; | |||||
| import com.iformall.common.ResultData; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Value; | |||||
| import org.springframework.web.bind.annotation.GetMapping; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| @RestController | |||||
| @Api(description = "登录相关接口") | |||||
| public class HomeController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Value("${version}") | |||||
| private String version; | |||||
| @GetMapping("/version") | |||||
| @ApiOperation("获取后端版本号") | |||||
| public ResultData version() { | |||||
| logger.debug("[" + getIpAddr() + "] HomeController::version"); | |||||
| return new ResultData(version); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,437 @@ | |||||
| package com.iformall.controller; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.pay.WxPayConstant; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import com.iformall.service.*; | |||||
| import io.swagger.annotations.Api; | |||||
| import io.swagger.annotations.ApiOperation; | |||||
| import lombok.AllArgsConstructor; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.web.bind.annotation.PostMapping; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import org.springframework.web.bind.annotation.RestController; | |||||
| import java.util.*; | |||||
| @RestController | |||||
| @AllArgsConstructor | |||||
| //@RequestMapping(value = "/p") | |||||
| @Api(description = "POS相关接口") | |||||
| public class PosController extends BaseController { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| private final PosService posService; | |||||
| private final ThDevInfoService thDevInfoService; | |||||
| @ApiOperation(value = "获取注册二维码", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"nonce_str\":\"string(必填)\"}") | |||||
| @PostMapping("/getQrCode") | |||||
| public Map<String, String> getQrCode(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.doGetQrCode(params); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), | |||||
| e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", WxPayConstant.RET_FAIL, | |||||
| 500, | |||||
| e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "会员识别", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"mem_id\":\"string(选填)\"," + | |||||
| "\"mem_phone\":\"string(选填)\"," + | |||||
| "\"pos_order_id\":\"string(必填)\"" + | |||||
| "\"nonce_str\":\"string(必填)\"}") | |||||
| @PostMapping("/checkMem") | |||||
| public Map<String, String> checkMem(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.checkMember(params); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "券是否可以核销", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"bu_user_id\":\"string(必填)\"," + | |||||
| "\"coupon_order_id\":\"string(必填)\" +" + | |||||
| "\"nonce_str\":\"string(必填)\" +" + | |||||
| "\"pos_order_id\":\"string(选填)\" }") | |||||
| @PostMapping("/checkCouponOrderForVerify") | |||||
| public Map<String, String> checkCouponOrderVerify(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.couponOrderVerifyDoSomething(params, EnumVerifyActionType.CHECK); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "券预核销", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"bu_user_id\":\"string(必填)\"," + | |||||
| "\"coupon_order_id\":\"string(必填)\" +" + | |||||
| "\"nonce_str\":\"string(必填)\" +" + | |||||
| "\"pos_order_id\":\"string(必填)\" }") | |||||
| @PostMapping("/couponOrderPreVerify") | |||||
| public Map<String, String> couponOrderPreVerify(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.couponOrderVerifyDoSomething(params, EnumVerifyActionType.PRE_VERIFY); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "券预核销取消", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"bu_user_id\":\"string(必填)\"," + | |||||
| "\"coupon_order_id\":\"string(必填)\" +" + | |||||
| "\"nonce_str\":\"string(必填)\" +" + | |||||
| "\"pos_order_id\":\"string(必填)\" }") | |||||
| @PostMapping("/couponOrderPreVerifyCancel") | |||||
| public Map<String, String> couponOrderPreVerifyCancel(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.couponOrderVerifyCancel(params, EnumVerifyActionType.PRE_VERIFY_CANCEL); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "券独立核销", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"bu_user_id\":\"string(必填)\"," + | |||||
| "\"coupon_order_id\":\"string(必填)\" +" + | |||||
| "\"nonce_str\":\"string(必填)\" +" + | |||||
| "\"pos_order_id\":\"string(必填)\" }") | |||||
| @PostMapping("/couponOrderIndependentVerify") | |||||
| public Map<String, String> couponOrderIndependentVerify(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.couponOrderVerifyDoSomething(params, EnumVerifyActionType.VERIFY_INDEPENT); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "券交易核销", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"bu_user_id\":\"string(必填)\"," + | |||||
| "\"coupon_order_id\":\"string(必填)\" +" + | |||||
| "\"nonce_str\":\"string(必填)\" +" + | |||||
| "\"pos_order_id\":\"string(必填)\" }") | |||||
| @PostMapping("/couponOrderPayVerify") | |||||
| public Map<String, String> couponOrderPayVerify(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.couponOrderVerifyDoSomething(params, EnumVerifyActionType.VERIFY_PAY); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| @ApiOperation(value = "券核销取消", notes = "{" + | |||||
| "\"dev_id\":\"string(必填)\"," + | |||||
| "\"tenant_id\":\"string(必填)\"," + | |||||
| "\"merchant_id\":\"string(必填)\"," + | |||||
| "\"bu_user_id\":\"string(必填)\"," + | |||||
| "\"coupon_order_id\":\"string(必填)\" +" + | |||||
| "\"nonce_str\":\"string(必填)\" +" + | |||||
| "\"pos_order_id\":\"string(必填)\" }") | |||||
| @PostMapping("/couponOrderVerifyCancel") | |||||
| public Map<String, String> couponOrderIndependentVerifyCancel(@RequestBody Map<String, String> params) { | |||||
| JSONObject payContent = new JSONObject(); | |||||
| // 1. check sign | |||||
| Map<String, String> retMap = checkSign(params, payContent); | |||||
| if (retMap != null) { | |||||
| // 签名相关异常返回 | |||||
| return retMap; | |||||
| } | |||||
| String resKey = payContent.getString("resKey"); | |||||
| logger.info("resKey: " + resKey); | |||||
| try { | |||||
| retMap = posService.couponOrderVerifyCancel(params, EnumVerifyActionType.VERIFY_CANCEL); | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_SUCCESS, null); | |||||
| } catch (MallinkException e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| return buildReturnMap(retMap, resKey, WxPayConstant.RET_SUCCESS, "", | |||||
| WxPayConstant.RET_FAIL, | |||||
| 500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 构造返回map,无签名, 有错误 | |||||
| * @param retCode | |||||
| * @param retMsg | |||||
| * @param resCode | |||||
| * @param errCode | |||||
| * @param errMsg | |||||
| * @return | |||||
| */ | |||||
| private Map<String, String> buildReturnMap(String retCode, String retMsg, String resCode, Integer errCode, String errMsg) { | |||||
| Map<String, String> retMap = new HashMap<>(); | |||||
| retMap.put(WxPayConstant.RETURN_CODE, retCode); | |||||
| retMap.put(WxPayConstant.RETURN_MSG, retMsg); | |||||
| retMap.put(WxPayConstant.RESULT_CODE, resCode); | |||||
| retMap.put(WxPayConstant.ERR_CODE, "" + errCode); | |||||
| retMap.put(WxPayConstant.ERR_CODE_DESC, errMsg); | |||||
| return retMap; | |||||
| } | |||||
| /** | |||||
| * 构造返回map,带签名, 有错误 | |||||
| * @param retMap | |||||
| * @param resKey | |||||
| * @param retCode | |||||
| * @param retMsg | |||||
| * @param resCode | |||||
| * @param err | |||||
| * @return | |||||
| */ | |||||
| private Map<String, String> buildReturnMap(Map<String, String> retMap, String resKey, String retCode, String retMsg, String resCode, ErrorCode err) { | |||||
| if(retMap == null) { | |||||
| retMap = new HashMap<>(); | |||||
| } | |||||
| retMap.put(WxPayConstant.RETURN_CODE, retCode); | |||||
| retMap.put(WxPayConstant.RETURN_MSG, retMsg); | |||||
| retMap.put(WxPayConstant.RESULT_CODE, resCode); | |||||
| if (err != null) { | |||||
| retMap.put(WxPayConstant.ERR_CODE, "" + err.getCode()); | |||||
| retMap.put(WxPayConstant.ERR_CODE_DESC, err.getMessage()); | |||||
| } | |||||
| return WxPayment.buildSignAfterParasMapForHMAC(retMap, resKey); | |||||
| } | |||||
| /** | |||||
| * 构造返回map,带签名, 有错误 | |||||
| * @param retMap | |||||
| * @param resKey | |||||
| * @param retCode | |||||
| * @param retMsg | |||||
| * @param resCode | |||||
| * @param errCode | |||||
| * @param errMsg | |||||
| * @return | |||||
| */ | |||||
| private Map<String, String> buildReturnMap(Map<String, String> retMap, String resKey, String retCode, String retMsg, String resCode, Integer errCode, String errMsg) { | |||||
| if(retMap == null) { | |||||
| retMap = new HashMap<>(); | |||||
| } | |||||
| retMap.put(WxPayConstant.RETURN_CODE, retCode); | |||||
| retMap.put(WxPayConstant.RETURN_MSG, retMsg); | |||||
| retMap.put(WxPayConstant.RESULT_CODE, resCode); | |||||
| retMap.put(WxPayConstant.ERR_CODE, "" + errCode); | |||||
| retMap.put(WxPayConstant.ERR_CODE_DESC, errMsg); | |||||
| return WxPayment.buildSignAfterParasMapForHMAC(retMap, resKey); | |||||
| } | |||||
| /** | |||||
| * 验证创建订单请求参数,参数通过返回JSONObject对象,否则返回错误文本信息 | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| private Map<String, String> checkSign(Map<String, String> params, JSONObject payContent) { | |||||
| // 1. check sign | |||||
| // 开发者参数 | |||||
| String devId = params.get(WxPayConstant.DEV_ID); // 开发者ID | |||||
| String sign = params.get(WxPayConstant.SIGN); // 签名 | |||||
| if (StringUtils.isBlank(devId)) { | |||||
| String errorMessage = "request params[dev_id] error."; | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errorMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(sign)) { | |||||
| String errorMessage = "request params[sign] error."; | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errorMessage); | |||||
| } | |||||
| // 查询开发者信息 | |||||
| ThDevInfo devInfo = thDevInfoService.getByDevId(devId); | |||||
| if (devInfo == null) { | |||||
| String errorMessage = "Can't found devInfo[dev_id="+devId+"] record in db."; | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_NOT_FOUND.getCode(), errorMessage); | |||||
| } | |||||
| if (devInfo.getState().equals(EnumEnableType.Disable.getCode())) { | |||||
| String errorMessage = "devInfo not available [dev_id="+devId+"] record in db."; | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_IS_DISABLED.getCode(), errorMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(devInfo.getReqKey())) { | |||||
| String errorMessage = "reqKey is null[dev_id="+devId+"] record in db."; | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_REQ_KEY_IS_NULL.getCode(), errorMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(devInfo.getResKey())) { | |||||
| String errorMessage = "resKey is null[dev_id="+devId+"] record in db."; | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, "参数错误", WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_RES_KEY_IS_NULL.getCode(), errorMessage); | |||||
| } | |||||
| payContent.put("resKey", devInfo.getResKey()); | |||||
| boolean signVerified = WxPayment.verifyNotifyHMAC(params, devInfo.getReqKey()); | |||||
| if (!signVerified) { | |||||
| String errorMessage = "签名错误"; | |||||
| logger.error("checksign error, params: " + params.toString()); | |||||
| return buildReturnMap(WxPayConstant.RET_FAIL, errorMessage, WxPayConstant.RET_FAIL, ErrorCode.DEV_ID_RES_KEY_IS_NULL.getCode(), errorMessage); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,28 @@ | |||||
| package com.iformall.service; | |||||
| import com.iformall.enums.EnumVerifyActionType; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import java.util.Map; | |||||
| public interface PosService { | |||||
| /** | |||||
| * 获取商城二维码 | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| Map<String, String> doGetQrCode(Map<String, String> params) throws MallinkException; | |||||
| /** | |||||
| * 识别会员 | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| Map<String, String> checkMember(Map<String, String> params) throws MallinkException; | |||||
| Map<String, String> couponOrderVerifyDoSomething(@RequestBody Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException; | |||||
| Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException; | |||||
| } | |||||
| @@ -0,0 +1,753 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.iformall.common.ErrorCode; | |||||
| import com.iformall.domain.po.*; | |||||
| import com.iformall.domain.vo.WxCouponOrderCVo; | |||||
| import com.iformall.domain.vo.WxLevelMerchantCVo; | |||||
| import com.iformall.enums.*; | |||||
| import com.iformall.exception.MallinkException; | |||||
| import com.iformall.mapper.WxCouponMapper; | |||||
| import com.iformall.mapper.WxCouponMerchantMapper; | |||||
| import com.iformall.mapper.WxCouponOrderMapper; | |||||
| import com.iformall.mapper.WxOrderMapper; | |||||
| import com.iformall.pay.WxPayConstant; | |||||
| import com.iformall.service.*; | |||||
| import lombok.AllArgsConstructor; | |||||
| import org.apache.commons.lang3.StringUtils; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.stereotype.Service; | |||||
| import org.springframework.transaction.annotation.Transactional; | |||||
| import org.springframework.web.bind.annotation.RequestBody; | |||||
| import java.util.Date; | |||||
| import java.util.HashMap; | |||||
| import java.util.List; | |||||
| import java.util.Map; | |||||
| @Service | |||||
| @AllArgsConstructor | |||||
| public class PosServiceImpl implements PosService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| private final WxMallService mallService; | |||||
| private final WxCUserService cUserService; | |||||
| private final WxLevelConfigService levelConfigService; | |||||
| private final WxCouponOrderService couponOrderService; | |||||
| private final WxMerchantService merchantService; | |||||
| private final WxMerchantBUserService merchantBUserService; | |||||
| private final PosCouponOrderVerifyService posCouponOrderVerifyService; | |||||
| private final WxScoreRulesService scoreRulesService; | |||||
| private final WxCreditHistoryService creditHistoryService; | |||||
| private final WxOrderMapper orderMapper; | |||||
| private final WxCouponOrderMapper couponOrderMapper; | |||||
| private final WxCouponMerchantMapper couponMerchantMapper; | |||||
| private final WxCouponMapper couponMapper; | |||||
| /** | |||||
| * 获取商城二维码 | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| @Override | |||||
| public Map<String, String> doGetQrCode(Map<String, String> params) throws MallinkException { | |||||
| Map<String, String> retMap = new HashMap<>(); | |||||
| String nonceStr = params.get(WxPayConstant.NONCE_STR); // 随机数 | |||||
| String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID | |||||
| if (StringUtils.isBlank(tenantId)) { | |||||
| String errMessage = "request params[tenant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| WxMall mall = mallService.getByTenantId(tenantId); | |||||
| if (mall == null) { | |||||
| logger.error(ErrorCode.MALL_INFO_NOT_FOUND.getMessage()); | |||||
| throw new MallinkException(ErrorCode.MALL_INFO_NOT_FOUND); | |||||
| } | |||||
| retMap.put("qrcode_url", mall.getImgQrcodeWeapp()); | |||||
| return retMap; | |||||
| } | |||||
| /** | |||||
| * 识别会员 | |||||
| * @param params | |||||
| * @return | |||||
| */ | |||||
| @Override | |||||
| public Map<String, String> checkMember(Map<String, String> params) throws MallinkException { | |||||
| Map<String, String> retMap = new HashMap<>(); | |||||
| String nonceStr = params.get(WxPayConstant.NONCE_STR); // 随机数 | |||||
| String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID | |||||
| String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID | |||||
| String memIdStr = params.get(WxPayConstant.MEM_ID); // 会员ID | |||||
| String memPhoneStr = params.get(WxPayConstant.MEM_PHONE); // 会员手机 | |||||
| String posOrderIdStr = params.get(WxPayConstant.POS_ORDER_ID); // POS订单ID | |||||
| if (StringUtils.isBlank(tenantId)) { | |||||
| String errMessage = "request params[tenant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(merchantIdStr)) { | |||||
| String errMessage = "request params[merchant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(posOrderIdStr)) { | |||||
| String errMessage = "request params[pos_order_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(memIdStr) && StringUtils.isBlank(memPhoneStr)) { | |||||
| String errMessage = "please give one value for mem_id or mem_phone"; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| WxCUser user = null; | |||||
| if (StringUtils.isNotBlank(memIdStr)) { | |||||
| Long memId; | |||||
| try { | |||||
| memId = Long.valueOf(memIdStr); | |||||
| } catch (NumberFormatException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| user = cUserService.getById(memId); | |||||
| } | |||||
| if (StringUtils.isNotBlank(memPhoneStr)) { | |||||
| WxCUser q = new WxCUser(); | |||||
| q.setTenantId(tenantId); | |||||
| q.setPhone(memPhoneStr); | |||||
| user = cUserService.getByObject(q); | |||||
| } | |||||
| if (user == null) { | |||||
| logger.error(ErrorCode.USER_NOT_MEMBER.getMessage()); | |||||
| throw new MallinkException(ErrorCode.USER_NOT_MEMBER); | |||||
| } | |||||
| Long merchantId, posOrderId; | |||||
| try { | |||||
| merchantId = Long.valueOf(merchantIdStr); | |||||
| posOrderId = Long.valueOf(posOrderIdStr); | |||||
| } catch (NumberFormatException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR); | |||||
| } | |||||
| // Level, 折扣 | |||||
| List<WxLevelConfig> levelList = levelConfigService.getByTenantId(tenantId); | |||||
| String level = WxLevelConfigService.DEFAULT_LEVEL; | |||||
| Long levelId = 0L; | |||||
| for (WxLevelConfig levelConfig : levelList) { | |||||
| if (user.getScore() >= levelConfig.getPoints()) { | |||||
| if (levelConfig.getDiscountEnable().equals(EnumLevelConfigDiscountStatus.ENABLE.getCode())) | |||||
| levelId = levelConfig.getId(); | |||||
| level = levelConfig.getLevel(); | |||||
| } | |||||
| } | |||||
| WxLevelMerchant levelMerchant = new WxLevelMerchant(); | |||||
| levelMerchant.setTenantId(tenantId); | |||||
| levelMerchant.setLevelId(levelId); | |||||
| levelMerchant.setMerchantId(merchantId); | |||||
| List<WxLevelMerchantCVo> levelMerchantList = levelConfigService.findListCVo(levelMerchant); | |||||
| if(levelMerchantList.size() >= 1) { | |||||
| WxLevelMerchantCVo levelMerchantCVo = levelMerchantList.get(0); | |||||
| if(levelMerchantCVo != null) { | |||||
| retMap.put("discount", levelMerchantCVo.getDiscount().toString()); | |||||
| retMap.put("levelMerchant", levelMerchantCVo.toString()); | |||||
| } | |||||
| } else { | |||||
| retMap.put("discount", "100"); | |||||
| } | |||||
| retMap.put("id", user.getId().toString()); | |||||
| retMap.put("phone", user.getPhone()); | |||||
| retMap.put("level", level); | |||||
| // 优惠券列表 | |||||
| Map<String, Object> coQ = new HashMap<>(); | |||||
| coQ.put("tenantId", tenantId); | |||||
| coQ.put("cUserId", user.getId()); | |||||
| coQ.put("merchantId", merchantId); | |||||
| coQ.put("posOrderId", posOrderId); | |||||
| List<Map> couponOrderList = couponOrderService.findAvailCouponOrder(coQ); | |||||
| retMap.put("coupon_order_list", couponOrderList.toString()); | |||||
| return retMap; | |||||
| } | |||||
| @Override | |||||
| public Map<String, String> couponOrderVerifyDoSomething(@RequestBody Map<String, String> params, EnumVerifyActionType actionType) throws MallinkException { | |||||
| Map<String, String> retMap = new HashMap<>(); | |||||
| String nonceStr = params.get(WxPayConstant.NONCE_STR); // 随机数 | |||||
| String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID | |||||
| String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID | |||||
| String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID | |||||
| String couponOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // 券ID | |||||
| String posOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // POS订单ID | |||||
| if (StringUtils.isBlank(tenantId)) { | |||||
| String errMessage = "request params[tenant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(merchantIdStr)) { | |||||
| String errMessage = "request params[merchant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(buUserIdStr)) { | |||||
| String errMessage = "request params[bu_user_id] error."; | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(couponOrderIdStr)) { | |||||
| String errMessage = "request params[coupon_order_id] error."; | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { | |||||
| if (StringUtils.isBlank(posOrderIdStr)) { | |||||
| String errMessage = "request params[pos_order_id] error."; | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| } | |||||
| Long merchantId, buUserId, couponOrderId, posOrderId = 0L; | |||||
| try { | |||||
| merchantId = Long.valueOf(merchantIdStr); | |||||
| buUserId = Long.valueOf(buUserIdStr); | |||||
| couponOrderId = Long.valueOf(couponOrderIdStr); | |||||
| if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || | |||||
| actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT) || | |||||
| actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { | |||||
| posOrderId = Long.valueOf(posOrderIdStr); | |||||
| } | |||||
| } catch (NumberFormatException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), e.getMessage()); | |||||
| } | |||||
| // 2. check merchant | |||||
| WxMerchant merchant = merchantService.getById(merchantId); | |||||
| if (merchant == null) { | |||||
| logger.error(ErrorCode.MERCHANT_INFO_NOT_FOUND.getMessage() + ": " + merchantIdStr); | |||||
| throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); | |||||
| } | |||||
| if (merchant.getIsDel().equals(EnumDelStatus.DEL.getCode()) || merchant.getStatus().equals(EnumMerchantStatus.NOT_VALID.getCode())) { | |||||
| logger.error(ErrorCode.MERCHANT_INFO_NOT_VALID.getMessage() + ": " + merchantIdStr); | |||||
| throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_VALID); | |||||
| } | |||||
| // 3. check buUser | |||||
| WxMerchantBUser buUser = merchantBUserService.getById(buUserId); | |||||
| if (buUser == null) { | |||||
| logger.error(ErrorCode.USER_IS_EMPTY.getMessage() + ": " + buUserIdStr); | |||||
| throw new MallinkException(ErrorCode.USER_IS_EMPTY); | |||||
| } | |||||
| if (!buUser.getMerchantId().equals(merchantId)) { | |||||
| logger.error(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG.getMessage() + ": " + buUserIdStr); | |||||
| throw new MallinkException(ErrorCode.VERIFY_BUSER_MERCHANT_NOT_BELONG); | |||||
| } | |||||
| // 4. check couponOrderId | |||||
| WxCouponOrderCVo couponOrderCVo = couponOrderService.detailCUserVo(couponOrderIdStr); | |||||
| if (couponOrderCVo == null) { | |||||
| logger.error(ErrorCode.COUPON_ORDER_IS_NULL.getMessage() + ": " + couponOrderIdStr); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL); | |||||
| } | |||||
| // 5. get coupon | |||||
| WxCoupon wxCoupon = couponMapper.selectByPrimaryKey(couponOrderCVo.getCouponId()); | |||||
| if (wxCoupon == null) { | |||||
| logger.error("券: coupon-" + wxCoupon.getId() + "不存在" + "couponOrder-" + couponOrderCVo.getId()); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL); | |||||
| } | |||||
| // 5. 检查有效期 | |||||
| if (couponOrderCVo.getValidStartDate() != null && couponOrderCVo.getValidEndDate() != null) { | |||||
| Date now = new Date(); | |||||
| if (couponOrderCVo.getValidStartDate().getTime() > now.getTime()) { | |||||
| logger.error("此券有效期未开始:" + couponOrderIdStr); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE); | |||||
| } | |||||
| if (couponOrderCVo.getValidEndDate().getTime() < now.getTime()) { | |||||
| logger.error("此券有效期已结束:" + couponOrderIdStr); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE); | |||||
| } | |||||
| } | |||||
| // 6. 检查适用门店 | |||||
| WxCouponMerchant wxCouponMerchant = new WxCouponMerchant(); | |||||
| wxCouponMerchant.setProductId(couponOrderCVo.getCouponId()); | |||||
| wxCouponMerchant.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode()); | |||||
| List<WxCouponMerchant> couponMerchantList = couponMerchantMapper.findList(wxCouponMerchant); | |||||
| if (!couponMerchantList.stream().anyMatch(cm->cm.getMerchantId().equals(merchantId))){ | |||||
| logger.error("券: coupon-" + couponOrderCVo.getCouponId() + "核销: couponMerchantId-" + merchantIdStr + " 门店不适用"); | |||||
| throw new MallinkException(ErrorCode.VERIFY_COUPON_ORDER_MERCHANT_IS_NULL); | |||||
| } | |||||
| // 7. 券包状态检查 | |||||
| if (couponOrderCVo.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_OVER_TIME.getCode()) { | |||||
| logger.error("已过期: couponOrder-" + couponOrderCVo.getId()); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_OVER_TIME); | |||||
| } | |||||
| if (couponOrderCVo.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_INVALID.getCode()) { | |||||
| logger.error("已作废: couponOrder-" + couponOrderCVo.getId()); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_INVALID); | |||||
| } | |||||
| if (couponOrderCVo.getCouponOrderStatus() == EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) { | |||||
| logger.error("已经核销过的券: couponOrder-" + couponOrderCVo.getId()); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_USED); | |||||
| } | |||||
| if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode())) { | |||||
| logger.info("券已被预核销: " + couponOrderIdStr); | |||||
| if (!couponOrderCVo.getBUserId().equals(buUserId)) { | |||||
| logger.error(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL.getMessage() + ": " + buUserIdStr); | |||||
| throw new MallinkException(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL); | |||||
| } | |||||
| if (actionType.equals(EnumVerifyActionType.CHECK)) { | |||||
| if (StringUtils.isBlank(posOrderIdStr)) { | |||||
| logger.error(ErrorCode.VERIFY_PRE_POS_ORDER_IS_EMPTY.getMessage()); | |||||
| throw new MallinkException(ErrorCode.VERIFY_PRE_POS_ORDER_IS_EMPTY); | |||||
| } | |||||
| try { | |||||
| posOrderId = Long.valueOf(posOrderIdStr); | |||||
| } catch (NumberFormatException e) { | |||||
| logger.error("pos_order_id转换异常"); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR.getCode(), | |||||
| ErrorCode.SYS_PARAMETER_CAST_ERROR.getMessage() + ", pos_order_id:" + posOrderIdStr); | |||||
| } | |||||
| } | |||||
| // check pos order是否一致 | |||||
| PosCouponOrderVerify posCouponOrderVerifyQ = new PosCouponOrderVerify(); | |||||
| posCouponOrderVerifyQ.setTenantId(tenantId); | |||||
| posCouponOrderVerifyQ.setCouponOrderId(couponOrderId); | |||||
| posCouponOrderVerifyQ.setPosOrderId(posOrderId); | |||||
| posCouponOrderVerifyQ.setState(EnumEnableType.Enable.getCode()); | |||||
| List<PosCouponOrderVerify> posCouponOrderVerifyList = posCouponOrderVerifyService.getList(posCouponOrderVerifyQ); | |||||
| if (posCouponOrderVerifyList.size() != 1) { | |||||
| logger.error(ErrorCode.VERIFY_PRE_POS_ORDER_NOT_EQUAL.getMessage() + ": " + posOrderIdStr); | |||||
| throw new MallinkException(ErrorCode.VERIFY_PRE_POS_ORDER_NOT_EQUAL); | |||||
| } | |||||
| logger.info("券可以核销: " + couponOrderIdStr); | |||||
| if (actionType.equals(EnumVerifyActionType.CHECK)) { | |||||
| return retMap; | |||||
| } | |||||
| if (actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT) || actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { | |||||
| try { | |||||
| doVerify(couponOrderCVo, wxCoupon, merchantId, buUserId, posOrderId, retMap); | |||||
| return retMap; | |||||
| } catch (MallinkException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.COUPON_ORDER_USE_WAIT.getCode())) { | |||||
| logger.info("券可以核销: " + couponOrderIdStr); | |||||
| if (actionType.equals(EnumVerifyActionType.CHECK)) { | |||||
| return retMap; | |||||
| } | |||||
| if (actionType.equals(EnumVerifyActionType.PRE_VERIFY)) { | |||||
| try { | |||||
| doPreVerify(couponOrderCVo, buUserId, posOrderId); | |||||
| return retMap; | |||||
| } catch (MallinkException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| if (actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT) || actionType.equals(EnumVerifyActionType.VERIFY_PAY)) { | |||||
| try { | |||||
| doVerify(couponOrderCVo, wxCoupon, merchantId, buUserId, posOrderId, retMap); | |||||
| return retMap; | |||||
| } catch (MallinkException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(e.getErrorCode(), e.getMessage()); | |||||
| } catch (Exception e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(500, e.getMessage()); | |||||
| } | |||||
| } | |||||
| } | |||||
| String errMessage = "核销异常:未知的核销状态" + couponOrderCVo.getCouponOrderStatus(); | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(500, errMessage); | |||||
| } | |||||
| @Override | |||||
| public Map<String, String> couponOrderVerifyCancel(Map<String, String> params, EnumVerifyActionType actionType) { | |||||
| Map<String, String> retMap = new HashMap<>(); | |||||
| String nonceStr = params.get(WxPayConstant.NONCE_STR); // 随机数 | |||||
| String tenantId = params.get(WxPayConstant.TENANT_ID); // 租户ID | |||||
| String merchantIdStr = params.get(WxPayConstant.MERCHANT_ID); // 商户ID | |||||
| String buUserIdStr = params.get(WxPayConstant.BUSER_ID); // POS操作员ID | |||||
| String couponOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // 券ID | |||||
| String posOrderIdStr = params.get(WxPayConstant.COUPON_ORDER_ID); // POS订单ID | |||||
| if (StringUtils.isBlank(tenantId)) { | |||||
| String errMessage = "request params[tenant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(merchantIdStr)) { | |||||
| String errMessage = "request params[merchant_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(buUserIdStr)) { | |||||
| String errMessage = "request params[bu_user_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (StringUtils.isBlank(couponOrderIdStr)) { | |||||
| String errMessage = "request params[coupon_order_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| if (actionType.equals(EnumVerifyActionType.PRE_VERIFY) || actionType.equals(EnumVerifyActionType.VERIFY_INDEPENT)) { | |||||
| if (StringUtils.isBlank(posOrderIdStr)) { | |||||
| String errMessage = "request params[pos_order_id] error."; | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), errMessage); | |||||
| } | |||||
| } | |||||
| Long merchantId, buUserId, couponOrderId, posOrderId = 0L; | |||||
| try { | |||||
| merchantId = Long.valueOf(merchantIdStr); | |||||
| buUserId = Long.valueOf(buUserIdStr); | |||||
| couponOrderId = Long.valueOf(couponOrderIdStr); | |||||
| posOrderId = Long.valueOf(posOrderIdStr); | |||||
| } catch (NumberFormatException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.SYS_PARAMETER_CAST_ERROR); | |||||
| } | |||||
| // 2. check merchant | |||||
| WxMerchant merchant = merchantService.getById(merchantId); | |||||
| if (merchant == null) { | |||||
| logger.error(ErrorCode.MERCHANT_INFO_NOT_FOUND.getMessage() + ": " + merchantIdStr); | |||||
| throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); | |||||
| } | |||||
| // 3. check buUser | |||||
| WxMerchantBUser buUser = merchantBUserService.getById(buUserId); | |||||
| if (buUser == null) { | |||||
| logger.error(ErrorCode.USER_IS_EMPTY.getMessage() + ": " + buUserIdStr); | |||||
| throw new MallinkException(ErrorCode.USER_IS_EMPTY); | |||||
| } | |||||
| // 4. check couponOrderId | |||||
| WxCouponOrderCVo couponOrderCVo = couponOrderService.detailCUserVo(couponOrderIdStr); | |||||
| if (couponOrderCVo == null) { | |||||
| logger.error(ErrorCode.COUPON_ORDER_IS_NULL.getMessage() + ": " + couponOrderIdStr); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_NULL); | |||||
| } | |||||
| // 6. 检查适用门店 | |||||
| WxCouponMerchant wxCouponMerchant = new WxCouponMerchant(); | |||||
| wxCouponMerchant.setProductId(couponOrderCVo.getCouponId()); | |||||
| wxCouponMerchant.setStatus(EnumCouponMerchantStatus.COUPON_MERCHANT_STATUS_VALID.getCode()); | |||||
| List<WxCouponMerchant> couponMerchantList = couponMerchantMapper.findList(wxCouponMerchant); | |||||
| if (!couponMerchantList.stream().anyMatch(cm->cm.getMerchantId().equals(merchantId))){ | |||||
| logger.error("券: coupon-" + couponOrderCVo.getCouponId() + "核销: couponMerchantId-" + merchantIdStr + " 门店不适用"); | |||||
| throw new MallinkException(ErrorCode.VERIFY_COUPON_ORDER_MERCHANT_IS_NULL); | |||||
| } | |||||
| WxCouponOrder couponOrder = new WxCouponOrder(); | |||||
| couponOrder.setId(couponOrderCVo.getId()); | |||||
| // 预核销取消 | |||||
| if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()) && | |||||
| actionType.equals(EnumVerifyActionType.PRE_VERIFY_CANCEL)) { | |||||
| logger.info("券已被预核销: " + couponOrderIdStr); | |||||
| if (!couponOrderCVo.getBUserId().equals(buUserId)) { | |||||
| logger.error(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL.getMessage() + ": " + buUserIdStr); | |||||
| throw new MallinkException(ErrorCode.VERIFY_PRE_BUSER_NOT_EQUAL); | |||||
| } | |||||
| try { | |||||
| cancelPreVerify(couponOrderCVo, buUserId, posOrderId); | |||||
| } catch (MallinkException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(e.getErrorCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| // 核销取消 | |||||
| if (couponOrderCVo.getCouponOrderStatus().equals(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()) && | |||||
| actionType.equals(EnumVerifyActionType.VERIFY_CANCEL)) { | |||||
| logger.info("券已被核销: " + couponOrderIdStr); | |||||
| try { | |||||
| cancelVerify(couponOrderCVo, buUserId, posOrderId); | |||||
| } catch (MallinkException e) { | |||||
| logger.error(e.getMessage()); | |||||
| throw new MallinkException(e.getErrorCode(), e.getMessage()); | |||||
| } | |||||
| } | |||||
| String errMessage = "取消异常:未知的核销状态" + couponOrderCVo.getCouponOrderStatus(); | |||||
| logger.error(errMessage); | |||||
| throw new MallinkException(500, errMessage); | |||||
| } | |||||
| /** | |||||
| * 预核销 | |||||
| * @param buUserId | |||||
| * @param couponOrderCVo | |||||
| * @param posOrderId | |||||
| */ | |||||
| @Transactional(rollbackFor = Exception.class) | |||||
| public void doPreVerify(WxCouponOrderCVo couponOrderCVo, Long buUserId, Long posOrderId) { | |||||
| int num = 0; | |||||
| // 1. insert posOrderId | |||||
| PosCouponOrderVerify posCouponOrderVerify = new PosCouponOrderVerify(); | |||||
| posCouponOrderVerify.setTenantId(couponOrderCVo.getTenantId()); | |||||
| posCouponOrderVerify.setCouponOrderId(couponOrderCVo.getId()); | |||||
| posCouponOrderVerify.setPosOrderId(posOrderId); | |||||
| posCouponOrderVerify.setState(EnumEnableType.Enable.getCode()); | |||||
| posCouponOrderVerify.setCreateDate(new Date()); | |||||
| posCouponOrderVerify.setUpdateDate(new Date()); | |||||
| try { | |||||
| posCouponOrderVerifyService.saveOrUpdate(posCouponOrderVerify); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| // 2. update couponOrder | |||||
| try { | |||||
| WxCouponOrder couponOrder = new WxCouponOrder(); | |||||
| couponOrder.setId(couponOrderCVo.getId()); | |||||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()); | |||||
| couponOrder.setBUserId(buUserId); | |||||
| couponOrder.setUpdateDate(new Date()); | |||||
| num = couponOrderMapper.updateVerifyCouponOrder(couponOrder); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| if (num != 1) { | |||||
| logger.error("核销异常:updatete num " + num); | |||||
| throw new MallinkException(ErrorCode.VERIFY_ERROR.getCode(), "updatete num " + num); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 预核销回退 | |||||
| * @param couponOrderCVo | |||||
| * @param buUserId | |||||
| * @param posOrderId | |||||
| */ | |||||
| @Transactional(rollbackFor = Exception.class) | |||||
| public void cancelPreVerify(WxCouponOrderCVo couponOrderCVo, Long buUserId, Long posOrderId) { | |||||
| int num = 0; | |||||
| // 1. update posOrderId | |||||
| PosCouponOrderVerify posCouponOrderVerify = new PosCouponOrderVerify(); | |||||
| posCouponOrderVerify.setTenantId(couponOrderCVo.getTenantId()); | |||||
| posCouponOrderVerify.setCouponOrderId(couponOrderCVo.getId()); | |||||
| posCouponOrderVerify.setPosOrderId(posOrderId); | |||||
| posCouponOrderVerify.setState(EnumEnableType.Enable.getCode()); | |||||
| List<PosCouponOrderVerify> posCouponOrderVerifyList = posCouponOrderVerifyService.getList(posCouponOrderVerify); | |||||
| if (posCouponOrderVerifyList.size() == 1) { | |||||
| try { | |||||
| PosCouponOrderVerify updateOrder = new PosCouponOrderVerify(); | |||||
| updateOrder.setId(posCouponOrderVerify.getId()); | |||||
| updateOrder.setState(EnumEnableType.Disable.getCode()); | |||||
| updateOrder.setUpdateDate(new Date()); | |||||
| posCouponOrderVerifyService.saveOrUpdate(updateOrder); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| logger.error(ErrorCode.VERIFY_PRE_POS_ORDER_NOT_EQUAL.getMessage() + ": " + posOrderId); | |||||
| throw new MallinkException(ErrorCode.VERIFY_PRE_POS_ORDER_NOT_EQUAL); | |||||
| } | |||||
| // 2. update couponOrder | |||||
| try { | |||||
| WxCouponOrder couponOrder = new WxCouponOrder(); | |||||
| couponOrder.setId(couponOrderCVo.getId()); | |||||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USE_WAIT.getCode()); | |||||
| couponOrder.setBUserId(buUserId); | |||||
| couponOrder.setUpdateDate(new Date()); | |||||
| num = couponOrderMapper.updateVerifyCouponOrder(couponOrder); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| if (num != 1) { | |||||
| logger.error("核销异常:updatete num " + num); | |||||
| throw new MallinkException(ErrorCode.VERIFY_ERROR.getCode(), "updatete num " + num); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 核销 | |||||
| * @param couponOrderCVo | |||||
| * @param merchantId | |||||
| * @param buUserId | |||||
| * @param posOrderId | |||||
| */ | |||||
| @Transactional(rollbackFor = Exception.class) | |||||
| public void doVerify(WxCouponOrderCVo couponOrderCVo, WxCoupon coupon, Long merchantId, Long buUserId, Long posOrderId, Map<String, String> retMap) { | |||||
| int num = 0; | |||||
| // 1. insert posOrderId | |||||
| PosCouponOrderVerify posCouponOrderVerify = new PosCouponOrderVerify(); | |||||
| posCouponOrderVerify.setTenantId(couponOrderCVo.getTenantId()); | |||||
| posCouponOrderVerify.setCouponOrderId(couponOrderCVo.getId()); | |||||
| posCouponOrderVerify.setPosOrderId(posOrderId); | |||||
| posCouponOrderVerify.setState(EnumEnableType.Enable.getCode()); | |||||
| List<PosCouponOrderVerify> posCouponOrderVerifyList = posCouponOrderVerifyService.getList(posCouponOrderVerify); | |||||
| if (posCouponOrderVerifyList.size() == 0) { | |||||
| try { | |||||
| posCouponOrderVerifyService.saveOrUpdate(posCouponOrderVerify); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| } else if (posCouponOrderVerifyList.size() == 1){ | |||||
| } else if (posCouponOrderVerifyList.size() > 1){ | |||||
| } | |||||
| // 2. update couponOrder | |||||
| try { | |||||
| WxCouponOrder couponOrder = new WxCouponOrder(); | |||||
| couponOrder.setId(couponOrderCVo.getId()); | |||||
| couponOrder.setTenantId(couponOrderCVo.getTenantId()); | |||||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()); //1核销 | |||||
| couponOrder.setBUserId(buUserId); | |||||
| couponOrder.setUpdateDate(new Date()); | |||||
| num = couponOrderMapper.updateVerifyCouponOrder(couponOrder); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| if (num != 1) { | |||||
| logger.error("核销异常:updatete num " + num); | |||||
| throw new MallinkException(ErrorCode.VERIFY_ERROR.getCode(), "updatete num " + num); | |||||
| } | |||||
| // 3. 成长值 | |||||
| try { | |||||
| WxOrder order = orderMapper.selectByPrimaryKey(couponOrderCVo.getOrderId()); | |||||
| int point = scoreRulesService.addScore2(EnumScoreType.CONSUMPTION, order, couponOrderCVo.getBusinessId()); | |||||
| retMap.put("point", String.valueOf(point)); | |||||
| } catch (Exception e) { | |||||
| logger.error("核销成长值异常:" + e.getMessage()); | |||||
| } | |||||
| // 4. 积分 | |||||
| try { | |||||
| //-------此处为【现金支付】记录增加积分操作------- | |||||
| WxCreditHistory creditHistory = new WxCreditHistory(); | |||||
| creditHistory.setOperatorType(EnumUserType.BUSER.getCode()); | |||||
| creditHistory.setOperatorId(buUserId); | |||||
| creditHistory.setCUserId(couponOrderCVo.getcUserId()); | |||||
| creditHistory.setCreateDate(new Date()); | |||||
| creditHistory.setTenantId(couponOrderCVo.getTenantId()); | |||||
| creditHistory.setCreditType(EnumScoreType.CONSUMPTION.getCode()); | |||||
| creditHistory.setCouponId(couponOrderCVo.getCouponId()); | |||||
| creditHistory.setBusinessId(Long.valueOf(coupon.getBusiness())); | |||||
| creditHistory.setSpend(couponOrderCVo.getCouponPrice()); | |||||
| //如果券与商户一对一 则直接将消费商户更新为此商户 若一对多 则消费商户显示多商户 | |||||
| creditHistory.setMerchantId(merchantId); | |||||
| creditHistory = creditHistoryService.saveOrUpdate(creditHistory); | |||||
| if (creditHistory.getCreditNum() != null) { | |||||
| retMap.put("credit", String.valueOf(creditHistory.getCreditNum())); | |||||
| } | |||||
| } catch (Exception e) { | |||||
| logger.error("核销积分值异常:" + e.getMessage()); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * 核销回退 | |||||
| * @param couponOrderCVo | |||||
| * @param buUserId | |||||
| * @param posOrderId | |||||
| */ | |||||
| @Transactional(rollbackFor = Exception.class) | |||||
| public void cancelVerify(WxCouponOrderCVo couponOrderCVo, Long buUserId, Long posOrderId) { | |||||
| // 1. 积分历史回退 | |||||
| try { | |||||
| WxCreditHistory creditHistory = new WxCreditHistory(); | |||||
| creditHistory.setOperatorType(EnumUserType.BUSER.getCode()); | |||||
| creditHistory.setOperatorId(buUserId); | |||||
| creditHistory.setCUserId(couponOrderCVo.getcUserId()); | |||||
| creditHistory.setTenantId(couponOrderCVo.getTenantId()); | |||||
| creditHistory.setCreditType(EnumScoreType.CONSUMPTION.getCode()); | |||||
| creditHistory.setCouponId(couponOrderCVo.getCouponId()); | |||||
| int num = creditHistoryService.cancelCredit(creditHistory); | |||||
| if (num <= 1) { | |||||
| logger.error("核销积分历史回退失败: " + creditHistory.toString()); | |||||
| return; | |||||
| } | |||||
| } catch (Exception e) { | |||||
| logger.error("核销积分历史回退:" + e.getMessage()); | |||||
| } | |||||
| // 2. 成长值历史回退 | |||||
| try { | |||||
| WxScoreHistory scoreHistory = new WxScoreHistory(); | |||||
| scoreHistory.setTenantId(couponOrderCVo.getTenantId()); | |||||
| scoreHistory.setScoreType(EnumScoreType.CONSUMPTION.getCode()); | |||||
| scoreHistory.setCUserId(couponOrderCVo.getcUserId()); | |||||
| scoreHistory.setOrderId(couponOrderCVo.getOrderId()); | |||||
| int num = scoreRulesService.cancelScore(scoreHistory); | |||||
| if (num <= 1) { | |||||
| logger.error("核销成长值历史回退失败: " + scoreHistory.toString()); | |||||
| return; | |||||
| } | |||||
| } catch (Exception e) { | |||||
| logger.error("核销成长值历史回退:" + e.getMessage()); | |||||
| } | |||||
| // 3. update posOrderId | |||||
| PosCouponOrderVerify posCouponOrderVerify = new PosCouponOrderVerify(); | |||||
| posCouponOrderVerify.setTenantId(couponOrderCVo.getTenantId()); | |||||
| posCouponOrderVerify.setCouponOrderId(couponOrderCVo.getId()); | |||||
| posCouponOrderVerify.setPosOrderId(posOrderId); | |||||
| posCouponOrderVerify.setState(EnumEnableType.Enable.getCode()); | |||||
| List<PosCouponOrderVerify> posCouponOrderVerifyList = posCouponOrderVerifyService.getList(posCouponOrderVerify); | |||||
| if (posCouponOrderVerifyList.size() == 1) { | |||||
| try { | |||||
| PosCouponOrderVerify updateOrder = new PosCouponOrderVerify(); | |||||
| updateOrder.setId(posCouponOrderVerify.getId()); | |||||
| updateOrder.setState(EnumEnableType.Disable.getCode()); | |||||
| updateOrder.setUpdateDate(new Date()); | |||||
| posCouponOrderVerifyService.saveOrUpdate(updateOrder); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| } else { | |||||
| logger.error(ErrorCode.VERIFY_PRE_POS_ORDER_NOT_EQUAL.getMessage() + ": " + posOrderId); | |||||
| throw new MallinkException(ErrorCode.VERIFY_PRE_POS_ORDER_NOT_EQUAL); | |||||
| } | |||||
| // 4. update couponOrder | |||||
| int num = 0; | |||||
| try { | |||||
| WxCouponOrder couponOrder = new WxCouponOrder(); | |||||
| couponOrder.setId(couponOrderCVo.getId()); | |||||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()); //1核销 | |||||
| couponOrder.setBUserId(buUserId); | |||||
| couponOrder.setUpdateDate(new Date()); | |||||
| num = couponOrderMapper.updateVerifyCouponOrder(couponOrder); | |||||
| } catch (Exception e) { | |||||
| logger.error("db failed: couponOrder-" + couponOrderCVo.getId() + ", e:" + e.getMessage()); | |||||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); | |||||
| } | |||||
| if (num != 1) { | |||||
| logger.error("核销异常:updatete num " + num); | |||||
| throw new MallinkException(ErrorCode.VERIFY_ERROR.getCode(), "updatete num " + num); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,116 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # JDBC | |||||
| datasource: | |||||
| url: jdbc:mysql://202.165.179.86:3306/mallinkDevW?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true | |||||
| username: ENC(dZ8fmrtuBMQYaRytKQgTqg==) | |||||
| password: ENC(IKH7HxMZwIqMttMc9+QsqWa1KMsJvTs4) | |||||
| 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 | |||||
| #jackson: | |||||
| #date-format: yyyy-MM-dd HH:mm:ss | |||||
| # REDIS | |||||
| redis: | |||||
| host: 202.165.179.86 | |||||
| port: 6379 | |||||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 1 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 50 | |||||
| max-idle: 30 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(lknBjZsA24AaQEXuy0fFw3acd4v4Xsf3CsgDcRZgjlYnNAL9R07d/w==) | |||||
| password: ENC(gIkVPuYMmJ/EDxry8QIfGumIAk4plAwolGrfg1fiM3U=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| socketFactory: | |||||
| port: 465 | |||||
| class: javax.net.ssl.SSLSocketFactory | |||||
| # ROCKETMQ | |||||
| 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 | |||||
| rabbitmq: | |||||
| host: 202.165.179.86 | |||||
| port: 5672 | |||||
| username: ENC(2f9Nqt3c4cbVGYnhpjp9Mg==) | |||||
| password: ENC(2av0JfMfz141IHkG6ibI8aKzmD33bc64wcN/O43ucbo=) | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) | |||||
| secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) | |||||
| jasypt: | |||||
| encryptor: | |||||
| password: oRqdnDbK5pj3eMmB | |||||
| wechat: | |||||
| open: | |||||
| componentAppId: "wx897e4673286c915d" | |||||
| componentSecret: "cdfdfda65c45689beb6766c4c427eed2" | |||||
| componentToken: "formall2018" | |||||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||||
| redis: | |||||
| host: 202.165.179.86 | |||||
| port: 6379 | |||||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 2 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 100 | |||||
| max-idle: 500 | |||||
| max-wait: -1 | |||||
| min-idle: 10 | |||||
| fm: | |||||
| exception: false | |||||
| exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com | |||||
| deploy: 1 | |||||
| open: true | |||||
| upload_dir: /home/test/server/uploads | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall.mapper: debug | |||||
| path: ./logs/b | |||||
| @@ -0,0 +1,100 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # 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&useAffectedRows=true | |||||
| 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 | |||||
| # 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: 100 | |||||
| max-idle: 20 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(IiL/PHP9wCkpibWHRH/Mts8K9fh4izYqaiaF66bDrqtEHP+KUcJRRg==) | |||||
| password: ENC(m7L57m8mk6tApVoa4XIDQnXF0VxnYjKe4LVdzcgb+xY=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| socketFactory: | |||||
| port: 465 | |||||
| class: javax.net.ssl.SSLSocketFactory | |||||
| # RABBITMQ | |||||
| rabbitmq: | |||||
| host: localhost | |||||
| port: 5672 | |||||
| username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) | |||||
| password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) | |||||
| secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) | |||||
| wechat: | |||||
| open: | |||||
| componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) | |||||
| componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) | |||||
| componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) | |||||
| componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) | |||||
| redis: | |||||
| host: 127.0.0.1 | |||||
| port: 6379 | |||||
| password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 2 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 100 | |||||
| max-idle: 100 | |||||
| max-wait: -1 | |||||
| min-idle: 10 | |||||
| fm: | |||||
| exception: true | |||||
| exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com | |||||
| deploy: 3 | |||||
| open: true | |||||
| upload_dir: /home/ec2-user/server/uploads/ | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall.mapper: debug | |||||
| path: ./logs/b | |||||
| @@ -0,0 +1,100 @@ | |||||
| spring: | |||||
| profiles: | |||||
| include: rabbitMQ | |||||
| # 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&useAffectedRows=true | |||||
| 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 | |||||
| # 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: 50 | |||||
| max-idle: 30 | |||||
| max-wait: -1 | |||||
| min-idle: 0 | |||||
| mail: | |||||
| host: smtp.exmail.qq.com | |||||
| username: ENC(TtJQE2C4cWo8CpVGMMl5hiy5eykepd96J5XjsW3Kj5fgP+6+5ctDNQ==) | |||||
| password: ENC(Zh6A6kRtA2ABtH6nzdvsqQSO1/8p3mparJr8neI2BLU=) # 授权密码 | |||||
| properties: | |||||
| mail: | |||||
| smtp: | |||||
| auth: true | |||||
| starttls: | |||||
| enable: true | |||||
| socketFactory: | |||||
| port: 465 | |||||
| class: javax.net.ssl.SSLSocketFactory | |||||
| # RABBITMQ | |||||
| rabbitmq: | |||||
| host: 127.0.0.1 | |||||
| port: 5672 | |||||
| username: ENC(aSRr6mnSryEqzHHz1hJf1g==) | |||||
| password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=) | |||||
| publisher-confirms: true | |||||
| virtual-host: / | |||||
| aws: | |||||
| clientRegion: cn-northwest-1 | |||||
| bucketName: iformall-net | |||||
| access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) | |||||
| secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) | |||||
| wechat: | |||||
| open: | |||||
| componentAppId: ENC(hnH31XdNzArfMfikKgBFpqQuJUl6rVOPFFcAVyb595o=) | |||||
| componentSecret: ENC(t/GUVX5L+U7LCwSvZ5WmxAnmTMrc/Uy1nljsrokuzzsBL2j6BEVnrS/n7DCdGc/G) | |||||
| componentToken: ENC(gUF1m0YgCCI2IY54fX6sGLZVlCswA8tG) | |||||
| componentAesKey: ENC(TYHcrIkICtfrCfGq4HW6s1b/pHf7OD2uyPN11SzJNB0acqJ/4JVX1nuljo/cAtgMG4O05TImLQc=) | |||||
| redis: | |||||
| host: 127.0.0.1 | |||||
| port: 6379 | |||||
| password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) | |||||
| timeout: 3600 | |||||
| expire: 1800 #30分钟 | |||||
| database: 2 | |||||
| defaultExpiration: 2592000 # 默认生命周期30天 | |||||
| jedis: | |||||
| pool: | |||||
| max-active: 100 | |||||
| max-idle: 100 | |||||
| max-wait: -1 | |||||
| min-idle: 10 | |||||
| fm: | |||||
| exception: true | |||||
| exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com | |||||
| deploy: 2 | |||||
| open: true | |||||
| upload_dir: /home/ec2-user/server/uploads/ | |||||
| logging: | |||||
| level: | |||||
| tk.mybatis: debug | |||||
| com.iformall: debug | |||||
| path: ./logs/b | |||||
| @@ -0,0 +1,52 @@ | |||||
| server: | |||||
| port: 4000 | |||||
| servlet: | |||||
| context-path: /POS | |||||
| 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 | |||||
| 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 | |||||
| #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 | |||||
| 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.SSS}] [%-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.SSS}] [%-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.SSS}] [%-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.SSS}] [%-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.SSS}] [%-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.SSS}] [%-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> | |||||
| @@ -0,0 +1,176 @@ | |||||
| package com.iformall.pos.test; | |||||
| import com.alibaba.fastjson.JSONObject; | |||||
| import com.fasterxml.jackson.databind.ObjectMapper; | |||||
| import com.iformall.PosApplication; | |||||
| import com.iformall.pay.WxPayConstant; | |||||
| import com.iformall.pay.WxPayment; | |||||
| import org.junit.Assert; | |||||
| import org.junit.Test; | |||||
| import org.junit.runner.RunWith; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | |||||
| import org.springframework.boot.test.context.SpringBootTest; | |||||
| import org.springframework.http.MediaType; | |||||
| import org.springframework.test.context.ActiveProfiles; | |||||
| import org.springframework.test.context.junit4.SpringRunner; | |||||
| import org.springframework.test.web.servlet.MockMvc; | |||||
| import org.springframework.test.web.servlet.MvcResult; | |||||
| import org.springframework.test.web.servlet.RequestBuilder; | |||||
| import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | |||||
| import org.springframework.test.web.servlet.result.MockMvcResultHandlers; | |||||
| import org.springframework.test.web.servlet.result.MockMvcResultMatchers; | |||||
| import java.util.HashMap; | |||||
| import java.util.Map; | |||||
| /** | |||||
| * | |||||
| * @author Stormeye | |||||
| * | |||||
| */ | |||||
| @RunWith(SpringRunner.class) | |||||
| @SpringBootTest(classes = { PosApplication.class}) | |||||
| @ActiveProfiles("dev") | |||||
| @AutoConfigureMockMvc | |||||
| public class PosAppTest { | |||||
| @Autowired | |||||
| private MockMvc mockMvc; | |||||
| private static final String devId = "fmpos"; | |||||
| private static final String devReqKey = "ZiGFLC4@3c5sTLZT"; | |||||
| private static final String devResKey = "ugPAM7wd&%p6I0W8"; | |||||
| private static final String tenantId = "456"; | |||||
| @Test | |||||
| public void versionTest() throws Exception { | |||||
| // 1. version test | |||||
| this.mockMvc | |||||
| .perform(MockMvcRequestBuilders.get("/version")) | |||||
| .andExpect(MockMvcResultMatchers.status().isOk()) | |||||
| .andExpect(MockMvcResultMatchers.content().string("{\"code\":200,\"message\":\"success\",\"data\":\"1.0\"}")) | |||||
| .andDo(MockMvcResultHandlers.print()); | |||||
| } | |||||
| @Test | |||||
| public void signErrorTest() throws Exception { | |||||
| Map<String, String> reqObj = new HashMap<>(); | |||||
| reqObj.put(WxPayConstant.DEV_ID, ""); | |||||
| reqObj.put(WxPayConstant.TENANT_ID, "456"); | |||||
| reqObj.put(WxPayConstant.MERCHANT_ID, "456"); | |||||
| reqObj.put(WxPayConstant.BUSER_ID, ""); | |||||
| reqObj.put(WxPayConstant.COUPON_ORDER_ID, ""); | |||||
| reqObj.put(WxPayConstant.NONCE_STR, ""); | |||||
| reqObj.put(WxPayConstant.POS_ORDER_ID, ""); | |||||
| reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); | |||||
| String reqJsonStr = JSONObject.toJSONString(reqObj); | |||||
| this.mockMvc.perform(MockMvcRequestBuilders.post("/checkCouponOrderForVerify") | |||||
| .contentType(MediaType.APPLICATION_JSON) | |||||
| .content(reqJsonStr) | |||||
| ) | |||||
| .andExpect(MockMvcResultMatchers.status().isOk()) | |||||
| .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8)) | |||||
| .andExpect(MockMvcResultMatchers.jsonPath("$.return_code").value("FAIL")) | |||||
| .andDo(MockMvcResultHandlers.print()); | |||||
| } | |||||
| @Test | |||||
| public void getQrCodeTest() throws Exception { | |||||
| Map<String, String> reqObj = new HashMap<>(); | |||||
| reqObj.put(WxPayConstant.DEV_ID, devId); | |||||
| reqObj.put(WxPayConstant.TENANT_ID, tenantId); | |||||
| reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); | |||||
| String reqJsonStr = JSONObject.toJSONString(reqObj); | |||||
| RequestBuilder request = MockMvcRequestBuilders.post("/getQrCode") | |||||
| .contentType(MediaType.APPLICATION_JSON) | |||||
| .content(reqJsonStr); | |||||
| MvcResult result = mockMvc.perform(request).andReturn(); | |||||
| String responseStr = result.getResponse().getContentAsString(); | |||||
| System.out.println(responseStr); | |||||
| ObjectMapper mapper = new ObjectMapper(); | |||||
| Map<String,String> respMap = mapper.readValue(responseStr, Map.class); | |||||
| boolean resSigned = WxPayment.verifyNotifyHMAC(respMap, devResKey); | |||||
| System.out.println("response sign: " + resSigned); | |||||
| Assert.assertEquals(resSigned, true); | |||||
| } | |||||
| @Test | |||||
| public void getMemTest() throws Exception { | |||||
| Map<String, String> reqObj = new HashMap<>(); | |||||
| reqObj.put(WxPayConstant.DEV_ID, devId); | |||||
| reqObj.put(WxPayConstant.TENANT_ID, tenantId); | |||||
| reqObj.put(WxPayConstant.MERCHANT_ID, "317109453987631104"); | |||||
| // reqObj.put(WxPayConstant.MEM_ID, "318314000718200832"); | |||||
| reqObj.put(WxPayConstant.MEM_PHONE, "13910154397"); | |||||
| reqObj.put(WxPayConstant.POS_ORDER_ID, "1"); | |||||
| reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); | |||||
| String reqJsonStr = JSONObject.toJSONString(reqObj); | |||||
| RequestBuilder request = MockMvcRequestBuilders.post("/checkMem") | |||||
| .contentType(MediaType.APPLICATION_JSON) | |||||
| .content(reqJsonStr); | |||||
| MvcResult result = mockMvc.perform(request).andReturn(); | |||||
| String responseStr = result.getResponse().getContentAsString(); | |||||
| System.out.println(responseStr); | |||||
| ObjectMapper mapper = new ObjectMapper(); | |||||
| Map<String,String> respMap = mapper.readValue(responseStr, Map.class); | |||||
| boolean resSigned = WxPayment.verifyNotifyHMAC(respMap, devResKey); | |||||
| System.out.println("response sign: " + resSigned); | |||||
| Assert.assertEquals(resSigned, true); | |||||
| } | |||||
| @Test | |||||
| public void checkCouponOrderForVerifyTest() throws Exception { | |||||
| Map<String, String> reqObj = new HashMap<>(); | |||||
| reqObj.put(WxPayConstant.DEV_ID, devId); | |||||
| reqObj.put(WxPayConstant.TENANT_ID, "456"); | |||||
| reqObj.put(WxPayConstant.MERCHANT_ID, "317109453987631104"); | |||||
| reqObj.put(WxPayConstant.BUSER_ID, "317111133332426752"); | |||||
| reqObj.put(WxPayConstant.COUPON_ORDER_ID, "318978990426783744"); | |||||
| reqObj.put(WxPayConstant.NONCE_STR, "1"); | |||||
| reqObj.put(WxPayConstant.POS_ORDER_ID, "1"); | |||||
| reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); | |||||
| String reqJsonStr = JSONObject.toJSONString(reqObj); | |||||
| RequestBuilder request = MockMvcRequestBuilders.post("/checkCouponOrderForVerify") | |||||
| .contentType(MediaType.APPLICATION_JSON) | |||||
| .content(reqJsonStr); | |||||
| MvcResult result = mockMvc.perform(request).andReturn(); | |||||
| String responseStr = result.getResponse().getContentAsString(); | |||||
| System.out.println(responseStr); | |||||
| ObjectMapper mapper = new ObjectMapper(); | |||||
| Map<String,String> respMap = mapper.readValue(responseStr, Map.class); | |||||
| boolean resSigned = WxPayment.verifyNotifyHMAC(respMap, devResKey); | |||||
| System.out.println("response sign: " + resSigned); | |||||
| Assert.assertEquals(resSigned, true); | |||||
| } | |||||
| @Test | |||||
| public void couponOrderIndependForVerifyTest() throws Exception { | |||||
| Map<String, String> reqObj = new HashMap<>(); | |||||
| reqObj.put(WxPayConstant.DEV_ID, devId); | |||||
| reqObj.put(WxPayConstant.TENANT_ID, "456"); | |||||
| reqObj.put(WxPayConstant.MERCHANT_ID, "317109453987631104"); | |||||
| reqObj.put(WxPayConstant.BUSER_ID, "317111133332426752"); | |||||
| reqObj.put(WxPayConstant.COUPON_ORDER_ID, "318978990426783744"); | |||||
| reqObj.put(WxPayConstant.NONCE_STR, "1"); | |||||
| reqObj.put(WxPayConstant.POS_ORDER_ID, "1"); | |||||
| reqObj.put(WxPayConstant.SIGN, WxPayment.createSignHMAC(reqObj, devReqKey)); | |||||
| String reqJsonStr = JSONObject.toJSONString(reqObj); | |||||
| RequestBuilder request = MockMvcRequestBuilders.post("/couponOrderIndependentVerify") | |||||
| .contentType(MediaType.APPLICATION_JSON) | |||||
| .content(reqJsonStr); | |||||
| MvcResult result = mockMvc.perform(request).andReturn(); | |||||
| String responseStr = result.getResponse().getContentAsString(); | |||||
| System.out.println(responseStr); | |||||
| ObjectMapper mapper = new ObjectMapper(); | |||||
| Map<String,String> respMap = mapper.readValue(responseStr, Map.class); | |||||
| boolean resSigned = WxPayment.verifyNotifyHMAC(respMap, devResKey); | |||||
| System.out.println("response sign: " + resSigned); | |||||
| Assert.assertEquals(resSigned, true); | |||||
| } | |||||
| } | |||||
| @@ -52,6 +52,15 @@ public enum ErrorCode{ | |||||
| NET_TOKEN_INVALID(1052, "TOKEN无效"), | NET_TOKEN_INVALID(1052, "TOKEN无效"), | ||||
| NET_TOKEN_EMPTY(1053, "TOKEN不能为空"), | NET_TOKEN_EMPTY(1053, "TOKEN不能为空"), | ||||
| /** | |||||
| * 第三方开发者 | |||||
| */ | |||||
| DEV_ID_NOT_FOUND(1200, "未知的第三方开发者"), | |||||
| DEV_ID_IS_DISABLED(1201, "第三方开发者已被禁用"), | |||||
| DEV_ID_REQ_KEY_IS_NULL(1202, "开发者request key未设置"), | |||||
| DEV_ID_RES_KEY_IS_NULL(1203, "开发者response Key未设置"), | |||||
| DEV_ID_SIGN_ERR(1204, "开发者签名错误"), | |||||
| /** | /** | ||||
| * 业务级别 | * 业务级别 | ||||
| @@ -179,6 +188,7 @@ public enum ErrorCode{ | |||||
| COUPON_ORDER_MERANT_IS_NULL(4005, "卡券商户不存在"), | COUPON_ORDER_MERANT_IS_NULL(4005, "卡券商户不存在"), | ||||
| COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE(4006, "卡券使用期还未开始"), | COUPON_ORDER_IS_EARLIER_THAN_VALIDDATE(4006, "卡券使用期还未开始"), | ||||
| COUPON_ORDER_IS_LATER_THAN_VALIDDATE(4007, "卡券使用期已结束"), | COUPON_ORDER_IS_LATER_THAN_VALIDDATE(4007, "卡券使用期已结束"), | ||||
| COUPON_ORDER_IS_PRE_VERIFY(4008, "卡券已被预核销"), | |||||
| /** | /** | ||||
| * 卡 | * 卡 | ||||
| @@ -267,9 +277,14 @@ public enum ErrorCode{ | |||||
| * 核销 | * 核销 | ||||
| */ | */ | ||||
| VERIFY_ERROR(12050, "核销异常"), | VERIFY_ERROR(12050, "核销异常"), | ||||
| VERIFY_PRE_BUSER_NOT_EQUAL(12051, "预核销操作员不一致,请先取消上次预核销"), | |||||
| VERIFY_PRE_POS_ORDER_IS_EMPTY(12052, "预核销POS订单ID为空"), | |||||
| VERIFY_PRE_POS_ORDER_NOT_EQUAL(12053, "预核销POS订单不一致,请先取消上次预核销"), | |||||
| VERIFY_BUSER_MERCHANT_NOT_BELONG(12054, "核销员不属于此商户"), | |||||
| MSG_REPEAT_SEND(12061, "短信重复发送"), | MSG_REPEAT_SEND(12061, "短信重复发送"), | ||||
| VERIFY_COUPON_ORDER_MERCHANT_IS_NULL(12062, "卡券核销失败,请查看适用门店"), | VERIFY_COUPON_ORDER_MERCHANT_IS_NULL(12062, "卡券核销失败,请查看适用门店"), | ||||
| /** | /** | ||||
| * 解单 | * 解单 | ||||
| */ | */ | ||||
| @@ -0,0 +1,37 @@ | |||||
| package com.iformall.domain.po; | |||||
| import lombok.Data; | |||||
| import lombok.EqualsAndHashCode; | |||||
| import javax.persistence.*; | |||||
| import javax.persistence.Transient; | |||||
| import java.util.Date; | |||||
| import java.util.List; | |||||
| import javax.persistence.Id; | |||||
| @Table(name = "pos_coupon_order_verify") | |||||
| @Data | |||||
| @EqualsAndHashCode(callSuper = true) | |||||
| public class PosCouponOrderVerify extends BaseEntity { | |||||
| @Id | |||||
| protected Long id; | |||||
| @Transient | |||||
| protected List<Long> ids; | |||||
| @io.swagger.annotations.ApiModelProperty(value="租户ID",name="tenantId") | |||||
| private String tenantId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="券包ID",name="couponOrderId") | |||||
| private Long couponOrderId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="POS订单ID",name="posOrderId") | |||||
| private Long posOrderId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="状态,0-使用中,1-禁用",name="state") | |||||
| private Integer state; | |||||
| @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") | |||||
| private Date createDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate") | |||||
| private Date updateDate; | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| package com.iformall.domain.po; | |||||
| import lombok.Data; | |||||
| import javax.persistence.*; | |||||
| import java.util.*; | |||||
| import javax.persistence.Transient; | |||||
| import java.util.List; | |||||
| import javax.persistence.Id; | |||||
| @Table(name = "th_dev_info") | |||||
| @Data | |||||
| public class ThDevInfo extends BaseEntity { | |||||
| @Id | |||||
| protected Long id; | |||||
| @Transient | |||||
| protected List<Long> ids; | |||||
| @io.swagger.annotations.ApiModelProperty(value="开发者ID",name="devId") | |||||
| private String devId; | |||||
| @io.swagger.annotations.ApiModelProperty(value="名称",name="name") | |||||
| private String name; | |||||
| @io.swagger.annotations.ApiModelProperty(value="类型(0:自用, 1:东软POS)",name="type") | |||||
| private Integer type; | |||||
| @io.swagger.annotations.ApiModelProperty(value="请求私钥",name="reqKey") | |||||
| private String reqKey; | |||||
| @io.swagger.annotations.ApiModelProperty(value="响应私钥",name="resKey") | |||||
| private String resKey; | |||||
| @io.swagger.annotations.ApiModelProperty(value="商户状态,0-使用中,1-禁用",name="state") | |||||
| private Integer state; | |||||
| @io.swagger.annotations.ApiModelProperty(value="创建时间",name="createDate") | |||||
| private Date createDate; | |||||
| @io.swagger.annotations.ApiModelProperty(value="更新时间",name="updateDate") | |||||
| private Date updateDate; | |||||
| } | |||||
| @@ -39,7 +39,7 @@ public class WxCouponOrder extends BaseEntity{ | |||||
| private Long orderId; | private Long orderId; | ||||
| @io.swagger.annotations.ApiModelProperty(value = "该订单对应券的实际过期时间 ", name = "expiredTime") | @io.swagger.annotations.ApiModelProperty(value = "该订单对应券的实际过期时间 ", name = "expiredTime") | ||||
| private Date expiredTime; | private Date expiredTime; | ||||
| @io.swagger.annotations.ApiModelProperty(value = "状态:0-待使用 1-已核销 2-已过期 3-已作废 4-卡使用中 5-卡已过期 6-卡已用完 7-卡已线下退款", name = "couponOrderStatus") | |||||
| @io.swagger.annotations.ApiModelProperty(value = "状态:0-待使用 1-已核销 2-已过期 3-已作废 4-卡使用中 5-卡已过期 6-卡已用完 7-卡已线下退款 100-预核销", name = "couponOrderStatus") | |||||
| private Integer couponOrderStatus; | private Integer couponOrderStatus; | ||||
| @io.swagger.annotations.ApiModelProperty(value = "创建时间", name = "createDate") | @io.swagger.annotations.ApiModelProperty(value = "创建时间", name = "createDate") | ||||
| private Date createDate; | private Date createDate; | ||||
| @@ -32,7 +32,7 @@ public class WxLevelMerchantCVo implements Serializable { | |||||
| @io.swagger.annotations.ApiModelProperty(value = "店铺列表", name = "shopVoList") | @io.swagger.annotations.ApiModelProperty(value = "店铺列表", name = "shopVoList") | ||||
| private List<WxShopVo> shopVoList; | private List<WxShopVo> shopVoList; | ||||
| @io.swagger.annotations.ApiModelProperty(value="折扣",name="discount") | |||||
| @io.swagger.annotations.ApiModelProperty(value="折扣(0-100折扣)",name="discount") | |||||
| private Integer discount; | private Integer discount; | ||||
| @Transient | @Transient | ||||
| @@ -16,7 +16,9 @@ public enum EnumCouponOrderStatus { | |||||
| CARD_OVER_TIME(5, "已过期"), | CARD_OVER_TIME(5, "已过期"), | ||||
| CARD_COMPLETE(6, "已用完"), | CARD_COMPLETE(6, "已用完"), | ||||
| CARD_RETURNED(7, "已线下退款"), | CARD_RETURNED(7, "已线下退款"), | ||||
| CARD_TRANSFER(8, "已转赠") /// 此状态不在wx_coupon_order中使用,已移到transfer表 | |||||
| CARD_TRANSFER(8, "已转赠"), /// 此状态不在wx_coupon_order中使用,已移到transfer表 | |||||
| POS_PRE_VERIFY(100, "POS预核销"), // POS设置状态 | |||||
| ; | ; | ||||
| public static EnumCouponOrderStatus getEnum(Integer code) { | public static EnumCouponOrderStatus getEnum(Integer code) { | ||||
| @@ -0,0 +1,42 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum EnumVerifyActionType { | |||||
| // 0: 检查, 1: 预核销 2: 预核销撤销 3:独立核销 4: 交易核销 5:核销撤销 | |||||
| CHECK(0, "检查"), | |||||
| PRE_VERIFY(1, "预核销"), | |||||
| PRE_VERIFY_CANCEL(2, "预核销撤销"), | |||||
| VERIFY_INDEPENT(3,"独立核销"), | |||||
| VERIFY_PAY(4,"交易核销"), | |||||
| VERIFY_CANCEL(5,"核销撤销") | |||||
| ; | |||||
| public static EnumVerifyActionType getEnum(Integer code) { | |||||
| for (EnumVerifyActionType value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumVerifyActionType(Integer code, String message) { | |||||
| this.code = code; | |||||
| this.message = message; | |||||
| } | |||||
| public Integer getCode() { | |||||
| return code; | |||||
| } | |||||
| public String getMessage() { | |||||
| return message; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,36 @@ | |||||
| package com.iformall.enums; | |||||
| /** | |||||
| * Created by Stormeye on 2018/08/09. | |||||
| */ | |||||
| public enum EnumVerifyType { | |||||
| YES(1, "是"), | |||||
| NO(0, "否") | |||||
| ; | |||||
| public static EnumVerifyType getEnum(Integer code) { | |||||
| for (EnumVerifyType value : values()) { | |||||
| if (value.getCode().equals(code)) { | |||||
| return value; | |||||
| } | |||||
| } | |||||
| return null; | |||||
| } | |||||
| private Integer code; | |||||
| private String message; | |||||
| EnumVerifyType(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 java.util.*; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import org.apache.ibatis.annotations.Param; | |||||
| import com.iformall.domain.po.PosCouponOrderVerify; | |||||
| public interface PosCouponOrderVerifyMapper extends CommonMapper<PosCouponOrderVerify, Long> { | |||||
| List<PosCouponOrderVerify> findList(PosCouponOrderVerify posCouponOrderVerify); | |||||
| } | |||||
| @@ -0,0 +1,17 @@ | |||||
| package com.iformall.mapper; | |||||
| import java.util.*; | |||||
| import com.iformall.common.CommonMapper; | |||||
| import org.apache.ibatis.annotations.Param; | |||||
| import com.iformall.domain.po.ThDevInfo; | |||||
| public interface ThDevInfoMapper extends CommonMapper<ThDevInfo, Long> { | |||||
| List<ThDevInfo> findList(ThDevInfo thDevInfo); | |||||
| } | |||||
| @@ -69,4 +69,8 @@ public interface WxCouponOrderMapper extends CommonMapper<WxCouponOrder, Long> { | |||||
| //// 卡相关接口 | //// 卡相关接口 | ||||
| List<WxCardCVo> findCardListOfCUser(WxCardCVo wxCardCVo); | List<WxCardCVo> findCardListOfCUser(WxCardCVo wxCardCVo); | ||||
| WxCardCVo findCardDetailOfCUser(@Param("id")Long id); | WxCardCVo findCardDetailOfCUser(@Param("id")Long id); | ||||
| /// POS接口 | |||||
| List<Map> findAvailCouponOrder(Map<String,Object> params); | |||||
| } | } | ||||
| @@ -0,0 +1,28 @@ | |||||
| package com.iformall.pay; | |||||
| public class WxPayConstant { | |||||
| public final static String REQ_KEY = "reqKey"; | |||||
| public final static String RES_KEY = "resKey"; | |||||
| public final static String RET_SUCCESS = "SUCCESS"; | |||||
| public final static String RET_FAIL = "FAIL"; | |||||
| public final static String RETURN_CODE = "return_code"; | |||||
| public final static String RETURN_MSG = "return_msg"; | |||||
| public final static String RESULT_CODE = "result_code"; | |||||
| public final static String ERR_CODE = "err_code"; | |||||
| public final static String ERR_CODE_DESC = "err_code_des"; | |||||
| public final static String NONCE_STR = "nonce_str"; | |||||
| public final static String DEV_ID = "dev_id"; | |||||
| public final static String SIGN = "sign"; | |||||
| public final static String TENANT_ID = "tenant_id"; | |||||
| public final static String MERCHANT_ID = "merchant_id"; | |||||
| public final static String BUSER_ID = "bu_user_id"; | |||||
| public final static String COUPON_ORDER_ID = "coupon_order_id"; | |||||
| public final static String POS_ORDER_ID = "pos_order_id"; | |||||
| public final static String MEM_ID = "mem_id"; | |||||
| public final static String MEM_PHONE = "mem_phone"; | |||||
| } | |||||
| @@ -14,6 +14,7 @@ import java.util.Map.Entry; | |||||
| import java.util.TreeMap; | import java.util.TreeMap; | ||||
| public class WxPayment { | public class WxPayment { | ||||
| /** | /** | ||||
| * 构建参数 | * 构建参数 | ||||
| * | * | ||||
| @@ -386,6 +387,20 @@ public class WxPayment { | |||||
| return params; | return params; | ||||
| } | } | ||||
| /** | |||||
| * 构建签名之后的参数 | |||||
| * | |||||
| * @param params | |||||
| * @param paternerKey | |||||
| * @return Map | |||||
| */ | |||||
| public static Map<String, String> buildSignAfterParasMapForHMAC(Map<String, String> params, String paternerKey) { | |||||
| params.put("nonce_str", Utility.generateUUID().replace("-", "")); | |||||
| String sign = WxPayment.createSignHMAC(params, paternerKey); | |||||
| params.put("sign", sign); | |||||
| return params; | |||||
| } | |||||
| /** | /** | ||||
| * 生成签名 | * 生成签名 | ||||
| * | * | ||||
| @@ -0,0 +1,57 @@ | |||||
| package com.iformall.service; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.domain.po.PosCouponOrderVerify; | |||||
| import java.util.List; | |||||
| public interface PosCouponOrderVerifyService { | |||||
| /** | |||||
| * 根据实体查询分页列表 | |||||
| * | |||||
| * @param record | |||||
| * @param pageIndex | |||||
| * @param pageSize | |||||
| * @return | |||||
| */ | |||||
| PageInfo<PosCouponOrderVerify> listAsPage(PosCouponOrderVerify record, Integer pageIndex, Integer pageSize); | |||||
| /** | |||||
| * 根据实体查询列表 | |||||
| * | |||||
| * @param record | |||||
| * @return | |||||
| */ | |||||
| List<PosCouponOrderVerify> getList(PosCouponOrderVerify record); | |||||
| /** | |||||
| * 根据Id获得实体 | |||||
| * | |||||
| * @param id | |||||
| * @return | |||||
| */ | |||||
| PosCouponOrderVerify getById(Long id); | |||||
| /** | |||||
| * 保存或更新实体 | |||||
| * | |||||
| * @param record | |||||
| */ | |||||
| void saveOrUpdate(PosCouponOrderVerify record); | |||||
| /** | |||||
| * 根据Id删除实体 | |||||
| * | |||||
| * @param id | |||||
| */ | |||||
| void deleteById(Long id); | |||||
| } | |||||
| @@ -0,0 +1,55 @@ | |||||
| package com.iformall.service; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.domain.po.ThDevInfo; | |||||
| public interface ThDevInfoService { | |||||
| /** | |||||
| * 根据实体查询分页列表 | |||||
| * | |||||
| * @param record | |||||
| * @param pageIndex | |||||
| * @param pageSize | |||||
| * @return | |||||
| */ | |||||
| PageInfo<ThDevInfo> listAsPage(ThDevInfo record, Integer pageIndex, Integer pageSize); | |||||
| /** | |||||
| * 根据Id获得实体 | |||||
| * | |||||
| * @param id | |||||
| * @return | |||||
| */ | |||||
| ThDevInfo getById(Long id); | |||||
| /** | |||||
| * 根据devId获得实体 | |||||
| * | |||||
| * @param devId | |||||
| * @return | |||||
| */ | |||||
| ThDevInfo getByDevId(String devId); | |||||
| /** | |||||
| * 保存或更新实体 | |||||
| * | |||||
| * @param record | |||||
| */ | |||||
| void saveOrUpdate(ThDevInfo record); | |||||
| /** | |||||
| * 根据Id删除实体 | |||||
| * | |||||
| * @param id | |||||
| */ | |||||
| void deleteById(Long id); | |||||
| } | |||||
| @@ -10,6 +10,7 @@ import javax.servlet.http.HttpServletRequest; | |||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
| import java.util.Date; | import java.util.Date; | ||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | |||||
| public interface WxCouponOrderService { | public interface WxCouponOrderService { | ||||
| @@ -189,4 +190,10 @@ public interface WxCouponOrderService { | |||||
| void exportData(WxCouponOrderBVo wxCouponOrder, HttpServletRequest request, HttpServletResponse response); | void exportData(WxCouponOrderBVo wxCouponOrder, HttpServletRequest request, HttpServletResponse response); | ||||
| /** | |||||
| * POS相关接口 | |||||
| */ | |||||
| List<Map> findAvailCouponOrder(Map<String, Object> params); | |||||
| } | } | ||||
| @@ -45,6 +45,13 @@ public interface WxCreditHistoryService { | |||||
| */ | */ | ||||
| WxCreditHistory saveOrUpdate(WxCreditHistory record); | WxCreditHistory saveOrUpdate(WxCreditHistory record); | ||||
| /** | |||||
| * 积分历史回退 | |||||
| * | |||||
| * @param record | |||||
| */ | |||||
| int cancelCredit(WxCreditHistory record); | |||||
| /** | /** | ||||
| * 根据Id删除实体 | * 根据Id删除实体 | ||||
| * | * | ||||
| @@ -1,5 +1,6 @@ | |||||
| package com.iformall.service; | package com.iformall.service; | ||||
| import com.iformall.domain.po.WxScoreHistory; | |||||
| import com.iformall.domain.po.WxScoreRules; | import com.iformall.domain.po.WxScoreRules; | ||||
| import com.iformall.enums.EnumScoreType; | import com.iformall.enums.EnumScoreType; | ||||
| @@ -27,6 +28,13 @@ public interface WxScoreRulesService { | |||||
| */ | */ | ||||
| void saveOrUpdate(WxScoreRules record); | void saveOrUpdate(WxScoreRules record); | ||||
| /** | |||||
| * 成长值回退 | |||||
| * | |||||
| * @param record | |||||
| */ | |||||
| int cancelScore(WxScoreHistory record); | |||||
| /** | /** | ||||
| * 增加成长值 | * 增加成长值 | ||||
| */ | */ | ||||
| @@ -0,0 +1,60 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.github.pagehelper.PageHelper; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.domain.po.PosCouponOrderVerify; | |||||
| import com.iformall.mapper.PosCouponOrderVerifyMapper; | |||||
| import com.iformall.service.PosCouponOrderVerifyService; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.iformall.common.IdWorker; | |||||
| import java.util.List; | |||||
| @Service | |||||
| public class PosCouponOrderVerifyServiceImpl implements PosCouponOrderVerifyService { | |||||
| @Autowired | |||||
| PosCouponOrderVerifyMapper posCouponOrderVerifyMapper; | |||||
| @Override | |||||
| public PageInfo<PosCouponOrderVerify> listAsPage(PosCouponOrderVerify record, Integer pageIndex, Integer pageSize) { | |||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> posCouponOrderVerifyMapper.findList(record)); | |||||
| } | |||||
| @Override | |||||
| public List<PosCouponOrderVerify> getList(PosCouponOrderVerify record) { | |||||
| return posCouponOrderVerifyMapper.findList(record); | |||||
| } | |||||
| @Override | |||||
| public PosCouponOrderVerify getById(Long id) { | |||||
| return posCouponOrderVerifyMapper.selectByPrimaryKey(id); | |||||
| } | |||||
| @Override | |||||
| public void saveOrUpdate(PosCouponOrderVerify record) { | |||||
| if (record.getId() == null) { | |||||
| //record.setId(UUID.randomUUID().toString().replaceAll("-", "")); | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| record.setId(idWorker.nextId()); | |||||
| posCouponOrderVerifyMapper.insertSelective(record); | |||||
| } else { | |||||
| posCouponOrderVerifyMapper.updateByPrimaryKeySelective(record); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void deleteById(Long id) { | |||||
| posCouponOrderVerifyMapper.deleteByPrimaryKey(id); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,69 @@ | |||||
| package com.iformall.service.impl; | |||||
| import com.github.pagehelper.PageHelper; | |||||
| import com.github.pagehelper.PageInfo; | |||||
| import com.iformall.domain.po.ThDevInfo; | |||||
| import com.iformall.mapper.ThDevInfoMapper; | |||||
| import com.iformall.service.ThDevInfoService; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| import org.springframework.beans.factory.annotation.Autowired; | |||||
| import org.springframework.stereotype.Service; | |||||
| import com.iformall.common.IdWorker; | |||||
| @Service | |||||
| public class ThDevInfoServiceImpl implements ThDevInfoService { | |||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | |||||
| ThDevInfoMapper thDevInfoMapper; | |||||
| @Override | |||||
| public PageInfo<ThDevInfo> listAsPage(ThDevInfo record, Integer pageIndex, Integer pageSize) { | |||||
| return PageHelper.startPage(pageIndex, pageSize).doSelectPageInfo(() -> thDevInfoMapper.findList(record)); | |||||
| } | |||||
| @Override | |||||
| public ThDevInfo getById(Long id) { | |||||
| return thDevInfoMapper.selectByPrimaryKey(id); | |||||
| } | |||||
| @Override | |||||
| public ThDevInfo getByDevId(String devId) { | |||||
| ThDevInfo q = new ThDevInfo(); | |||||
| q.setDevId(devId); | |||||
| try { | |||||
| return thDevInfoMapper.selectOne(q); | |||||
| } catch (Exception e) { | |||||
| logger.error(e.getMessage()); | |||||
| } | |||||
| return null; | |||||
| } | |||||
| @Override | |||||
| public void saveOrUpdate(ThDevInfo record) { | |||||
| if (record.getId() == null) { | |||||
| //record.setId(UUID.randomUUID().toString().replaceAll("-", "")); | |||||
| final IdWorker idWorker = IdWorker.get(); | |||||
| record.setId(idWorker.nextId()); | |||||
| thDevInfoMapper.insertSelective(record); | |||||
| } else { | |||||
| thDevInfoMapper.updateByPrimaryKeySelective(record); | |||||
| } | |||||
| } | |||||
| @Override | |||||
| public void deleteById(Long id) { | |||||
| thDevInfoMapper.deleteByPrimaryKey(id); | |||||
| } | |||||
| } | |||||
| @@ -336,6 +336,10 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| logger.error("已经核销过的券: couponOrder-" + couponOrder.getId()); | logger.error("已经核销过的券: couponOrder-" + couponOrder.getId()); | ||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_USED); | throw new MallinkException(ErrorCode.COUPON_ORDER_IS_USED); | ||||
| } | } | ||||
| if (couponOrder.getCouponOrderStatus() == EnumCouponOrderStatus.POS_PRE_VERIFY.getCode()) { | |||||
| logger.error("券已被预核销: couponOrder-" + couponOrder.getId()); | |||||
| throw new MallinkException(ErrorCode.COUPON_ORDER_IS_PRE_VERIFY); | |||||
| } | |||||
| int num = 0; | int num = 0; | ||||
| try { | try { | ||||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()); //1核销 | couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USED.getCode()); //1核销 | ||||
| @@ -975,4 +979,9 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||||
| wxCardTransferInfoMapper.insertSelective(wxCardTransferInfo); | wxCardTransferInfoMapper.insertSelective(wxCardTransferInfo); | ||||
| } | } | ||||
| @Override | |||||
| public List<Map> findAvailCouponOrder(Map<String, Object> params) { | |||||
| return wxCouponOrderMapper.findAvailCouponOrder(params); | |||||
| } | |||||
| } | } | ||||
| @@ -19,6 +19,8 @@ import com.iformall.service.WxScoreRulesService; | |||||
| import com.iformall.utils.RedisLock; | import com.iformall.utils.RedisLock; | ||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
| import org.apache.commons.lang3.StringUtils; | 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.Autowired; | ||||
| import org.springframework.stereotype.Service; | import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Propagation; | import org.springframework.transaction.annotation.Propagation; | ||||
| @@ -35,6 +37,7 @@ import java.util.stream.Collectors; | |||||
| @Service | @Service | ||||
| @Slf4j | @Slf4j | ||||
| public class WxCreditHistoryServiceImpl implements WxCreditHistoryService { | public class WxCreditHistoryServiceImpl implements WxCreditHistoryService { | ||||
| private final Logger logger = LoggerFactory.getLogger(this.getClass()); | |||||
| @Autowired | @Autowired | ||||
| WxCreditHistoryMapper wxCreditHistoryMapper; | WxCreditHistoryMapper wxCreditHistoryMapper; | ||||
| @@ -230,6 +233,45 @@ public class WxCreditHistoryServiceImpl implements WxCreditHistoryService { | |||||
| return record; | return record; | ||||
| } | } | ||||
| @Override | |||||
| @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = {Exception.class}) | |||||
| public int cancelCredit(WxCreditHistory record) { | |||||
| int num = 0; | |||||
| WxCreditHistory wxCreditHistory = null; | |||||
| // 1. clear history | |||||
| List<WxCreditHistory> creditHistories = wxCreditHistoryMapper.findList(record); | |||||
| if (creditHistories.size() >= 1) { | |||||
| wxCreditHistory = creditHistories.get(0); | |||||
| } | |||||
| if (wxCreditHistory != null) { | |||||
| num = wxCreditHistoryMapper.deleteByPrimaryKey(wxCreditHistory.getId()); | |||||
| if (num != 1) { | |||||
| logger.error("删除积分历史出错"+ wxCreditHistory.toString()); | |||||
| } | |||||
| } else { | |||||
| logger.error("未找到积分历史"); | |||||
| return 0; | |||||
| } | |||||
| // 2. user | |||||
| WxCUser wxCUser = wxCUserMapper.selectByPrimaryKey(record.getCUserId()); | |||||
| WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoMapper.selectByPrimaryKey(record.getCUserId()); | |||||
| if (wxCUser != null) { | |||||
| WxCUser wxCUserNew = new WxCUser(); | |||||
| wxCUserNew.setId(wxCUser.getId()); | |||||
| wxCUserNew.setCredit(wxCUser.getCredit()-wxCreditHistory.getCreditNum()); | |||||
| wxCUserNew.setUpdateDate(new Date()); | |||||
| wxCUserMapper.updateByPrimaryKeySelective(wxCUserNew); | |||||
| } | |||||
| if (wxCUserBasicInfo != null) { | |||||
| WxCUserBasicInfo wxCUserBasicInfoNew = new WxCUserBasicInfo(); | |||||
| wxCUserBasicInfoNew.setId(wxCUserBasicInfo.getId()); | |||||
| wxCUserBasicInfoNew.setCredit(wxCUserBasicInfo.getCredit()-wxCreditHistory.getCreditNum()); | |||||
| wxCUserBasicInfoNew.setUpdateDate(new Date()); | |||||
| wxCUserBasicInfoMapper.updateByPrimaryKeySelective(wxCUserBasicInfoNew); | |||||
| } | |||||
| return num; | |||||
| } | |||||
| @Override | @Override | ||||
| public void deleteById(Long id) { | public void deleteById(Long id) { | ||||
| wxCreditHistoryMapper.deleteByPrimaryKey(id); | wxCreditHistoryMapper.deleteByPrimaryKey(id); | ||||
| @@ -185,6 +185,44 @@ public class WxScoreRulesServiceImpl implements WxScoreRulesService { | |||||
| } | } | ||||
| } | } | ||||
| @Override | |||||
| public int cancelScore(WxScoreHistory record) { | |||||
| int num = 0; | |||||
| WxScoreHistory history = null; | |||||
| // 1. delete history | |||||
| List<WxScoreHistory> histories = wxScoreHistoryMapper.findList(record); | |||||
| if (histories.size() >= 1) { | |||||
| history = histories.get(0); | |||||
| } | |||||
| if (history != null) { | |||||
| num = wxScoreHistoryMapper.deleteByPrimaryKey(history.getId()); | |||||
| if (num != 1) { | |||||
| logger.error("删除成长值历史出错"+ history.toString()); | |||||
| } | |||||
| } else { | |||||
| logger.error("未找到成长值历史"); | |||||
| return 0; | |||||
| } | |||||
| // 2. user score back | |||||
| WxCUser wxCUser = wxCUserMapper.selectByPrimaryKey(record.getCUserId()); | |||||
| WxCUserBasicInfo wxCUserBasicInfo = wxCUserBasicInfoMapper.selectByPrimaryKey(record.getCUserId()); | |||||
| if (wxCUser != null) { | |||||
| WxCUser wxCUserNew = new WxCUser(); | |||||
| wxCUserNew.setId(wxCUser.getId()); | |||||
| wxCUserNew.setScore(wxCUser.getScore() - history.getScoreAmount()); | |||||
| wxCUserNew.setUpdateDate(new Date()); | |||||
| wxCUserMapper.updateByPrimaryKeySelective(wxCUserNew); | |||||
| } | |||||
| if (wxCUserBasicInfo != null) { | |||||
| WxCUserBasicInfo wxCUserBasicInfoNew = new WxCUserBasicInfo(); | |||||
| wxCUserBasicInfoNew.setId(wxCUserBasicInfo.getId()); | |||||
| wxCUserBasicInfoNew.setPoins(wxCUserBasicInfo.getPoins()-history.getScoreAmount()); | |||||
| wxCUserBasicInfoNew.setUpdateDate(new Date()); | |||||
| wxCUserBasicInfoMapper.updateByPrimaryKeySelective(wxCUserBasicInfoNew); | |||||
| } | |||||
| return num; | |||||
| } | |||||
| private void updateScore(Long userId, int addedScoreNumber) { | private void updateScore(Long userId, int addedScoreNumber) { | ||||
| // 1. 获取cUser | // 1. 获取cUser | ||||
| WxCUser wxCUser = wxCUserService.getById(userId); | WxCUser wxCUser = wxCUserService.getById(userId); | ||||
| @@ -0,0 +1,54 @@ | |||||
| <?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.PosCouponOrderVerifyMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.PosCouponOrderVerify"> | |||||
| <id column="id" jdbcType="BIGINT" property="id" /> | |||||
| <result column="tenant_id" jdbcType="VARCHAR" property="tenantId" /> | |||||
| <result column="coupon_order_id" jdbcType="BIGINT" property="couponOrderId" /> | |||||
| <result column="pos_order_id" jdbcType="BIGINT" property="posOrderId" /> | |||||
| <result column="state" jdbcType="INTEGER" property="state" /> | |||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate"/> | |||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate"/> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`tenant_id`,`coupon_order_id`,`pos_order_id`,`state` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != tenantId "> | |||||
| and `tenant_id` like concat('%', #{tenantId},'%') | |||||
| </if> | |||||
| <if test=" null != couponOrderId "> | |||||
| and `coupon_order_id` = #{couponOrderId} | |||||
| </if> | |||||
| <if test=" null != posOrderId "> | |||||
| and `pos_order_id` = #{posOrderId} | |||||
| </if> | |||||
| <if test=" null != state "> | |||||
| and `state` = #{state} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns"> order by ${sortColumns} </if> | |||||
| </sql> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.PosCouponOrderVerify" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from pos_coupon_order_verify | |||||
| <include refid="dynamicWhereConditions" /> | |||||
| </select> | |||||
| </mapper> | |||||
| @@ -0,0 +1,68 @@ | |||||
| <?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.ThDevInfoMapper"> | |||||
| <resultMap id="BaseResultMap" type="com.iformall.domain.po.ThDevInfo"> | |||||
| <id column="id" jdbcType="BIGINT" property="id" /> | |||||
| <result column="dev_id" jdbcType="VARCHAR" property="devId" /> | |||||
| <result column="name" jdbcType="VARCHAR" property="name" /> | |||||
| <result column="type" jdbcType="INTEGER" property="type" /> | |||||
| <result column="req_key" jdbcType="VARCHAR" property="reqKey" /> | |||||
| <result column="res_key" jdbcType="VARCHAR" property="resKey" /> | |||||
| <result column="state" jdbcType="INTEGER" property="state" /> | |||||
| <result column="create_date" jdbcType="TIMESTAMP" property="createDate" /> | |||||
| <result column="update_date" jdbcType="TIMESTAMP" property="updateDate" /> | |||||
| </resultMap> | |||||
| <sql id="allColumns"> | |||||
| `id`,`dev_id`,`name`,`type`,`req_key`,`res_key`,`state`,`create_date`,`update_date` | |||||
| </sql> | |||||
| <sql id="dynamicWhereConditions"> | |||||
| where 1 = 1 | |||||
| <if test=" null != id "> | |||||
| and `id` = #{id} | |||||
| </if> | |||||
| <if test=" null != devId "> | |||||
| and `dev_id` like concat('%', #{devId},'%') | |||||
| </if> | |||||
| <if test=" null != name "> | |||||
| and `name` like concat('%', #{name},'%') | |||||
| </if> | |||||
| <if test=" null != type "> | |||||
| and `type` = #{type} | |||||
| </if> | |||||
| <if test=" null != reqKey "> | |||||
| and `req_key` like concat('%', #{reqKey},'%') | |||||
| </if> | |||||
| <if test=" null != resKey "> | |||||
| and `res_key` like concat('%', #{resKey},'%') | |||||
| </if> | |||||
| <if test=" null != state "> | |||||
| and `state` = #{state} | |||||
| </if> | |||||
| <if test=" null != createDate "> | |||||
| and `create_date` = #{createDate} | |||||
| </if> | |||||
| <if test=" null != updateDate "> | |||||
| and `update_date` = #{updateDate} | |||||
| </if> | |||||
| <if test=" null != ids "> | |||||
| and id in | |||||
| <foreach collection="ids" index="index" item="idItem" open="(" separator="," close=")"> | |||||
| #{idItem} | |||||
| </foreach> | |||||
| </if> | |||||
| <if test=" null != sortColumns"> order by ${sortColumns} </if> | |||||
| </sql> | |||||
| <select id="findList" parameterType="com.iformall.domain.po.ThDevInfo" resultMap="BaseResultMap"> | |||||
| select <include refid="allColumns" /> from th_dev_info | |||||
| <include refid="dynamicWhereConditions" /> | |||||
| </select> | |||||
| </mapper> | |||||
| @@ -1018,4 +1018,28 @@ | |||||
| and co.id = #{id} | and co.id = #{id} | ||||
| </select> | </select> | ||||
| <select id="findAvailCouponOrder" parameterType="java.util.Map" resultType="hashmap"> | |||||
| select co.id,c.title, co.create_date, co.expired_time, c.price | |||||
| from wx_coupon_order co | |||||
| left join wx_coupon_merchant cm on cm.product_id = co.coupon_id | |||||
| left join wx_coupon c on c.id = co.coupon_id | |||||
| where co.tenant_id = #{tenantId} and co.c_user_id = #{cUserId} | |||||
| and co.coupon_order_status = 0 | |||||
| and cm.merchant_id = #{merchantId} | |||||
| and co.expired_time > now() | |||||
| union | |||||
| select co.id,c.title, co.create_date, co.expired_time, c.price | |||||
| from wx_coupon_order co | |||||
| left join wx_coupon_merchant cm on cm.product_id = co.coupon_id | |||||
| left join wx_coupon c on c.id = co.coupon_id | |||||
| left join pos_coupon_order_verify pco on pco.coupon_order_id = co.id | |||||
| where co.tenant_id = #{tenantId} and co.c_user_id = #{cUserId} | |||||
| and co.coupon_order_status = 100 | |||||
| and cm.merchant_id = #{merchantId} | |||||
| and co.expired_time > now() | |||||
| and pco.pos_order_id = #{posOrderId} | |||||
| </select> | |||||
| </mapper> | </mapper> | ||||
| @@ -18,6 +18,7 @@ | |||||
| <module>mallinkSysAdmin</module> | <module>mallinkSysAdmin</module> | ||||
| <module>mallinkCApi</module> | <module>mallinkCApi</module> | ||||
| <module>mallinkBApi</module> | <module>mallinkBApi</module> | ||||
| <module>mallinkPosApi</module> | |||||
| <module>mallinkSchedule</module> | <module>mallinkSchedule</module> | ||||
| <module>mallinkMQConsumer</module> | <module>mallinkMQConsumer</module> | ||||
| <module>mallinkWebSocketServer</module> | <module>mallinkWebSocketServer</module> | ||||
| @@ -375,4 +376,4 @@ | |||||
| </plugins> | </plugins> | ||||
| </build> | </build> | ||||
| --> | --> | ||||
| </project> | |||||
| </project> | |||||