diff --git a/bweb/pom.xml b/bweb/pom.xml new file mode 100644 index 0000000..57b112a --- /dev/null +++ b/bweb/pom.xml @@ -0,0 +1,45 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + com.hfkj + bweb + + + + com.hfkj + service + PACKT-SNAPSHOT + + + + + + + src/main/resources/${env} + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/bweb/src/main/java/com/BWebApplication.java b/bweb/src/main/java/com/BWebApplication.java new file mode 100644 index 0000000..4897626 --- /dev/null +++ b/bweb/src/main/java/com/BWebApplication.java @@ -0,0 +1,30 @@ +package com; + +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; +import com.hfkj.common.utils.SpringContextUtil; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +// @ComponentScan +@EnableTransactionManagement +@EnableScheduling +@EnableMethodCache(basePackages = "com.hfkj") +@EnableCreateCacheAnnotation +@ServletComponentScan +@MapperScan("com.hfkj.dao") +public class BWebApplication +{ + public static void main( String[] args ) + { + ApplicationContext app = SpringApplication.run(BWebApplication.class, args); + SpringContextUtil.setApplicationContext(app); + } + +} diff --git a/bweb/src/main/java/com/bweb/config/AuthConfig.java b/bweb/src/main/java/com/bweb/config/AuthConfig.java new file mode 100644 index 0000000..c58319d --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/AuthConfig.java @@ -0,0 +1,136 @@ +package com.bweb.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.hfkj.common.security.UserCenter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private static Logger log = LoggerFactory.getLogger(AuthConfig.class); + + @Autowired + private UserCenter userCenter; + + /** + * 获取配置文件debug变量 + */ + @Value("${debug}") + private boolean debug = false; + + /** + * 解决18位long类型数据转json失去精度问题 + * @param converters + */ + @Override + public void configureMessageConverters(List> converters){ + MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); + + ObjectMapper objectMapper = jsonConverter.getObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + + converters.add(jsonConverter); + } + + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HandlerInterceptorAdapter() { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + if(debug){ + return true; + } + String token = request.getParameter("Authorization"); + if (StringUtils.isBlank(token)) { + token = request.getHeader("Authorization"); + } + if((StringUtils.isNotBlank(token) && userCenter.isTokenLogin(token)) || userCenter.isLogin(request)){//如果未登录,将无法使用任何接口 + userCenter.refreshCookie(request, response); + return true; + } else if(request instanceof StandardMultipartHttpServletRequest) { + StandardMultipartHttpServletRequest re = (StandardMultipartHttpServletRequest)request; + if(userCenter.isLogin(re.getRequest())){ + return true; + } else { + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } else{ + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } + }) + .addPathPatterns("/**") + .excludePathPatterns("/swagger-resources/**") + .excludePathPatterns("/**/api-docs") + .excludePathPatterns("/**/springfox-swagger-ui/**") + .excludePathPatterns("/**/swagger-ui.html") + .excludePathPatterns("/login/userLogin") + .excludePathPatterns("/login/logout") + .excludePathPatterns("/common/*") + .excludePathPatterns("/sms/*") + .excludePathPatterns("/coupon/getGuizhouSinopec") + .excludePathPatterns("/cmsContent/get*") + .excludePathPatterns("/highGoldRec/*") + .excludePathPatterns("/test/*") + .excludePathPatterns("/openApi/*") + ; + } + + public String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/bweb/src/main/java/com/bweb/config/ConfigListener.java b/bweb/src/main/java/com/bweb/config/ConfigListener.java new file mode 100644 index 0000000..fb81053 --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/ConfigListener.java @@ -0,0 +1,24 @@ +package com.bweb.config; + +import org.springframework.beans.factory.annotation.Autowired; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Autowired + private SysConfig sysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + SysConst.setSysConfig(sysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/bweb/src/main/java/com/bweb/config/CorsConfig.java b/bweb/src/main/java/com/bweb/config/CorsConfig.java new file mode 100644 index 0000000..5f46ab3 --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/CorsConfig.java @@ -0,0 +1,49 @@ +package com.bweb.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CorsConfig + * @Description: TODO () + * @Author 胡锐 + * @Date 2020/12/16 + **/ +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + List list = new ArrayList<>(); + list.add("*"); + corsConfiguration.setAllowedOrigins(list); + /* + // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等) + */ + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + return corsConfiguration; + } + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); + return new CorsFilter(source); + } +} diff --git a/bweb/src/main/java/com/bweb/config/MultipartConfig.java b/bweb/src/main/java/com/bweb/config/MultipartConfig.java new file mode 100644 index 0000000..267de74 --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/MultipartConfig.java @@ -0,0 +1,26 @@ +package com.bweb.config; + +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.MultipartConfigElement; + +@Configuration +public class MultipartConfig { + + /** + * 文件上传配置 + * @return + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + //文件最大 + factory.setMaxFileSize("300MB"); //KB,MB + //设置总上传数据总大小 + factory.setMaxRequestSize("350MB"); + return factory.createMultipartConfig(); + } + +} diff --git a/bweb/src/main/java/com/bweb/config/RedisConfig.java b/bweb/src/main/java/com/bweb/config/RedisConfig.java new file mode 100644 index 0000000..0c5f530 --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/RedisConfig.java @@ -0,0 +1,109 @@ +package com.bweb.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableCaching //开启注解 +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } +} \ No newline at end of file diff --git a/bweb/src/main/java/com/bweb/config/SwaggerConfig.java b/bweb/src/main/java/com/bweb/config/SwaggerConfig.java new file mode 100644 index 0000000..b46dc9a --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.bweb.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** +* SwaggerConfig.java +* 项目名称: +* 包: +* 类名称: SwaggerConfig.java +* 类描述: 构建restful api接口文档 +* 创建人: +* 创建时间: 2017 下午4:23:45 +*/ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + + /** + * 描述api的基本信息 + * 基本信息会展现在文档页面中 + * @return [api的基本信息] + */ + ApiInfo apiInfo() + { + return new ApiInfoBuilder().title("hgj-BWeb").description("提供给管理平台的接口").termsOfServiceUrl("").version("1.0.0") + .contact(new Contact("", "", "")).build(); + } + + @Bean + public Docket customImplementation() + { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage("com")) + .build().directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class).apiInfo(apiInfo()); + } + +} diff --git a/bweb/src/main/java/com/bweb/config/SysConfig.java b/bweb/src/main/java/com/bweb/config/SysConfig.java new file mode 100644 index 0000000..1535c40 --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/SysConfig.java @@ -0,0 +1,31 @@ +package com.bweb.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("sysConfig") +@ConfigurationProperties +@PropertySource("classpath:/config.properties") +public class SysConfig { + + private String fileUrl; + + private String cmsPath; + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } + + public String getCmsPath() { + return cmsPath; + } + + public void setCmsPath(String cmsPath) { + this.cmsPath = cmsPath; + } +} diff --git a/bweb/src/main/java/com/bweb/config/SysConst.java b/bweb/src/main/java/com/bweb/config/SysConst.java new file mode 100644 index 0000000..948513a --- /dev/null +++ b/bweb/src/main/java/com/bweb/config/SysConst.java @@ -0,0 +1,19 @@ +package com.bweb.config; + +public class SysConst { + + private static SysConfig sysConfig; + + public static void setSysConfig(SysConfig arg){ + sysConfig = arg; + } + + public static SysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new SysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/bweb/src/main/java/com/bweb/controller/CommonController.java b/bweb/src/main/java/com/bweb/controller/CommonController.java new file mode 100644 index 0000000..fabbb4f --- /dev/null +++ b/bweb/src/main/java/com/bweb/controller/CommonController.java @@ -0,0 +1,18 @@ +package com.bweb.controller; + +import io.swagger.annotations.Api; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + + +@RestController +@RequestMapping(value="/common") +@Api(value="共用接口") +public class CommonController { + + Logger log = LoggerFactory.getLogger(CommonController.class); + + + +} diff --git a/bweb/src/main/java/com/bweb/controller/FileUploadController.java b/bweb/src/main/java/com/bweb/controller/FileUploadController.java new file mode 100644 index 0000000..e9b2e31 --- /dev/null +++ b/bweb/src/main/java/com/bweb/controller/FileUploadController.java @@ -0,0 +1,138 @@ +package com.bweb.controller; + +import com.hfkj.common.utils.DateUtil; +import com.hfkj.common.utils.ResponseMsgUtil; +import com.bweb.config.SysConfig; +import com.hfkj.model.ResponseData; +import com.hfkj.service.FileUploadService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileOutputStream; +import java.util.*; + +@RestController +@RequestMapping(value="/fileUpload") +@Api(value="文件上传") +public class FileUploadController { + + private static Logger log = LoggerFactory.getLogger(FileUploadController.class); + + @Resource + private SysConfig sysConfig; + + @Resource + private FileUploadService fileUploadService; + + @RequestMapping(value="/uploadfile",method = RequestMethod.POST) + @ResponseBody + @ApiOperation(value = "文件上传") + public ResponseData uploadFile(@RequestParam(value = "files" , required = false) MultipartFile files, + HttpServletRequest request, + HttpServletResponse response) throws Exception { + try { + response.setHeader("Access-Control-Allow-Origin", "*"); + CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver( + request.getSession().getServletContext()); + // 判断 request 是否有文件上传,即多部分请求 + List fileNames = new ArrayList(); + if (multipartResolver.isMultipart(request)) { + // 转换成多部分request + MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; + Iterator iterator = multiRequest.getFileNames(); + + while (iterator.hasNext()) { + MultipartFile file = multiRequest.getFile(iterator.next()); + if (file != null) { + FileOutputStream out = null; + try { + String fileType = file.getOriginalFilename() + .substring(file.getOriginalFilename().lastIndexOf(".") + 1); + String fileName = file.getOriginalFilename().substring(0, file.getOriginalFilename().lastIndexOf(".")) + System.currentTimeMillis() + "." + fileType; + String childPath = DateUtil.date2String(new Date(), "yyyyMM"); + String destDirName = sysConfig.getFileUrl() + File.separator + childPath; + File dir = new File(destDirName); + if (!dir.exists()) { + dir.mkdirs(); + } + out = new FileOutputStream(destDirName + File.separator + fileName); + out.write(file.getBytes()); + out.flush(); + fileNames.add(childPath + "/" + fileName); + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + if (out != null) { + out.close(); + } + } + } + } + } + return ResponseMsgUtil.success(fileNames); + + } catch (Exception e) { + log.error(e.getMessage(), e); + return ResponseMsgUtil.exception(e); + } + + } + + @RequestMapping(value = "/fileUpload", method = RequestMethod.POST) + @ApiOperation(value = "上传文件(新接口)") + @ResponseBody + public ResponseData fileUpload(@RequestParam(name = "requestFile") MultipartFile requestFile, + @RequestParam(value = "uploadType", required = true) String uploadType, + HttpServletRequest request + ) { + try { + CommonsMultipartResolver multipartResolver = + new CommonsMultipartResolver(request.getSession().getServletContext()); + + // 提取文件列表 + List files = new ArrayList<>(); + if (multipartResolver.isMultipart(request)) { + MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; + Iterator iterator = multiRequest.getFileNames(); + + while (iterator.hasNext()) { + MultipartFile file = multiRequest.getFile(iterator.next()); + files.add(file); + } + } + + // 定制参数 + Map paramsMap = new HashMap<>(); + if ("cmsModule".equals(uploadType)) { + paramsMap.put("pathPrefix", sysConfig.getFileUrl()); + paramsMap.put("childPath", "/CMS/module/"); + paramsMap.put("fileNameGenerator", "generateFileNameAndTimeStamp"); + } else if ("cmsPatch".equals(uploadType)) { + paramsMap.put("pathPrefix", sysConfig.getFileUrl()); + paramsMap.put("childPath", "/CMS/html/"); + paramsMap.put("fileNameGenerator", "generateFileNameAndTimeStamp"); + } else if ("cmsImg".equals(uploadType)) { + paramsMap.put("pathPrefix", sysConfig.getFileUrl()); + paramsMap.put("childPath", "/CMS/img/"); + paramsMap.put("fileNameGenerator", "generateFileNameAndTimeStamp"); + } + + return ResponseMsgUtil.success(fileUploadService.upload(files, paramsMap)); + } catch (Exception e) { + log.error("FileUploadController --> addCategoryModule() error!", e); + return ResponseMsgUtil.exception(e); + } + } + + +} diff --git a/bweb/src/main/resources/dev/application.yml b/bweb/src/main/resources/dev/application.yml new file mode 100644 index 0000000..07a5b09 --- /dev/null +++ b/bweb/src/main/resources/dev/application.yml @@ -0,0 +1,89 @@ +server: + port: 9502 + servlet: + context-path: /brest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/puhui_go?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +rocketmq: + name-server: 139.9.154.68:9876 + producer: + access-key: huifukeji + secret-key: HF123456. + #必须指定group + group: default-group + consumer: + access-key: huifukeji + secret-key: HF123456. + +jetcache: + statIntervalMinutes: 15 + areaInCacheName: false + local: + default: + type: linkedhashmap + keyConvertor: fastjson + remote: + default: + type: redis + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + keyConvertor: fastjson + broadcastChannel: projectA + valueEncoder: java + valueDecoder: java + poolConfig: + minIdle: 5 + maxIdle: 20 + maxTotal: 50 diff --git a/bweb/src/main/resources/dev/config.properties b/bweb/src/main/resources/dev/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/bweb/src/main/resources/dev/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/bweb/src/main/resources/dev/logback.xml b/bweb/src/main/resources/dev/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/bweb/src/main/resources/dev/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/bweb/src/main/resources/pre/application.yml b/bweb/src/main/resources/pre/application.yml new file mode 100644 index 0000000..874093a --- /dev/null +++ b/bweb/src/main/resources/pre/application.yml @@ -0,0 +1,56 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/bweb/src/main/resources/pre/config.properties b/bweb/src/main/resources/pre/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/bweb/src/main/resources/pre/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/bweb/src/main/resources/pre/logback.xml b/bweb/src/main/resources/pre/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/bweb/src/main/resources/pre/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/bweb/src/main/resources/prod/application.yml b/bweb/src/main/resources/prod/application.yml new file mode 100644 index 0000000..f3e38c7 --- /dev/null +++ b/bweb/src/main/resources/prod/application.yml @@ -0,0 +1,57 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/hsg?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 127.0.0.1 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/bweb/src/main/resources/prod/config.properties b/bweb/src/main/resources/prod/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/bweb/src/main/resources/prod/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/bweb/src/main/resources/prod/logback.xml b/bweb/src/main/resources/prod/logback.xml new file mode 100644 index 0000000..e509de0 --- /dev/null +++ b/bweb/src/main/resources/prod/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/cweb/pom.xml b/cweb/pom.xml new file mode 100644 index 0000000..361cfdd --- /dev/null +++ b/cweb/pom.xml @@ -0,0 +1,45 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + com.hfkj + cweb + + + + com.hfkj + service + PACKT-SNAPSHOT + + + + + + + src/main/resources/${env} + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/cweb/src/main/java/com/CWebApplication.java b/cweb/src/main/java/com/CWebApplication.java new file mode 100644 index 0000000..84183e8 --- /dev/null +++ b/cweb/src/main/java/com/CWebApplication.java @@ -0,0 +1,30 @@ +package com; + +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; +import com.hfkj.common.utils.SpringContextUtil; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +// @ComponentScan +@EnableTransactionManagement +@EnableScheduling +@EnableMethodCache(basePackages = "com.hfkj") +@EnableCreateCacheAnnotation +@ServletComponentScan +@MapperScan("com.hfkj.dao") +public class CWebApplication +{ + public static void main( String[] args ) + { + ApplicationContext app = SpringApplication.run(CWebApplication.class, args); + SpringContextUtil.setApplicationContext(app); + } + +} diff --git a/cweb/src/main/java/com/cweb/config/AuthConfig.java b/cweb/src/main/java/com/cweb/config/AuthConfig.java new file mode 100644 index 0000000..989ed17 --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/AuthConfig.java @@ -0,0 +1,169 @@ +package com.cweb.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.hfkj.common.security.UserCenter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private static Logger log = LoggerFactory.getLogger(AuthConfig.class); + + @Resource + private UserCenter userCenter; + + /** + * 获取配置文件debug变量 + */ + @Value("${debug}") + private boolean debug = false; + + /** + * 解决18位long类型数据转json失去精度问题 + * @param converters + */ + @Override + public void configureMessageConverters(List> converters){ + MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); + + ObjectMapper objectMapper = jsonConverter.getObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + + converters.add(jsonConverter); + } + + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HandlerInterceptorAdapter() { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + if(debug){ + return true; + } + String token = request.getParameter("Authorization"); + if (StringUtils.isBlank(token)) { + token = request.getHeader("Authorization"); + } + if((StringUtils.isNotBlank(token) && userCenter.isTokenLogin(token)) || userCenter.isLogin(request)){//如果未登录,将无法使用任何接口 + userCenter.refreshCookie(request, response); + return true; + } else if(request instanceof StandardMultipartHttpServletRequest) { + StandardMultipartHttpServletRequest re = (StandardMultipartHttpServletRequest)request; + if(userCenter.isLogin(re.getRequest())){ + return true; + } else { + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } else{ + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } + }) + .addPathPatterns("/**") + .excludePathPatterns("/swagger-resources/**") + .excludePathPatterns("/**/api-docs") + .excludePathPatterns("/**/springfox-swagger-ui/**") + .excludePathPatterns("/**/swagger-ui.html") + .excludePathPatterns("/login/*") + .excludePathPatterns("/order/*") + .excludePathPatterns("/coupon/getCouponList") + .excludePathPatterns("/wechatpay/*") + .excludePathPatterns("/coupon/getCouponById") + .excludePathPatterns("/discount/getDiscountByQrCode") + .excludePathPatterns("/discount/getDiscountById") + .excludePathPatterns("/discount/getCouponByDiscount") + .excludePathPatterns("/discount/getDiscountByDiscountAgentId") + .excludePathPatterns("/highMerchantStore/getMerchantStoreById") + .excludePathPatterns("/highMerchantStore/getStoreListByCoupon") + .excludePathPatterns("/highMerchantStore/getStoreList") + .excludePathPatterns("/highMerchantStore/getMerchantList") + .excludePathPatterns("/highMerchantStore/getStoreListByMerchant") + .excludePathPatterns("/sms/sendSmsCode") + .excludePathPatterns("/sms/getSmsCode") + .excludePathPatterns("/activity/getWinLotteryList") + .excludePathPatterns("/user/login") + .excludePathPatterns("/user/unionPhoneLogin") + .excludePathPatterns("/user/getUnionId") + .excludePathPatterns("/highUser/setCacheParam") + .excludePathPatterns("/highUser/getCacheParam") + .excludePathPatterns("/highUser/delCacheParam") + .excludePathPatterns("/order/orderToH5Pay") + .excludePathPatterns("/order/orderToPay") + .excludePathPatterns("/test/*") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/outRechargeOrder/*") + .excludePathPatterns("/wechat/*") + .excludePathPatterns("/tuanyou/*") + .excludePathPatterns("/unionPay/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/common/*") + .excludePathPatterns("/order/qzOrderToPay") + .excludePathPatterns("/czOrder/orderRefundNotify") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highBrand/*") + .excludePathPatterns("/highGoodsType/*") + .excludePathPatterns("/sendSms/*") + .excludePathPatterns("/test/*") + .excludePathPatterns("/sms/*") + ; + } + + public String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/cweb/src/main/java/com/cweb/config/ConfigListener.java b/cweb/src/main/java/com/cweb/config/ConfigListener.java new file mode 100644 index 0000000..cb92b19 --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/ConfigListener.java @@ -0,0 +1,25 @@ +package com.cweb.config; + +import org.springframework.beans.factory.annotation.Autowired; + +import javax.annotation.Resource; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Resource + private SysConfig sysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + SysConst.setSysConfig(sysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/cweb/src/main/java/com/cweb/config/CorsConfig.java b/cweb/src/main/java/com/cweb/config/CorsConfig.java new file mode 100644 index 0000000..14e87c0 --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/CorsConfig.java @@ -0,0 +1,49 @@ +package com.cweb.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CorsConfig + * @Description: TODO () + * @Author 胡锐 + * @Date 2020/12/16 + **/ +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + List list = new ArrayList<>(); + list.add("*"); + corsConfiguration.setAllowedOrigins(list); + /* + // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等) + */ + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + return corsConfiguration; + } + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); + return new CorsFilter(source); + } +} diff --git a/cweb/src/main/java/com/cweb/config/MultipartConfig.java b/cweb/src/main/java/com/cweb/config/MultipartConfig.java new file mode 100644 index 0000000..97794e9 --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/MultipartConfig.java @@ -0,0 +1,26 @@ +package com.cweb.config; + +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.MultipartConfigElement; + +@Configuration +public class MultipartConfig { + + /** + * 文件上传配置 + * @return + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + //文件最大 + factory.setMaxFileSize("300MB"); //KB,MB + //设置总上传数据总大小 + factory.setMaxRequestSize("350MB"); + return factory.createMultipartConfig(); + } + +} diff --git a/cweb/src/main/java/com/cweb/config/RedisConfig.java b/cweb/src/main/java/com/cweb/config/RedisConfig.java new file mode 100644 index 0000000..c6db7fc --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/RedisConfig.java @@ -0,0 +1,110 @@ +package com.cweb.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableCaching //开启注解 +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} \ No newline at end of file diff --git a/cweb/src/main/java/com/cweb/config/SwaggerConfig.java b/cweb/src/main/java/com/cweb/config/SwaggerConfig.java new file mode 100644 index 0000000..95ebf13 --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.cweb.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** +* SwaggerConfig.java +* 项目名称: +* 包: +* 类名称: SwaggerConfig.java +* 类描述: 构建restful api接口文档 +* 创建人: +* 创建时间: 2017 下午4:23:45 +*/ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + + /** + * 描述api的基本信息 + * 基本信息会展现在文档页面中 + * @return [api的基本信息] + */ + ApiInfo apiInfo() + { + return new ApiInfoBuilder().title("hgj-CWeb").description("提供给用户端的接口").termsOfServiceUrl("").version("1.0.0") + .contact(new Contact("", "", "")).build(); + } + + @Bean + public Docket customImplementation() + { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage("com")) + .build().directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class).apiInfo(apiInfo()); + } + +} diff --git a/cweb/src/main/java/com/cweb/config/SysConfig.java b/cweb/src/main/java/com/cweb/config/SysConfig.java new file mode 100644 index 0000000..3be648e --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/SysConfig.java @@ -0,0 +1,31 @@ +package com.cweb.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("sysConfig") +@ConfigurationProperties +@PropertySource("classpath:/config.properties") +public class SysConfig { + + private String fileUrl; + + private String cmsPath; + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } + + public String getCmsPath() { + return cmsPath; + } + + public void setCmsPath(String cmsPath) { + this.cmsPath = cmsPath; + } +} diff --git a/cweb/src/main/java/com/cweb/config/SysConst.java b/cweb/src/main/java/com/cweb/config/SysConst.java new file mode 100644 index 0000000..23c919a --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/SysConst.java @@ -0,0 +1,19 @@ +package com.cweb.config; + +public class SysConst { + + private static SysConfig sysConfig; + + public static void setSysConfig(SysConfig arg){ + sysConfig = arg; + } + + public static SysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new SysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/cweb/src/main/java/com/cweb/config/WxMaConfiguration.java b/cweb/src/main/java/com/cweb/config/WxMaConfiguration.java new file mode 100644 index 0000000..b877321 --- /dev/null +++ b/cweb/src/main/java/com/cweb/config/WxMaConfiguration.java @@ -0,0 +1,33 @@ +package com.cweb.config; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; +import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +public class WxMaConfiguration { + + private static WxMaService maService; + + public static WxMaService getMaService() { + if (maService == null) { + throw new IllegalArgumentException(String.format("未找到对应的配置,请核实!")); + } + + return maService; + } + + @PostConstruct + public void init() { + /*WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); + config.setAppid(SysConst.getSysConfig().getWxAppId()); + config.setSecret(SysConst.getSysConfig().getWxAppSecret()); + + maService = new WxMaServiceImpl(); + maService.setWxMaConfig(config);*/ + } + +} diff --git a/cweb/src/main/java/com/cweb/controller/CommonController.java b/cweb/src/main/java/com/cweb/controller/CommonController.java new file mode 100644 index 0000000..ecbfa8b --- /dev/null +++ b/cweb/src/main/java/com/cweb/controller/CommonController.java @@ -0,0 +1,16 @@ +package com.cweb.controller; + +import io.swagger.annotations.Api; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + + +@RestController +@RequestMapping(value="/common") +@Api(value="共用接口") +public class CommonController { + + Logger log = LoggerFactory.getLogger(CommonController.class); + +} diff --git a/cweb/src/main/resources/dev/application.yml b/cweb/src/main/resources/dev/application.yml new file mode 100644 index 0000000..915cda2 --- /dev/null +++ b/cweb/src/main/resources/dev/application.yml @@ -0,0 +1,89 @@ +server: + port: 9501 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/puhui_go?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +rocketmq: + name-server: 139.9.154.68:9876 + producer: + access-key: huifukeji + secret-key: HF123456. + #必须指定group + group: default-group + consumer: + access-key: huifukeji + secret-key: HF123456. + +jetcache: + statIntervalMinutes: 15 + areaInCacheName: false + local: + default: + type: linkedhashmap + keyConvertor: fastjson + remote: + default: + type: redis + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + keyConvertor: fastjson + broadcastChannel: projectA + valueEncoder: java + valueDecoder: java + poolConfig: + minIdle: 5 + maxIdle: 20 + maxTotal: 50 diff --git a/cweb/src/main/resources/dev/config.properties b/cweb/src/main/resources/dev/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/cweb/src/main/resources/dev/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/cweb/src/main/resources/dev/logback.xml b/cweb/src/main/resources/dev/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/cweb/src/main/resources/dev/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/cweb/src/main/resources/pre/application.yml b/cweb/src/main/resources/pre/application.yml new file mode 100644 index 0000000..874093a --- /dev/null +++ b/cweb/src/main/resources/pre/application.yml @@ -0,0 +1,56 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/cweb/src/main/resources/pre/config.properties b/cweb/src/main/resources/pre/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/cweb/src/main/resources/pre/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/cweb/src/main/resources/pre/logback.xml b/cweb/src/main/resources/pre/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/cweb/src/main/resources/pre/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/cweb/src/main/resources/prod/application.yml b/cweb/src/main/resources/prod/application.yml new file mode 100644 index 0000000..f3e38c7 --- /dev/null +++ b/cweb/src/main/resources/prod/application.yml @@ -0,0 +1,57 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/hsg?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 127.0.0.1 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/cweb/src/main/resources/prod/config.properties b/cweb/src/main/resources/prod/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/cweb/src/main/resources/prod/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/cweb/src/main/resources/prod/logback.xml b/cweb/src/main/resources/prod/logback.xml new file mode 100644 index 0000000..e509de0 --- /dev/null +++ b/cweb/src/main/resources/prod/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/openapi/pom.xml b/openapi/pom.xml new file mode 100644 index 0000000..4dd5f11 --- /dev/null +++ b/openapi/pom.xml @@ -0,0 +1,45 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + com.hfkj + openapi + + + + com.hfkj + service + PACKT-SNAPSHOT + + + + + + + src/main/resources/${env} + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/openapi/src/main/java/com/OpenAPiApplication.java b/openapi/src/main/java/com/OpenAPiApplication.java new file mode 100644 index 0000000..a2a4b2a --- /dev/null +++ b/openapi/src/main/java/com/OpenAPiApplication.java @@ -0,0 +1,30 @@ +package com; + +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; +import com.hfkj.common.utils.SpringContextUtil; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +// @ComponentScan +@EnableTransactionManagement +@EnableScheduling +@EnableMethodCache(basePackages = "com.hfkj") +@EnableCreateCacheAnnotation +@ServletComponentScan +@MapperScan("com.hfkj.dao") +public class OpenAPiApplication +{ + public static void main( String[] args ) + { + ApplicationContext app = SpringApplication.run(OpenAPiApplication.class, args); + SpringContextUtil.setApplicationContext(app); + } + +} diff --git a/openapi/src/main/java/com/openapi/config/AuthConfig.java b/openapi/src/main/java/com/openapi/config/AuthConfig.java new file mode 100644 index 0000000..50b0ac2 --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/AuthConfig.java @@ -0,0 +1,170 @@ +package com.openapi.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.hfkj.common.security.UserCenter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private static Logger log = LoggerFactory.getLogger(AuthConfig.class); + + @Resource + private UserCenter userCenter; + + /** + * 获取配置文件debug变量 + */ + @Value("${debug}") + private boolean debug = false; + + /** + * 解决18位long类型数据转json失去精度问题 + * @param converters + */ + @Override + public void configureMessageConverters(List> converters){ + MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); + + ObjectMapper objectMapper = jsonConverter.getObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + + converters.add(jsonConverter); + } + + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HandlerInterceptorAdapter() { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + if(debug){ + return true; + } + return true; + /*String token = request.getParameter("Authorization"); + if (StringUtils.isBlank(token)) { + token = request.getHeader("Authorization"); + } + if((StringUtils.isNotBlank(token) && userCenter.isTokenLogin(token)) || userCenter.isLogin(request)){//如果未登录,将无法使用任何接口 + userCenter.refreshCookie(request, response); + return true; + } else if(request instanceof StandardMultipartHttpServletRequest) { + StandardMultipartHttpServletRequest re = (StandardMultipartHttpServletRequest)request; + if(userCenter.isLogin(re.getRequest())){ + return true; + } else { + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } else{ + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + }*/ + } + }) + .addPathPatterns("/**") + .excludePathPatterns("/swagger-resources/**") + .excludePathPatterns("/**/api-docs") + .excludePathPatterns("/**/springfox-swagger-ui/**") + .excludePathPatterns("/**/swagger-ui.html") + .excludePathPatterns("/login/*") + .excludePathPatterns("/order/*") + .excludePathPatterns("/coupon/getCouponList") + .excludePathPatterns("/wechatpay/*") + .excludePathPatterns("/coupon/getCouponById") + .excludePathPatterns("/discount/getDiscountByQrCode") + .excludePathPatterns("/discount/getDiscountById") + .excludePathPatterns("/discount/getCouponByDiscount") + .excludePathPatterns("/discount/getDiscountByDiscountAgentId") + .excludePathPatterns("/highMerchantStore/getMerchantStoreById") + .excludePathPatterns("/highMerchantStore/getStoreListByCoupon") + .excludePathPatterns("/highMerchantStore/getStoreList") + .excludePathPatterns("/highMerchantStore/getMerchantList") + .excludePathPatterns("/highMerchantStore/getStoreListByMerchant") + .excludePathPatterns("/sms/sendSmsCode") + .excludePathPatterns("/sms/getSmsCode") + .excludePathPatterns("/activity/getWinLotteryList") + .excludePathPatterns("/user/login") + .excludePathPatterns("/user/unionPhoneLogin") + .excludePathPatterns("/user/getUnionId") + .excludePathPatterns("/highUser/setCacheParam") + .excludePathPatterns("/highUser/getCacheParam") + .excludePathPatterns("/highUser/delCacheParam") + .excludePathPatterns("/order/orderToH5Pay") + .excludePathPatterns("/order/orderToPay") + .excludePathPatterns("/test/*") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/outRechargeOrder/*") + .excludePathPatterns("/wechat/*") + .excludePathPatterns("/tuanyou/*") + .excludePathPatterns("/unionPay/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/common/*") + .excludePathPatterns("/order/qzOrderToPay") + .excludePathPatterns("/czOrder/orderRefundNotify") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highBrand/*") + .excludePathPatterns("/highGoodsType/*") + .excludePathPatterns("/sendSms/*") + .excludePathPatterns("/test/*") + .excludePathPatterns("/sms/*") + ; + } + + public String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/openapi/src/main/java/com/openapi/config/ConfigListener.java b/openapi/src/main/java/com/openapi/config/ConfigListener.java new file mode 100644 index 0000000..5352371 --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/ConfigListener.java @@ -0,0 +1,23 @@ +package com.openapi.config; + +import javax.annotation.Resource; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Resource + private SysConfig sysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + SysConst.setSysConfig(sysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/openapi/src/main/java/com/openapi/config/CorsConfig.java b/openapi/src/main/java/com/openapi/config/CorsConfig.java new file mode 100644 index 0000000..dd7cee3 --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/CorsConfig.java @@ -0,0 +1,49 @@ +package com.openapi.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CorsConfig + * @Description: TODO () + * @Author 胡锐 + * @Date 2020/12/16 + **/ +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + List list = new ArrayList<>(); + list.add("*"); + corsConfiguration.setAllowedOrigins(list); + /* + // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等) + */ + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + return corsConfiguration; + } + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); + return new CorsFilter(source); + } +} diff --git a/openapi/src/main/java/com/openapi/config/MultipartConfig.java b/openapi/src/main/java/com/openapi/config/MultipartConfig.java new file mode 100644 index 0000000..f39edf8 --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/MultipartConfig.java @@ -0,0 +1,26 @@ +package com.openapi.config; + +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.MultipartConfigElement; + +@Configuration +public class MultipartConfig { + + /** + * 文件上传配置 + * @return + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + //文件最大 + factory.setMaxFileSize("300MB"); //KB,MB + //设置总上传数据总大小 + factory.setMaxRequestSize("350MB"); + return factory.createMultipartConfig(); + } + +} diff --git a/openapi/src/main/java/com/openapi/config/RedisConfig.java b/openapi/src/main/java/com/openapi/config/RedisConfig.java new file mode 100644 index 0000000..999b0ed --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/RedisConfig.java @@ -0,0 +1,110 @@ +package com.openapi.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableCaching //开启注解 +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} diff --git a/openapi/src/main/java/com/openapi/config/SwaggerConfig.java b/openapi/src/main/java/com/openapi/config/SwaggerConfig.java new file mode 100644 index 0000000..e05c353 --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.openapi.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** +* SwaggerConfig.java +* 项目名称: +* 包: +* 类名称: SwaggerConfig.java +* 类描述: 构建restful api接口文档 +* 创建人: +* 创建时间: 2017 下午4:23:45 +*/ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + + /** + * 描述api的基本信息 + * 基本信息会展现在文档页面中 + * @return [api的基本信息] + */ + ApiInfo apiInfo() + { + return new ApiInfoBuilder().title("hgj-CWeb").description("提供给用户端的接口").termsOfServiceUrl("").version("1.0.0") + .contact(new Contact("", "", "")).build(); + } + + @Bean + public Docket customImplementation() + { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage("com")) + .build().directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class).apiInfo(apiInfo()); + } + +} diff --git a/openapi/src/main/java/com/openapi/config/SysConfig.java b/openapi/src/main/java/com/openapi/config/SysConfig.java new file mode 100644 index 0000000..bcddd3b --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/SysConfig.java @@ -0,0 +1,31 @@ +package com.openapi.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("sysConfig") +@ConfigurationProperties +@PropertySource("classpath:/config.properties") +public class SysConfig { + + private String fileUrl; + + private String cmsPath; + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } + + public String getCmsPath() { + return cmsPath; + } + + public void setCmsPath(String cmsPath) { + this.cmsPath = cmsPath; + } +} diff --git a/openapi/src/main/java/com/openapi/config/SysConst.java b/openapi/src/main/java/com/openapi/config/SysConst.java new file mode 100644 index 0000000..343acc6 --- /dev/null +++ b/openapi/src/main/java/com/openapi/config/SysConst.java @@ -0,0 +1,19 @@ +package com.openapi.config; + +public class SysConst { + + private static SysConfig sysConfig; + + public static void setSysConfig(SysConfig arg){ + sysConfig = arg; + } + + public static SysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new SysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/openapi/src/main/resources/dev/application.yml b/openapi/src/main/resources/dev/application.yml new file mode 100644 index 0000000..6180e80 --- /dev/null +++ b/openapi/src/main/resources/dev/application.yml @@ -0,0 +1,89 @@ +server: + port: 9505 + servlet: + context-path: /openapi + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/puhui_go?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +rocketmq: + name-server: 139.9.154.68:9876 + producer: + access-key: huifukeji + secret-key: HF123456. + #必须指定group + group: default-group + consumer: + access-key: huifukeji + secret-key: HF123456. + +jetcache: + statIntervalMinutes: 15 + areaInCacheName: false + local: + default: + type: linkedhashmap + keyConvertor: fastjson + remote: + default: + type: redis + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + keyConvertor: fastjson + broadcastChannel: projectA + valueEncoder: java + valueDecoder: java + poolConfig: + minIdle: 5 + maxIdle: 20 + maxTotal: 50 diff --git a/openapi/src/main/resources/dev/config.properties b/openapi/src/main/resources/dev/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/openapi/src/main/resources/dev/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/openapi/src/main/resources/dev/logback.xml b/openapi/src/main/resources/dev/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/openapi/src/main/resources/dev/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/openapi/src/main/resources/pre/application.yml b/openapi/src/main/resources/pre/application.yml new file mode 100644 index 0000000..874093a --- /dev/null +++ b/openapi/src/main/resources/pre/application.yml @@ -0,0 +1,56 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/openapi/src/main/resources/pre/config.properties b/openapi/src/main/resources/pre/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/openapi/src/main/resources/pre/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/openapi/src/main/resources/pre/logback.xml b/openapi/src/main/resources/pre/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/openapi/src/main/resources/pre/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/openapi/src/main/resources/prod/application.yml b/openapi/src/main/resources/prod/application.yml new file mode 100644 index 0000000..f3e38c7 --- /dev/null +++ b/openapi/src/main/resources/prod/application.yml @@ -0,0 +1,57 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/hsg?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 127.0.0.1 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/openapi/src/main/resources/prod/config.properties b/openapi/src/main/resources/prod/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/openapi/src/main/resources/prod/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/openapi/src/main/resources/prod/logback.xml b/openapi/src/main/resources/prod/logback.xml new file mode 100644 index 0000000..e509de0 --- /dev/null +++ b/openapi/src/main/resources/prod/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/order/pom.xml b/order/pom.xml new file mode 100644 index 0000000..dac2cc8 --- /dev/null +++ b/order/pom.xml @@ -0,0 +1,45 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + com.hfkj + order + + + + com.hfkj + service + PACKT-SNAPSHOT + + + + + + + src/main/resources/${env} + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/order/src/main/java/com/OrderApplication.java b/order/src/main/java/com/OrderApplication.java new file mode 100644 index 0000000..693268a --- /dev/null +++ b/order/src/main/java/com/OrderApplication.java @@ -0,0 +1,29 @@ +package com; + +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; +import com.hfkj.common.utils.SpringContextUtil; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +// @ComponentScan +@EnableTransactionManagement +@EnableScheduling +@EnableMethodCache(basePackages = "com.hfkj") +@EnableCreateCacheAnnotation +@ServletComponentScan +@MapperScan("com.hfkj.dao") +public class OrderApplication { + public static void main( String[] args ) + { + ApplicationContext app = SpringApplication.run(OrderApplication.class, args); + SpringContextUtil.setApplicationContext(app); + } + +} diff --git a/order/src/main/java/com/order/config/AuthConfig.java b/order/src/main/java/com/order/config/AuthConfig.java new file mode 100644 index 0000000..97b9c9a --- /dev/null +++ b/order/src/main/java/com/order/config/AuthConfig.java @@ -0,0 +1,169 @@ +package com.order.config; + +import com.hfkj.common.security.UserCenter; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private static Logger log = LoggerFactory.getLogger(AuthConfig.class); + + @Resource + private UserCenter userCenter; + + /** + * 获取配置文件debug变量 + */ + @Value("${debug}") + private boolean debug = false; + + /** + * 解决18位long类型数据转json失去精度问题 + * @param converters + */ + @Override + public void configureMessageConverters(List> converters){ + MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); + + ObjectMapper objectMapper = jsonConverter.getObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + + converters.add(jsonConverter); + } + + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HandlerInterceptorAdapter() { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + if(debug){ + return true; + } + String token = request.getParameter("Authorization"); + if (StringUtils.isBlank(token)) { + token = request.getHeader("Authorization"); + } + if((StringUtils.isNotBlank(token) && userCenter.isTokenLogin(token)) || userCenter.isLogin(request)){//如果未登录,将无法使用任何接口 + userCenter.refreshCookie(request, response); + return true; + } else if(request instanceof StandardMultipartHttpServletRequest) { + StandardMultipartHttpServletRequest re = (StandardMultipartHttpServletRequest)request; + if(userCenter.isLogin(re.getRequest())){ + return true; + } else { + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } else{ + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } + }) + .addPathPatterns("/**") + .excludePathPatterns("/swagger-resources/**") + .excludePathPatterns("/**/api-docs") + .excludePathPatterns("/**/springfox-swagger-ui/**") + .excludePathPatterns("/**/swagger-ui.html") + .excludePathPatterns("/login/*") + .excludePathPatterns("/order/*") + .excludePathPatterns("/coupon/getCouponList") + .excludePathPatterns("/wechatpay/*") + .excludePathPatterns("/coupon/getCouponById") + .excludePathPatterns("/discount/getDiscountByQrCode") + .excludePathPatterns("/discount/getDiscountById") + .excludePathPatterns("/discount/getCouponByDiscount") + .excludePathPatterns("/discount/getDiscountByDiscountAgentId") + .excludePathPatterns("/highMerchantStore/getMerchantStoreById") + .excludePathPatterns("/highMerchantStore/getStoreListByCoupon") + .excludePathPatterns("/highMerchantStore/getStoreList") + .excludePathPatterns("/highMerchantStore/getMerchantList") + .excludePathPatterns("/highMerchantStore/getStoreListByMerchant") + .excludePathPatterns("/sms/sendSmsCode") + .excludePathPatterns("/sms/getSmsCode") + .excludePathPatterns("/activity/getWinLotteryList") + .excludePathPatterns("/user/login") + .excludePathPatterns("/user/unionPhoneLogin") + .excludePathPatterns("/user/getUnionId") + .excludePathPatterns("/highUser/setCacheParam") + .excludePathPatterns("/highUser/getCacheParam") + .excludePathPatterns("/highUser/delCacheParam") + .excludePathPatterns("/order/orderToH5Pay") + .excludePathPatterns("/order/orderToPay") + .excludePathPatterns("/test/*") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/outRechargeOrder/*") + .excludePathPatterns("/wechat/*") + .excludePathPatterns("/tuanyou/*") + .excludePathPatterns("/unionPay/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/common/*") + .excludePathPatterns("/order/qzOrderToPay") + .excludePathPatterns("/czOrder/orderRefundNotify") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highBrand/*") + .excludePathPatterns("/highGoodsType/*") + .excludePathPatterns("/sendSms/*") + .excludePathPatterns("/test/*") + .excludePathPatterns("/sms/*") + ; + } + + public String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/order/src/main/java/com/order/config/ConfigListener.java b/order/src/main/java/com/order/config/ConfigListener.java new file mode 100644 index 0000000..9ce8eef --- /dev/null +++ b/order/src/main/java/com/order/config/ConfigListener.java @@ -0,0 +1,23 @@ +package com.order.config; + +import javax.annotation.Resource; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Resource + private SysConfig sysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + SysConst.setSysConfig(sysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/order/src/main/java/com/order/config/CorsConfig.java b/order/src/main/java/com/order/config/CorsConfig.java new file mode 100644 index 0000000..997dbd0 --- /dev/null +++ b/order/src/main/java/com/order/config/CorsConfig.java @@ -0,0 +1,49 @@ +package com.order.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CorsConfig + * @Description: TODO () + * @Author 胡锐 + * @Date 2020/12/16 + **/ +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + List list = new ArrayList<>(); + list.add("*"); + corsConfiguration.setAllowedOrigins(list); + /* + // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等) + */ + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + return corsConfiguration; + } + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); + return new CorsFilter(source); + } +} diff --git a/order/src/main/java/com/order/config/MultipartConfig.java b/order/src/main/java/com/order/config/MultipartConfig.java new file mode 100644 index 0000000..3649115 --- /dev/null +++ b/order/src/main/java/com/order/config/MultipartConfig.java @@ -0,0 +1,26 @@ +package com.order.config; + +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.MultipartConfigElement; + +@Configuration +public class MultipartConfig { + + /** + * 文件上传配置 + * @return + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + //文件最大 + factory.setMaxFileSize("300MB"); //KB,MB + //设置总上传数据总大小 + factory.setMaxRequestSize("350MB"); + return factory.createMultipartConfig(); + } + +} diff --git a/order/src/main/java/com/order/config/RedisConfig.java b/order/src/main/java/com/order/config/RedisConfig.java new file mode 100644 index 0000000..8f20900 --- /dev/null +++ b/order/src/main/java/com/order/config/RedisConfig.java @@ -0,0 +1,110 @@ +package com.order.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableCaching //开启注解 +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} diff --git a/order/src/main/java/com/order/config/SessionKeyCache.java b/order/src/main/java/com/order/config/SessionKeyCache.java new file mode 100644 index 0000000..88b25c7 --- /dev/null +++ b/order/src/main/java/com/order/config/SessionKeyCache.java @@ -0,0 +1,53 @@ +package com.order.config; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SessionKeyCache { + + private static Map CACHE_DATA = new ConcurrentHashMap<>(); + + public static T getData(String key) { + CacheData data = CACHE_DATA.get(key); + if (data != null){ + if(data.getExpire() <= 0 || data.getSaveTime() >= System.currentTimeMillis()) { + return data.getData(); + }else{ + clear(key); + } + } + return null; + } + + public static void setData(String key, T data, int expire) { + CACHE_DATA.put(key, new CacheData(data, expire)); + } + + public static void clear(String key) { + CACHE_DATA.remove(key); + } + + private static class CacheData { + CacheData(T t, int expire) { + this.data = t; + this.expire = expire <= 0 ? 0 : expire*1000; + this.saveTime = System.currentTimeMillis() + this.expire; + } + + private T data; + private long saveTime; // 存活时间 + private long expire; // 过期时间 小于等于0标识永久存活 + + public T getData() { + return data; + } + + public long getExpire() { + return expire; + } + + public long getSaveTime() { + return saveTime; + } + } +} diff --git a/order/src/main/java/com/order/config/SwaggerConfig.java b/order/src/main/java/com/order/config/SwaggerConfig.java new file mode 100644 index 0000000..6ca5f23 --- /dev/null +++ b/order/src/main/java/com/order/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.order.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** +* SwaggerConfig.java +* 项目名称: +* 包: +* 类名称: SwaggerConfig.java +* 类描述: 构建restful api接口文档 +* 创建人: +* 创建时间: 2017 下午4:23:45 +*/ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + + /** + * 描述api的基本信息 + * 基本信息会展现在文档页面中 + * @return [api的基本信息] + */ + ApiInfo apiInfo() + { + return new ApiInfoBuilder().title("hgj-CWeb").description("提供给用户端的接口").termsOfServiceUrl("").version("1.0.0") + .contact(new Contact("", "", "")).build(); + } + + @Bean + public Docket customImplementation() + { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage("com")) + .build().directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class).apiInfo(apiInfo()); + } + +} diff --git a/order/src/main/java/com/order/config/SysConfig.java b/order/src/main/java/com/order/config/SysConfig.java new file mode 100644 index 0000000..e6b1824 --- /dev/null +++ b/order/src/main/java/com/order/config/SysConfig.java @@ -0,0 +1,31 @@ +package com.order.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("sysConfig") +@ConfigurationProperties +@PropertySource("classpath:/config.properties") +public class SysConfig { + + private String fileUrl; + + private String cmsPath; + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } + + public String getCmsPath() { + return cmsPath; + } + + public void setCmsPath(String cmsPath) { + this.cmsPath = cmsPath; + } +} diff --git a/order/src/main/java/com/order/config/SysConst.java b/order/src/main/java/com/order/config/SysConst.java new file mode 100644 index 0000000..07b20b4 --- /dev/null +++ b/order/src/main/java/com/order/config/SysConst.java @@ -0,0 +1,19 @@ +package com.order.config; + +public class SysConst { + + private static SysConfig sysConfig; + + public static void setSysConfig(SysConfig arg){ + sysConfig = arg; + } + + public static SysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new SysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/order/src/main/java/com/order/config/WxMaConfiguration.java b/order/src/main/java/com/order/config/WxMaConfiguration.java new file mode 100644 index 0000000..20447be --- /dev/null +++ b/order/src/main/java/com/order/config/WxMaConfiguration.java @@ -0,0 +1,31 @@ +package com.order.config; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +public class WxMaConfiguration { + + private static WxMaService maService; + + public static WxMaService getMaService() { + if (maService == null) { + throw new IllegalArgumentException(String.format("未找到对应的配置,请核实!")); + } + + return maService; + } + + @PostConstruct + public void init() { + /*WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); + config.setAppid(SysConst.getSysConfig().getWxAppId()); + config.setSecret(SysConst.getSysConfig().getWxAppSecret()); + + maService = new WxMaServiceImpl(); + maService.setWxMaConfig(config);*/ + } + +} diff --git a/order/src/main/java/com/order/config/WxMsgConfig.java b/order/src/main/java/com/order/config/WxMsgConfig.java new file mode 100644 index 0000000..f056903 --- /dev/null +++ b/order/src/main/java/com/order/config/WxMsgConfig.java @@ -0,0 +1,55 @@ +package com.order.config; + +import cn.binarywang.wx.miniapp.api.WxMaMsgService; +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage; +import com.hfkj.common.utils.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class WxMsgConfig { + + private static Logger log = LoggerFactory.getLogger(WxMsgConfig.class); + + public static void pushOneUser(String orderName , String price , String orderNo , Date payTime , String remark , Long orderId , String openId) { + + try { + List list = new ArrayList<>(); + + Map m = new HashMap<>(); + + m.put("thing1", orderName); + m.put("amount2", price + "元"); + m.put("character_string3", orderNo); + m.put("time4", DateUtil.date2String(payTime , "yyyy年MM月dd日 HH:mm:ss")); + m.put("thing6", remark); + + for (String key: m.keySet()) { + WxMaSubscribeMessage.Data msgElement = new WxMaSubscribeMessage.Data(); + msgElement.setName(key); + msgElement.setValue(m.get(key)); + list.add(msgElement); + } + + WxMaSubscribeMessage subscribeMessage = new WxMaSubscribeMessage(); + subscribeMessage.setToUser(openId); // 小程序openId + subscribeMessage.setTemplateId("oUvaCPeeOg4wH6HTvCcSabU6FnzXUXOBXsqBYAPOV-U"); + subscribeMessage.setData(list); + subscribeMessage.setPage("pages/user/order_details/order_details?id=" + orderId); + subscribeMessage.setMiniprogramState("developer"); + + final WxMaService wxService = WxMaConfiguration.getMaService(); + WxMaMsgService maMsgService = wxService.getMsgService(); + maMsgService.sendSubscribeMsg(subscribeMessage); + } catch (Exception e) { + log.error(String.valueOf(e)); + } + + } + + + + +} diff --git a/order/src/main/resources/dev/application.yml b/order/src/main/resources/dev/application.yml new file mode 100644 index 0000000..85623af --- /dev/null +++ b/order/src/main/resources/dev/application.yml @@ -0,0 +1,89 @@ +server: + port: 9503 + servlet: + context-path: /order + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/puhui_go?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +rocketmq: + name-server: 139.9.154.68:9876 + producer: + access-key: huifukeji + secret-key: HF123456. + #必须指定group + group: default-group + consumer: + access-key: huifukeji + secret-key: HF123456. + +jetcache: + statIntervalMinutes: 15 + areaInCacheName: false + local: + default: + type: linkedhashmap + keyConvertor: fastjson + remote: + default: + type: redis + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + keyConvertor: fastjson + broadcastChannel: projectA + valueEncoder: java + valueDecoder: java + poolConfig: + minIdle: 5 + maxIdle: 20 + maxTotal: 50 diff --git a/order/src/main/resources/dev/config.properties b/order/src/main/resources/dev/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/order/src/main/resources/dev/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/order/src/main/resources/dev/logback.xml b/order/src/main/resources/dev/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/order/src/main/resources/dev/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/order/src/main/resources/pre/application.yml b/order/src/main/resources/pre/application.yml new file mode 100644 index 0000000..874093a --- /dev/null +++ b/order/src/main/resources/pre/application.yml @@ -0,0 +1,56 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/order/src/main/resources/pre/config.properties b/order/src/main/resources/pre/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/order/src/main/resources/pre/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/order/src/main/resources/pre/logback.xml b/order/src/main/resources/pre/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/order/src/main/resources/pre/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/order/src/main/resources/prod/application.yml b/order/src/main/resources/prod/application.yml new file mode 100644 index 0000000..f3e38c7 --- /dev/null +++ b/order/src/main/resources/prod/application.yml @@ -0,0 +1,57 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/hsg?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 127.0.0.1 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/order/src/main/resources/prod/config.properties b/order/src/main/resources/prod/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/order/src/main/resources/prod/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/order/src/main/resources/prod/logback.xml b/order/src/main/resources/prod/logback.xml new file mode 100644 index 0000000..e509de0 --- /dev/null +++ b/order/src/main/resources/prod/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4f6d1ed --- /dev/null +++ b/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + + com.hfkj + puhui-go-parent + pom + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 2.0.5.RELEASE + + + + + UTF-8 + UTF-8 + 2.6.1 + 2.9.9 + + + + + commons-net + commons-net + 3.6 + + + net.coobird + thumbnailator + 0.4.8 + + + junit + junit + 4.12 + + test + + + org.springframework.boot + spring-boot-starter-test + test + + + com.github.binarywang + weixin-java-mp + 3.8.0 + + + + compile + + + + service + cweb + bweb + schedule + order + user + openapi + + + + diff --git a/schedule/pom.xml b/schedule/pom.xml new file mode 100644 index 0000000..4a5f85b --- /dev/null +++ b/schedule/pom.xml @@ -0,0 +1,45 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + com.hfkj + schedule + + + + com.hfkj + service + PACKT-SNAPSHOT + + + + + + + src/main/resources/${env} + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/schedule/schedule.iml b/schedule/schedule.iml new file mode 100644 index 0000000..e8ce722 --- /dev/null +++ b/schedule/schedule.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/schedule/src/main/java/com/hfkj/ScheduleApplication.java b/schedule/src/main/java/com/hfkj/ScheduleApplication.java new file mode 100644 index 0000000..a322fc5 --- /dev/null +++ b/schedule/src/main/java/com/hfkj/ScheduleApplication.java @@ -0,0 +1,30 @@ +package com.hfkj; + +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; +import com.hfkj.common.utils.SpringContextUtil; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +// @ComponentScan +@EnableTransactionManagement +@EnableScheduling +@EnableMethodCache(basePackages = "com.hfkj") +@EnableCreateCacheAnnotation +@ServletComponentScan +@MapperScan("com.hfkj.dao") +public class ScheduleApplication +{ + public static void main( String[] args ) + { + ApplicationContext app = SpringApplication.run(ScheduleApplication.class, args); + SpringContextUtil.setApplicationContext(app); + } + +} diff --git a/schedule/src/main/java/com/hfkj/config/AuthConfig.java b/schedule/src/main/java/com/hfkj/config/AuthConfig.java new file mode 100644 index 0000000..49348f7 --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/AuthConfig.java @@ -0,0 +1,169 @@ +package com.hfkj.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.hfkj.common.security.UserCenter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private static Logger log = LoggerFactory.getLogger(AuthConfig.class); + + @Resource + private UserCenter userCenter; + + /** + * 获取配置文件debug变量 + */ + @Value("${debug}") + private boolean debug = false; + + /** + * 解决18位long类型数据转json失去精度问题 + * @param converters + */ + @Override + public void configureMessageConverters(List> converters){ + MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); + + ObjectMapper objectMapper = jsonConverter.getObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + + converters.add(jsonConverter); + } + + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HandlerInterceptorAdapter() { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + if(debug){ + return true; + } + String token = request.getParameter("Authorization"); + if (StringUtils.isBlank(token)) { + token = request.getHeader("Authorization"); + } + if((StringUtils.isNotBlank(token) && userCenter.isTokenLogin(token)) || userCenter.isLogin(request)){//如果未登录,将无法使用任何接口 + userCenter.refreshCookie(request, response); + return true; + } else if(request instanceof StandardMultipartHttpServletRequest) { + StandardMultipartHttpServletRequest re = (StandardMultipartHttpServletRequest)request; + if(userCenter.isLogin(re.getRequest())){ + return true; + } else { + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } else{ + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } + }) + .addPathPatterns("/**") + .excludePathPatterns("/swagger-resources/**") + .excludePathPatterns("/**/api-docs") + .excludePathPatterns("/**/springfox-swagger-ui/**") + .excludePathPatterns("/**/swagger-ui.html") + .excludePathPatterns("/login/*") + .excludePathPatterns("/order/*") + .excludePathPatterns("/coupon/getCouponList") + .excludePathPatterns("/wechatpay/*") + .excludePathPatterns("/coupon/getCouponById") + .excludePathPatterns("/discount/getDiscountByQrCode") + .excludePathPatterns("/discount/getDiscountById") + .excludePathPatterns("/discount/getCouponByDiscount") + .excludePathPatterns("/discount/getDiscountByDiscountAgentId") + .excludePathPatterns("/highMerchantStore/getMerchantStoreById") + .excludePathPatterns("/highMerchantStore/getStoreListByCoupon") + .excludePathPatterns("/highMerchantStore/getStoreList") + .excludePathPatterns("/highMerchantStore/getMerchantList") + .excludePathPatterns("/highMerchantStore/getStoreListByMerchant") + .excludePathPatterns("/sms/sendSmsCode") + .excludePathPatterns("/sms/getSmsCode") + .excludePathPatterns("/activity/getWinLotteryList") + .excludePathPatterns("/user/login") + .excludePathPatterns("/user/unionPhoneLogin") + .excludePathPatterns("/user/getUnionId") + .excludePathPatterns("/highUser/setCacheParam") + .excludePathPatterns("/highUser/getCacheParam") + .excludePathPatterns("/highUser/delCacheParam") + .excludePathPatterns("/order/orderToH5Pay") + .excludePathPatterns("/order/orderToPay") + .excludePathPatterns("/test/*") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/outRechargeOrder/*") + .excludePathPatterns("/wechat/*") + .excludePathPatterns("/tuanyou/*") + .excludePathPatterns("/unionPay/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/common/*") + .excludePathPatterns("/order/qzOrderToPay") + .excludePathPatterns("/czOrder/orderRefundNotify") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highBrand/*") + .excludePathPatterns("/highGoodsType/*") + .excludePathPatterns("/sendSms/*") + .excludePathPatterns("/test/*") + .excludePathPatterns("/sms/*") + ; + } + + public String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/schedule/src/main/java/com/hfkj/config/ConfigListener.java b/schedule/src/main/java/com/hfkj/config/ConfigListener.java new file mode 100644 index 0000000..35eaeda --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/ConfigListener.java @@ -0,0 +1,23 @@ +package com.hfkj.config; + +import javax.annotation.Resource; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Resource + private SysConfig sysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + SysConst.setSysConfig(sysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/schedule/src/main/java/com/hfkj/config/CorsConfig.java b/schedule/src/main/java/com/hfkj/config/CorsConfig.java new file mode 100644 index 0000000..e7b150f --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/CorsConfig.java @@ -0,0 +1,49 @@ +package com.hfkj.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CorsConfig + * @Description: TODO () + * @Author 胡锐 + * @Date 2020/12/16 + **/ +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + List list = new ArrayList<>(); + list.add("*"); + corsConfiguration.setAllowedOrigins(list); + /* + // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等) + */ + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + return corsConfiguration; + } + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); + return new CorsFilter(source); + } +} diff --git a/schedule/src/main/java/com/hfkj/config/MultipartConfig.java b/schedule/src/main/java/com/hfkj/config/MultipartConfig.java new file mode 100644 index 0000000..a60902b --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/MultipartConfig.java @@ -0,0 +1,26 @@ +package com.hfkj.config; + +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.MultipartConfigElement; + +@Configuration +public class MultipartConfig { + + /** + * 文件上传配置 + * @return + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + //文件最大 + factory.setMaxFileSize("300MB"); //KB,MB + //设置总上传数据总大小 + factory.setMaxRequestSize("350MB"); + return factory.createMultipartConfig(); + } + +} diff --git a/schedule/src/main/java/com/hfkj/config/RedisConfig.java b/schedule/src/main/java/com/hfkj/config/RedisConfig.java new file mode 100644 index 0000000..c3dcc94 --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/RedisConfig.java @@ -0,0 +1,110 @@ +package com.hfkj.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableCaching //开启注解 +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} diff --git a/schedule/src/main/java/com/hfkj/config/SwaggerConfig.java b/schedule/src/main/java/com/hfkj/config/SwaggerConfig.java new file mode 100644 index 0000000..b95a4a2 --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.hfkj.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** +* SwaggerConfig.java +* 项目名称: +* 包: +* 类名称: SwaggerConfig.java +* 类描述: 构建restful api接口文档 +* 创建人: +* 创建时间: 2017 下午4:23:45 +*/ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + + /** + * 描述api的基本信息 + * 基本信息会展现在文档页面中 + * @return [api的基本信息] + */ + ApiInfo apiInfo() + { + return new ApiInfoBuilder().title("hgj-CWeb").description("提供给用户端的接口").termsOfServiceUrl("").version("1.0.0") + .contact(new Contact("", "", "")).build(); + } + + @Bean + public Docket customImplementation() + { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage("com")) + .build().directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class).apiInfo(apiInfo()); + } + +} diff --git a/schedule/src/main/java/com/hfkj/config/SysConfig.java b/schedule/src/main/java/com/hfkj/config/SysConfig.java new file mode 100644 index 0000000..084f5ec --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/SysConfig.java @@ -0,0 +1,31 @@ +package com.hfkj.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("sysConfig") +@ConfigurationProperties +@PropertySource("classpath:/config.properties") +public class SysConfig { + + private String fileUrl; + + private String cmsPath; + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } + + public String getCmsPath() { + return cmsPath; + } + + public void setCmsPath(String cmsPath) { + this.cmsPath = cmsPath; + } +} diff --git a/schedule/src/main/java/com/hfkj/config/SysConst.java b/schedule/src/main/java/com/hfkj/config/SysConst.java new file mode 100644 index 0000000..e4c91e8 --- /dev/null +++ b/schedule/src/main/java/com/hfkj/config/SysConst.java @@ -0,0 +1,19 @@ +package com.hfkj.config; + +public class SysConst { + + private static SysConfig sysConfig; + + public static void setSysConfig(SysConfig arg){ + sysConfig = arg; + } + + public static SysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new SysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/schedule/src/main/resources/dev/application.yml b/schedule/src/main/resources/dev/application.yml new file mode 100644 index 0000000..40eb448 --- /dev/null +++ b/schedule/src/main/resources/dev/application.yml @@ -0,0 +1,92 @@ +server: + port: 9509 + servlet: + context-path: /schedule + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/puhui_go?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true + + mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + + pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +rocketmq: + name-server: 139.9.154.68:9876 + producer: + access-key: huifukeji + secret-key: HF123456. + #必须指定group + group: default-group + consumer: + access-key: huifukeji + secret-key: HF123456. + +jetcache: + statIntervalMinutes: 15 + areaInCacheName: false + local: + default: + type: linkedhashmap + keyConvertor: fastjson + remote: + default: + type: redis + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + keyConvertor: fastjson + broadcastChannel: projectA + valueEncoder: java + valueDecoder: java + poolConfig: + minIdle: 5 + maxIdle: 20 + maxTotal: 50 diff --git a/schedule/src/main/resources/dev/config.properties b/schedule/src/main/resources/dev/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/schedule/src/main/resources/dev/logback.xml b/schedule/src/main/resources/dev/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/schedule/src/main/resources/dev/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/schedule/src/main/resources/pre/application.yml b/schedule/src/main/resources/pre/application.yml new file mode 100644 index 0000000..db63258 --- /dev/null +++ b/schedule/src/main/resources/pre/application.yml @@ -0,0 +1,59 @@ +server: + port: 9303 + servlet: + context-path: /schedule + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true + + mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + + pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/schedule/src/main/resources/pre/config.properties b/schedule/src/main/resources/pre/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/schedule/src/main/resources/pre/logback.xml b/schedule/src/main/resources/pre/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/schedule/src/main/resources/pre/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/schedule/src/main/resources/prod/application.yml b/schedule/src/main/resources/prod/application.yml new file mode 100644 index 0000000..54fea1f --- /dev/null +++ b/schedule/src/main/resources/prod/application.yml @@ -0,0 +1,59 @@ +server: + port: 9303 + servlet: + context-path: /schedule + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/hsg?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 127.0.0.1 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true + +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/schedule/src/main/resources/prod/config.properties b/schedule/src/main/resources/prod/config.properties new file mode 100644 index 0000000..e69de29 diff --git a/schedule/src/main/resources/prod/logback.xml b/schedule/src/main/resources/prod/logback.xml new file mode 100644 index 0000000..e509de0 --- /dev/null +++ b/schedule/src/main/resources/prod/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/service/pom.xml b/service/pom.xml new file mode 100644 index 0000000..fb74890 --- /dev/null +++ b/service/pom.xml @@ -0,0 +1,246 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + service + PACKT-SNAPSHOT + + + UTF-8 + UTF-8 + 1.8 + 2.6.1 + 2.9.9 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 1.3.1 + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + com.alicp.jetcache + jetcache-starter-redis + 2.5.0 + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.2.2 + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.2.10 + + + org.aspectj + aspectjweaver + 1.8.13 + + + tk.mybatis + mapper + 3.3.0 + + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + + mysql + mysql-connector-java + 5.1.34 + + + + + com.alibaba + druid + 1.0.20 + + + + io.springfox + springfox-swagger2 + ${springfox-version} + + + + io.springfox + springfox-swagger-ui + ${springfox-version} + + + + joda-time + joda-time + ${joda-time-version} + + + + org.slf4j + slf4j-api + 1.7.25 + + + org.slf4j + slf4j-simple + 1.7.25 + provided + + + org.apache.commons + commons-lang3 + 3.7 + + + org.apache.commons + commons-collections4 + 4.2 + + + commons-codec + commons-codec + 1.10 + + + commons-logging + commons-logging + 1.2 + + + + commons-fileupload + commons-fileupload + 1.4 + + + junit + junit + 4.12 + test + + + commons-io + commons-io + 2.6 + + + com.alibaba + fastjson + 1.2.7 + + + org.apache.httpcomponents + httpmime + 4.5.6 + + + com.aliyun + aliyun-java-sdk-core + 4.1.0 + + + + dom4j + dom4j + 1.6.1 + + + org.apache.poi + poi + 4.1.2 + + + org.apache.poi + poi-ooxml + 4.1.2 + + + org.apache.poi + poi-ooxml-schemas + 4.1.2 + + + com.google.zxing + javase + 3.3.0 + + + com.google.code.gson + gson + + + org.slf4j + slf4j-api + 1.7.7 + + + com.thoughtworks.xstream + xstream + 1.4.11.1 + + + com.github.binarywang + weixin-java-miniapp + 3.8.0 + + + com.alibaba + easyexcel + 2.2.6 + + + com.sun.jersey + jersey-client + 1.16 + + + + + + src/main/resources/${env} + false + + + + diff --git a/service/src/main/java/com/hfkj/common/Base64Util.java b/service/src/main/java/com/hfkj/common/Base64Util.java new file mode 100644 index 0000000..9c0d71e --- /dev/null +++ b/service/src/main/java/com/hfkj/common/Base64Util.java @@ -0,0 +1,42 @@ +package com.hfkj.common; + +import java.util.Base64; + +public class Base64Util { + /** + * @param data + * @return str + * @throws Exception + */ + public static String encode(String data) throws Exception{ +// String encodeBase64 = new BASE64Encoder().encode(data.getBytes("utf-8")); + String encodeBase64 = Base64.getEncoder().encodeToString(data.getBytes("utf-8")); + String safeBase64Str = encodeBase64.replace('+', '-'); + safeBase64Str = safeBase64Str.replace('/', '_'); + safeBase64Str = safeBase64Str.replaceAll("=", ""); + return safeBase64Str.replaceAll("\\s*", ""); + } + + /** + * @param safeBase64Str + * @return str + * @throws Exception + */ + public static String decode(final String safeBase64Str) throws Exception{ + String base64Str = safeBase64Str.replace('-', '+'); + base64Str = base64Str.replace('_', '/'); + int mod4 = base64Str.length() % 4; + if(mod4 > 0){ + base64Str += "====".substring(mod4); + } + +// byte[] ret = new BASE64Decoder().decodeBuffer(base64Str); + byte[] ret = Base64.getDecoder().decode(base64Str); + return new String(ret, "utf-8"); + } + + public static void main(String[] args) throws Exception { + System.out.println(encode("abcd1234")); + System.out.println(decode("YWJjZDEyMzQ")); + } +} diff --git a/service/src/main/java/com/hfkj/common/QRCodeGenerator.java b/service/src/main/java/com/hfkj/common/QRCodeGenerator.java new file mode 100644 index 0000000..0e08f01 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/QRCodeGenerator.java @@ -0,0 +1,43 @@ +package com.hfkj.common; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.WriterException; +import com.google.zxing.client.j2se.MatrixToImageWriter; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; + +import java.io.File; +import java.io.IOException; + +/** + * @Auther: 胡锐 + * @Description: 生成二维码 + * @Date: 2021/3/27 12:07 + */ +public class QRCodeGenerator { + + public static void generateQRCodeImage(String text, int width, int height, String filePath) throws WriterException, IOException { + QRCodeWriter qrCodeWriter = new QRCodeWriter(); + + BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height); + + File file = new File(filePath); + if(!file.exists()){ + file.mkdirs(); + } + //Path path = FileSystems.getDefault().getPath(filePath); + MatrixToImageWriter.writeToFile(bitMatrix, "PNG", file); + + } + + public static void main(String[] args) { + try { + generateQRCodeImage("This is my first QR Code", 350, 350, "D:\\/ss/qr1.png"); + } catch (WriterException e) { + System.out.println("Could not generate QR Code, WriterException :: " + e.getMessage()); + } catch (IOException e) { + System.out.println("Could not generate QR Code, IOException :: " + e.getMessage()); + } + + } +} diff --git a/service/src/main/java/com/hfkj/common/exception/AppException.java b/service/src/main/java/com/hfkj/common/exception/AppException.java new file mode 100644 index 0000000..307f7e6 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/AppException.java @@ -0,0 +1,10 @@ +package com.hfkj.common.exception; + +/** + * 数据异常,只影响部分功能的异常,例如本应该为x的数据,莫名其妙为Y + */ +public class AppException extends BaseException { + AppException(String errorCode, String errorMsg) { + super(errorCode,errorMsg); + } +} diff --git a/service/src/main/java/com/hfkj/common/exception/BaseException.java b/service/src/main/java/com/hfkj/common/exception/BaseException.java new file mode 100644 index 0000000..4af58db --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/BaseException.java @@ -0,0 +1,23 @@ +package com.hfkj.common.exception; + +/** + * sl框架基础异常,不允许自己new实例,需要同步工具类进行实例化 + */ +public class BaseException extends RuntimeException { + protected String errorCode; + protected String errorMsg; + + BaseException(String errorCode, String errorMsg) { + super("errorCode="+errorCode+", errorMsg="+errorMsg); + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + public String getErrorCode() { + return errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } +} diff --git a/service/src/main/java/com/hfkj/common/exception/BizException.java b/service/src/main/java/com/hfkj/common/exception/BizException.java new file mode 100644 index 0000000..87b00f8 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/BizException.java @@ -0,0 +1,10 @@ +package com.hfkj.common.exception; + +/** + * 用户操作异常 + */ +public class BizException extends BaseException { + BizException(String errorCode, String errorMsg) { + super(errorCode,errorMsg); + } +} diff --git a/service/src/main/java/com/hfkj/common/exception/ErrorCode.java b/service/src/main/java/com/hfkj/common/exception/ErrorCode.java new file mode 100644 index 0000000..b5b9e33 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/ErrorCode.java @@ -0,0 +1,160 @@ +package com.hfkj.common.exception; + +/** + * + * @ClassName: ErrorCode + * @Description: + * 代码code规则: + * 0000-0999 系统异常 + * 1000-1999 app异常 + * 2000-2999 biz异常 + * 999999 未知异常 + * @author: 机器猫 + * @date: 2018年8月12日 上午11:43:30 + * + * @Copyright: 2018 www.shinwoten.com Inc. All rights reserved. + */ +public enum ErrorCode { + + //////////////////sys//////////////// + DB_CONNECT_ERROR("0000","数据库连接异常"), + FTP_CONNECT_ERROR("0001","FTP服务器连接失败"), + FTP_CONFIG_NOT_FOUND("0002","FTP服务地址路径配置缺失"), + + //////////////////APP/////////////// + WECHAT_DECRYPT_ERROR("3001","微信解密错误->%s"), + WECHAT_LOGIN_ERROR("3002","微信登录失败"), + WECHAT_LOGIN_TEACHER_ERROR("3003","当前微信用户不是老师,请联系管理员"), + SERVER_BUSY_ERROR("3004","服务器繁忙,请稍后重试"), + + //////////////////业务异常///////////// + COMMON_ERROR("2000",""), + REQ_PARAMS_ERROR("2001","请求参数校验失败"), + PHONE_REGISTER_ERROR("2002","手机号已注册"), + VERIFICATION_CODE_ERROR("2003","验证码错误"), + SEC_USER_OR_PASSWORD_ERROR("2005","手机号或密码错误"), + NOT_FOUND_PHONE("2006","未找到手机号"), + OLD_PASSWORD("2007","旧密码错误"), + BS_COMPANY_UNAVAILABLE("2013","公司不可用"), + NOT_FOUND_USER_ERROR("2016","用户不存在"), + NOT_FOUND_COMPANY("2018","未找到公司"), + USER_PHONE_HAS_ONE_ERROR("2020","该用户电话已被绑定,请更换"), + USER_ROLE_PERMISSION_ALLOT_ERROR("2011","请联系管理员核实用户角色权限是否启用"), + COMPANY_REGION_HAS_IN_CITY_ERROR("2031","单位区域必须选择到市级区域"), + UN_FIND_ORGANIZATION_ERROR("2032","未找到该部门信息"), + COMPANY_ADMIN_USER_ERROR("2033","公司主账号异常"), + ORGANIZATION_NAME_IS_EXIST_ERROR("2034","部门名称已经存在"), + TOP_ORGANIZATION_DELETE_ERROR("2035","顶级组织不允许删除"), + SON_ORGANIZATION_IS_EXIST_ERROR("2036","存在子级部门,不能删除"), + ORG_REGION_HAS_IN_REGION_ERROR("2037","区级单位所属区域必须选择到区级"), + CMS_CATEGORY_NOT_FOUND("2038", "未找到分类"), + CMS_CATEGORY_MODULE_NOT_FOUND("2039", "未找到模板"), + CMS_CATEGORY_MODULE_EXISTS("2040", "同一分类下存在相同名称的模板"), + CMS_CATEGORY_EXISTS_CHILDREN("2041", "分类存在子级,无法删除"), + CMS_CATEGORY_EXISTS("2042", "存在相同编码的分类"), + CMS_CREATE_HTML_ERROR("2043", "生成页面错误"), + CMS_CONTENT_NOT_FOUND("2044", "未找到内容信息"), + CMS_PATCH_NOT_FOUND("2045", "未找到附件"), + MENU_TREE_HAS_NOT_ERROR("2041","该主角色没有权限"), + PERMISSION_NAME_IS_EXIST_ERROR("2043","该权限名称已经存在"), + PERMISSION_CODE_IS_EXIST_ERROR("2044","该权限编码已经存在"), + MENU_TYPE_IS_NOT_EDIT_ERROR("2046","菜单类型不允许修改"), + MENU_HAS_SON_ERROR("2047","存在子菜单,不能删除"), + ROLE_NAME_IS_EXIST_ERROR("2048","该角色名已经存在"), + USER_LOGIN_NAME_IS_EXIST_ERROR("2049","该登录用户名已经存在"), + USER_ROLE_HAS_ALLOT_ERROR("2050","该角色已分配给用户,不能删除"), + COMPANY_NAME_IS_EXIST_ERROR("2055","公司已经存在"), + UN_FIND_TOP_ORGANIZATION_ERROR("2051","找不到顶级组织架构"), + BASE_ORGANIZATION_HAS_NOT_MANAGE_ERROR("2056","该部门暂无管理员"), + BASE_ORGANIZATION_HAS_NOT_PARENT_ERROR("2057","该部门无上级部门"), + SEC_USER_EXPIRED("2068","用户身份错误或已过期"), + UN_MEMBER_ERROR("2084","未找到用户"), + SING_ERROR("2089","签名错误"), + REGION_ABBREVIATE_EXIST("2098","地区简称已存在"), + NOT_FOUND_CHANNEL("2099","未找到渠道商"), + PASSWORD_ERROR("2102","密码错误"), + SMS_CODE_ERROR("2103","验证码错误"), + ID_CARD_NUM_IS_ERROR("2104","身份证号码错误"), + MERCHANT_NOF_FOUND("2105","未找到商户"), + MERCHANT_STORE_NOF_FOUND("2106","未找到商户门店"), + PHONE_NUM_IS_ERROR("2107","请输入正确的电话号码"), + PHONE_NUM_EXISTED("2108","电话号码已被使用"), + MERCHANT_STATUS_ERROR("2109","商户状态不正常,请联系管理员"), + SELECT_HANDSEL_COUPON_ERROR("2110","请选择赠送卡卷名单"), + NOT_FOUND_COUPON("2111","未找到卡券信息"), + WRITE_COUPON_NUMBER_ERROR("2112","请填写卡卷数量"), + COUPON_UNABLE_UP_SHELF("2113","卡卷状态错误"), + NOT_FOUND_APPROVE("2114","未找到审批记录"), + APPROVE_PROCESSED("2115","审批已处理"), + COUPON_STOCK_ERROR("2116","卡卷库存数量错误"), + COUPON_TYPE_ERROR("2117","卡卷类型错误"), + COUPON_STATUS_ERROR("2118","卡卷状态错误"), + GOODS_PRICE_REFER_ERROR("2119","未找到价格信息"), + DISCOUNT_PRICE_BIG_SALES_PRICE_ERROR("2120","折扣价格不能大于原价"), + INVALID_TIME_BIG_EFFECTIVE_TIME_ERROR("2121","失效时间不能大于生效时间"), + PRICE_REFER_STATUS_ERROR("2122","暂时无法增加,有处于在待编辑、待生效、审批中的价格"), + NEED_WRITE_NEW_SALE_PRICE("2123","请填写正确的新销售价格"), + NEED_WRITE_DISCOUNT_PRICE("2124","请填写正确的折扣数,折扣数范围【0】 ~ 【10】"), + DISCOUNT_PRICE_RANGE("2125","请输入正确的"), + TEL_EXISTED("2126","联系方式已被使用"), + ORDER_TYPE_ERROR("2127","订单类型错误"), + COUPON_STOCK_INSUFFICIENT("2118","卡卷库存数量不足"), + NOT_FOUND_ORDER("2119","未找到订单信息"), + ORDER_NO_STAY_PAY("2120","订单不处于待支付状态"), + NOT_FOUND_COUPON_CODE("2121","销售码不存在"), + COUPON_CODE_STATUS("2122","卡券码状态错误"), + COUPON_CODE_OVERDUE("2122","卡券码已过期"), + COUPON_CODE_NAME("2123","卡券名称已存在"), + AGENT_NAME("2124","代理商名称已存在"), + NOT_FOUND_DISCOUNT("2125","未找到优惠券信息"), + NOT_FOUND_AGENT("2126","未找到代理商信息"), + DISCOUNT_STOCK_COUNT_ERROR("2127","优惠券库存数量不足"), + RECHARGE_CLOSE("2128","系统已关闭,请稍后充值"), + REPEAT_SET_USER_PAY_PWD("2129","已设置支付密码"), + NOT_SET_USER_PAY_PWD("2130","未设置支付密码"), + NOT_ENTER_USER_PAY_PWD("2131","未输入支付密码"), + USER_PAY_PWD_ERROR("2132","支付密码错误"), + NO_BIND_PHONE("2133","未绑定手机号"), + title_("2134","名称已存在"), + ADD_REPEATEDLY("2135","重复添加"), + + + STATUS_ERROR("3000","状态错误"), + ADD_DATA_ERROR("3001","增加数据失败"), + UPDATE_DATA_ERROR("3002","修改数据失败"), + DELETE_DATA_ERROR("3003","删除数据失败"), + COMPETENCE_INSUFFICIENT("3004","权限不足"), + REQUEST_ERROR("3005","请求错误"), + REQUEST_TIMED_OUT("3006","请求超时,请稍后重试"), + + MSG_EVENT_NULL("2999","消息类型为空"), + USE_VISIT_ILLEGAL("4001","用户身份错误"), + RC_VISIT_ERROR("2998",""), + UNKNOW_ERROR("999999","未知异常"), + EXCEL_ERROR("80000","Excel处理异常"), + ;//注意:上面为逗号,此次为分号 + + + private String code; + private String msg; + ErrorCode(String code, String msg){ + this.code = code; + this.msg = msg; + } + + public String getCode() { + return code; + } + +// public void setCode(String code) { +// this.code = code; +// } + + public String getMsg() { + return msg; + } + +// public void setMsg(String msg) { +// this.msg = msg; +// } +} diff --git a/service/src/main/java/com/hfkj/common/exception/ErrorHelp.java b/service/src/main/java/com/hfkj/common/exception/ErrorHelp.java new file mode 100644 index 0000000..19716be --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/ErrorHelp.java @@ -0,0 +1,23 @@ +package com.hfkj.common.exception; + +public class ErrorHelp { + + public static BaseException genException(SysCode sc, ErrorCode ec, Object... args){ + String errorCode = sc.getCode()+ec.getCode(); + StringBuilder sb = new StringBuilder(); + if (args != null && args.length != 0) { + for(Object o : args){ + sb.append(o.toString()); + } + } + String errorMsg = ec.getMsg()+sb.toString();//@TODO 这里需要处理变参 + char a = ec.getCode().charAt(0); + if (a == '0') {//系统异常 + return new SysException(errorCode,errorMsg); + } else if (a == '1') {//APP异常 + return new AppException(errorCode,errorMsg); + } else {//业务异常 + return new BizException(errorCode,errorMsg); + } + } +} diff --git a/service/src/main/java/com/hfkj/common/exception/SysCode.java b/service/src/main/java/com/hfkj/common/exception/SysCode.java new file mode 100644 index 0000000..5e0eaa9 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/SysCode.java @@ -0,0 +1,24 @@ +package com.hfkj.common.exception; + +public enum SysCode { + System("10","System"), + Auth("20","Auth"), + MiniProgram("30","小程序"); + + private String code; + private String name; + + SysCode(String code,String name){ + this.code = code; + this.name = name; + } + + public String getCode(){ + return this.code; + } + + public String getName() { + return this.name; + } + +} diff --git a/service/src/main/java/com/hfkj/common/exception/SysException.java b/service/src/main/java/com/hfkj/common/exception/SysException.java new file mode 100644 index 0000000..f0a07dc --- /dev/null +++ b/service/src/main/java/com/hfkj/common/exception/SysException.java @@ -0,0 +1,10 @@ +package com.hfkj.common.exception; + +/** + * 系统异常,例如网络断开,数据库不可访问等影响系统正常运行的异常 + */ +public class SysException extends BaseException { + SysException(String errorCode, String errorMsg) { + super(errorCode,errorMsg); + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/entity/AliPayReqInfo.java b/service/src/main/java/com/hfkj/common/pay/entity/AliPayReqInfo.java new file mode 100644 index 0000000..da9e050 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/entity/AliPayReqInfo.java @@ -0,0 +1,151 @@ +package com.hfkj.common.pay.entity; + +/** + * @Description: 支付宝統一下单参数 + */ +public class AliPayReqInfo { + private String timeout_express; //该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。 90m + private String total_amount; //必填。订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 9.00 + private String seller_id; //收款支付宝用户ID。 如果该值为空,则默认为商户签约账号对应的支付宝用户ID 2088102147948060 + private String product_code; //销售产品码,商家和支付宝签约的产品码 QUICK_MSECURITY_PAY + private String body; //对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 Iphone6 16G + private String subject; //必填。商品的标题/交易标题/订单标题/订单关键字等。 大乐透 + private String out_trade_no; //必填。商户网站唯一订单号 70501111111S001111119 + private String time_expire; //绝对超时时间,格式为yyyy-MM-dd HH:mm。 2016-12-31 10:05 + private String goods_type; //商品主类型 :0-虚拟类商品,1-实物类商品 0 + private String promo_params; //优惠参数 + private String passback_params; //必填。公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝只会在同步返回(包括跳转回商户网站)和异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝。 merchantBizType%3d3C%26merchantBizNo%3d2016010101111 + private String enable_pay_channels; //可用渠道,用户只能在指定渠道范围内支付 + private String store_id; //商户门店编号 NJ_001 + private String specified_channel; //指定渠道,目前仅支持传入pcredit + private String disable_pay_channels; //禁用渠道,用户不可用指定渠道支付 + private String business_params; //商户传入业务信息,具体值要和支付宝约定,应用于安全,营销等参数直传场景,格式为json格式 + + public String getTimeout_express() { + return timeout_express; + } + + public void setTimeout_express(String timeout_express) { + this.timeout_express = timeout_express; + } + + public String getTotal_amount() { + return total_amount; + } + + public void setTotal_amount(String total_amount) { + this.total_amount = total_amount; + } + + public String getSeller_id() { + return seller_id; + } + + public void setSeller_id(String seller_id) { + this.seller_id = seller_id; + } + + public String getProduct_code() { + return product_code; + } + + public void setProduct_code(String product_code) { + this.product_code = product_code; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getSubject() { + return subject; + } + + public void setSubject(String subject) { + this.subject = subject; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getGoods_type() { + return goods_type; + } + + public void setGoods_type(String goods_type) { + this.goods_type = goods_type; + } + + public String getPromo_params() { + return promo_params; + } + + public void setPromo_params(String promo_params) { + this.promo_params = promo_params; + } + + public String getPassback_params() { + return passback_params; + } + + public void setPassback_params(String passback_params) { + this.passback_params = passback_params; + } + + public String getEnable_pay_channels() { + return enable_pay_channels; + } + + public void setEnable_pay_channels(String enable_pay_channels) { + this.enable_pay_channels = enable_pay_channels; + } + + public String getStore_id() { + return store_id; + } + + public void setStore_id(String store_id) { + this.store_id = store_id; + } + + public String getSpecified_channel() { + return specified_channel; + } + + public void setSpecified_channel(String specified_channel) { + this.specified_channel = specified_channel; + } + + public String getDisable_pay_channels() { + return disable_pay_channels; + } + + public void setDisable_pay_channels(String disable_pay_channels) { + this.disable_pay_channels = disable_pay_channels; + } + + public String getBusiness_params() { + return business_params; + } + + public void setBusiness_params(String business_params) { + this.business_params = business_params; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/entity/OrderType.java b/service/src/main/java/com/hfkj/common/pay/entity/OrderType.java new file mode 100644 index 0000000..0763530 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/entity/OrderType.java @@ -0,0 +1,46 @@ +package com.hfkj.common.pay.entity; + +public enum OrderType { + // 建议将支付频率高的模块放在前面 + GOODS_ORDER("GOODS_ORDER", "goodsOrderService", "购买商品"), + RECHARGE_ORDER("RECHARGE_ORDER", "rechargeOrderService", "充值订单"), + KFC_ORDER("KFC", "kfcOrderService", "KFC订单"), + CINEMA_ORDER("CINEMA", "cinemaOrderService", "电影票订单"), + MOBILE_ORDER("MOBILE", "mobileOrderService", "话费充值订单"), + TEST("TEST", "testPayService", "支付测试"), + ; + + private String moduleCode; + private String service; + private String moduleName; + + private OrderType(String moduleCode, String service, String moduleName) { + this.moduleCode = moduleCode; + this.service = service; + this.moduleName = moduleName; + } + + public String getModuleCode() { + return moduleCode; + } + + private void setModuleCode(String moduleCode) { + this.moduleCode = moduleCode; + } + + public String getService() { + return service; + } + + private void setService(String service) { + this.service = service; + } + + public String getModuleName() { + return moduleName; + } + + private void setModuleName(String moduleName) { + this.moduleName = moduleName; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/entity/WeChatPayReqInfo.java b/service/src/main/java/com/hfkj/common/pay/entity/WeChatPayReqInfo.java new file mode 100644 index 0000000..da672ce --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/entity/WeChatPayReqInfo.java @@ -0,0 +1,240 @@ +package com.hfkj.common.pay.entity; +import java.io.Serializable; + +/** + * @Description: 微信統一下单参数 + */ +public class WeChatPayReqInfo implements Serializable { + + private static final long serialVersionUID = -7642108447915413137L; + private String appid; // 公众号id 必填 + private String mch_id; // 商户号 必填 + private String sub_appid; // 微信支付分配的子商户号 必填 + private String sub_mch_id; // 微信支付分配的子商户号 必填 + private String nonce_str; // 随机字符串 必填 + private String sign; // 签名 必填 + private String device_info; // 设备号 可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB" + private String body; // 商品描述 必填 + private String detail; // 商品详情 + private String attach; // 附加数据 + private String out_trade_no; // 商户订单号 必填 + private String fee_type; // 货币类型 默认为人民币CNY + private Integer total_fee; // 总金额 传入int型的数据 必填 + private String spbill_create_ip; // 终端ip 必填 + private String time_start; // 交易起始时间 订单生成时间 + private String time_expire; // 交易结束时间 订单失效时间 + private String goods_tag; // 订单优惠标记 + private String notify_url; // 通知url 必填 + private String trade_type; // 交易类型 JSAPI,NATIVE,APP 必填 + private String product_id; //商品id trade_type=NATIVE时(即扫码支付),此参数必传 + private String limit_pay; // 指定支付方式 no_credit--可限制用户不能使用信用卡支付 + private String openid; // 用户标识(trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识) + private String sub_openid; // 用户标识(trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识) + private String profit_sharing; + + public String getProfit_sharing() { + return profit_sharing; + } + + public void setProfit_sharing(String profit_sharing) { + this.profit_sharing = profit_sharing; + } + + public String getSub_openid() { + return sub_openid; + } + + public void setSub_openid(String sub_openid) { + this.sub_openid = sub_openid; + } + + private String scene_info; // 该字段用于统一下单时上报场景信息,目前支持上报实际门店信息 格式{"store_id":// "SZT10000", "store_name":"腾讯大厦腾大餐厅"} + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public Integer getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(Integer total_fee) { + this.total_fee = total_fee; + } + + public String getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getTime_start() { + return time_start; + } + + public void setTime_start(String time_start) { + this.time_start = time_start; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getGoods_tag() { + return goods_tag; + } + + public void setGoods_tag(String goods_tag) { + this.goods_tag = goods_tag; + } + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getProduct_id() { + return product_id; + } + + public void setProduct_id(String product_id) { + this.product_id = product_id; + } + + public String getLimit_pay() { + return limit_pay; + } + + public void setLimit_pay(String limit_pay) { + this.limit_pay = limit_pay; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getScene_info() { + return scene_info; + } + + public void setScene_info(String scene_info) { + this.scene_info = scene_info; + } + + public String getSub_mch_id() { + return sub_mch_id; + } + + public void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public String getSub_appid() { + return sub_appid; + } + + public void setSub_appid(String sub_appid) { + this.sub_appid = sub_appid; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/entity/WechatCallBackInfo.java b/service/src/main/java/com/hfkj/common/pay/entity/WechatCallBackInfo.java new file mode 100644 index 0000000..3b73b6b --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/entity/WechatCallBackInfo.java @@ -0,0 +1,154 @@ +package com.hfkj.common.pay.entity; + +/** + * 统一下单返回结果 + * @author phil + * @data 2017年6月27日 + * + */ +public class WechatCallBackInfo { + + private static final long serialVersionUID = 9030465964635155064L; + private String appid; // 公众号id + private String mch_id; // 商户号 + private String nonce_str; // 随机字符串 + private String sign; // 签名 + private String return_code; // 返回状态码 + private String return_msg; // 返回信息 + // 以下字段在return_code为SUCCESS的时候有返回(包括父类) + private String device_info; // 设备号 + private String result_code; // 业务结果 SUCCESS/FAIL + private String err_code; // 错误代码 + private String err_code_des; // 错误代码描述 + // 以下字段在return_code 和result_code都为SUCCESS的时候有返回 + private String trade_type; // 交易类型 + private String prepay_id; // 预支付交易会话标识,有效期为2小时 + private String code_url; // 二维码链接 + + public static long getSerialVersionUID() { + return serialVersionUID; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getCode_url() { + return code_url; + } + + public void setCode_url(String code_url) { + this.code_url = code_url; + } + + @Override + public String toString() { + return "WechatCallBackInfo{" + + "appid='" + appid + '\'' + + ", mch_id='" + mch_id + '\'' + + ", nonce_str='" + nonce_str + '\'' + + ", sign='" + sign + '\'' + + ", return_code='" + return_code + '\'' + + ", return_msg='" + return_msg + '\'' + + ", device_info='" + device_info + '\'' + + ", result_code='" + result_code + '\'' + + ", err_code='" + err_code + '\'' + + ", err_code_des='" + err_code_des + '\'' + + ", trade_type='" + trade_type + '\'' + + ", prepay_id='" + prepay_id + '\'' + + ", code_url='" + code_url + '\'' + + '}'; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/entity/WechatPayReturnParam.java b/service/src/main/java/com/hfkj/common/pay/entity/WechatPayReturnParam.java new file mode 100644 index 0000000..a0dff02 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/entity/WechatPayReturnParam.java @@ -0,0 +1,151 @@ +package com.hfkj.common.pay.entity; +/** + * + * @Description: 微信支付异步回调参数 + */ +public class WechatPayReturnParam { + private String appid; //是 String(32) wx8888888888888888 微信开放平台审核通过的应用APPID + private String attach; //否 String(128) 123456 商家数据包,原样返回 + private String bank_type; //是 String(16) CMC 银行类型,采用字符串类型的银行标识,银行类型见银行列表 + private String cash_fee; //是 Int 100 现金支付金额订单现金支付金额,详见支付金额 + private String fee_type; //否 String(8) CNY 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 + private String is_subscribe; //是 String(1) Y 用户是否关注公众账号,Y-关注,N-未关注 + private String mch_id; //是 String(32) 1900000109 微信支付分配的商户号 + private String nonce_str; //是 String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串,不长于32位 + private String openid; //是 String(128) wxd930ea5d5a258f4f 用户在商户appid下的唯一标识 + private String out_trade_no; //是 String(32) 1212321211201407033568112322 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。 + private String result_code; //是 String(16) SUCCESS SUCCESS/FAIL + private String return_code; + private String time_end; //是 String(14) 20141030133525 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规 + private String total_fee; //是 Int 100 订单总金额,单位为分 + private String trade_type; //是 String(16) APP APP + private String transaction_id; //微信支付订单号 + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getBank_type() { + return bank_type; + } + + public void setBank_type(String bank_type) { + this.bank_type = bank_type; + } + + public String getCash_fee() { + return cash_fee; + } + + public void setCash_fee(String cash_fee) { + this.cash_fee = cash_fee; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public String getIs_subscribe() { + return is_subscribe; + } + + public void setIs_subscribe(String is_subscribe) { + this.is_subscribe = is_subscribe; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getTime_end() { + return time_end; + } + + public void setTime_end(String time_end) { + this.time_end = time_end; + } + + public String getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(String total_fee) { + this.total_fee = total_fee; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/entity/WechatReturn.java b/service/src/main/java/com/hfkj/common/pay/entity/WechatReturn.java new file mode 100644 index 0000000..26ab2fe --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/entity/WechatReturn.java @@ -0,0 +1,77 @@ +package com.hfkj.common.pay.entity; + +public class WechatReturn { + private String appid; + private String mch_id; + private String nonce_str; + private String prepay_id; + private String result_code; + private String return_code; + private String return_msg; + private String trade_type; + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/HttpReqUtil.java b/service/src/main/java/com/hfkj/common/pay/util/HttpReqUtil.java new file mode 100644 index 0000000..1dd670a --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/HttpReqUtil.java @@ -0,0 +1,329 @@ +package com.hfkj.common.pay.util; + +import org.apache.commons.lang3.StringUtils; + +import javax.imageio.ImageIO; +import javax.net.ssl.*; +import javax.servlet.http.HttpServletRequest; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +/** + * Http连接工具类 + * + * @author phil + * @date 2017年7月2日 + * + */ +public class HttpReqUtil { + + private static int DEFAULT_CONNTIME = 5000; + private static int DEFAULT_READTIME = 5000; + private static int DEFAULT_UPLOAD_READTIME = 10 * 1000; + public static String POST = "POST"; + public static String GET = "GET"; + /** + * http请求 + * + * @param method + * 请求方法GET/POST + * @param path + * 请求路径 + * @param timeout + * 连接超时时间 默认为5000 + * @param readTimeout + * 读取超时时间 默认为5000 + * @param data + * 数据 + * @return + */ + private static String defaultConnection(String method, String path, int timeout, int readTimeout, String data, String encoding) + throws Exception { + String result = ""; + URL url = new URL(path); + if (url != null) { + HttpURLConnection conn = getConnection(method, url); + conn.setConnectTimeout(timeout == 0 ? DEFAULT_CONNTIME : timeout); + conn.setReadTimeout(readTimeout == 0 ? DEFAULT_READTIME : readTimeout); + if (data != null && !"".equals(data)) { + OutputStream output = conn.getOutputStream(); + output.write(data.getBytes("UTF-8")); + output.flush(); + output.close(); + } + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + InputStream input = conn.getInputStream(); + result = IOUtil.inputStreamToString(input, encoding); + input.close(); + conn.disconnect(); + } + } + return result; + } + + /** + * 根据url的协议选择对应的请求方式 + * + * @param method + * 请求的方法 + * @return + * @throws IOException + */ + private static HttpURLConnection getConnection(String method, URL url) throws IOException { + HttpURLConnection conn = null; + if ("https".equals(url.getProtocol())) { + SSLContext context = null; + try { + context = SSLContext.getInstance("SSL", "SunJSSE"); + context.init(new KeyManager[0], new TrustManager[] { new MyX509TrustManager() }, + new java.security.SecureRandom()); + } catch (Exception e) { + throw new IOException(e); + } + HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection(); + connHttps.setSSLSocketFactory(context.getSocketFactory()); + connHttps.setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String arg0, SSLSession arg1) { + return true; + } + }); + conn = connHttps; + } else { + conn = (HttpURLConnection) url.openConnection(); + } + conn.setRequestMethod(method); + conn.setUseCaches(false); + conn.setDoInput(true); + conn.setDoOutput(true); + return conn; + } + + /** + * 设置参数 + * + * @param map + * 参数map + * @param path + * 需要赋值的path + * @param charset + * 编码格式 默认编码为utf-8(取消默认) + * @return 已经赋值好的url 只需要访问即可 + */ + public static String setParmas(Map map, String path, String charset) throws Exception { + String result = ""; + boolean hasParams = false; + if (path != null && !"".equals(path)) { + if (map != null && map.size() > 0) { + StringBuilder builder = new StringBuilder(); + Set> params = map.entrySet(); + for (Entry entry : params) { + String key = entry.getKey().trim(); + String value = entry.getValue().trim(); + if (hasParams) { + builder.append("&"); + } else { + hasParams = true; + } + if (charset != null && !"".equals(charset)) { + // builder.append(key).append("=").append(URLDecoder.(value,charset)); + builder.append(key).append("=").append(IOUtil.urlEncode(value, charset)); + } else { + builder.append(key).append("=").append(value); + } + } + result = builder.toString(); + } + } + return doUrlPath(path, result).toString(); + } + + /** + * 设置连接参数 + * + * @param path + * 路径 + * @return + */ + private static URL doUrlPath(String path, String query) throws Exception { + URL url = new URL(path); + if (StringUtils.isEmpty(path)) { + return url; + } + if (StringUtils.isEmpty(url.getQuery())) { + if (path.endsWith("?")) { + path += query; + } else { + path = path + "?" + query; + } + } else { + if (path.endsWith("&")) { + path += query; + } else { + path = path + "&" + query; + } + } + return new URL(path); + } + + /** + * 默认的http请求执行方法,返回 + * + * @param method + * 请求的方法 POST/GET + * @param path + * 请求path 路径 + * @param map + * 请求参数集合 + * @param data + * 输入的数据 允许为空 + * @return + */ + public static String HttpDefaultExecute(String method, String path, Map map, String data, String encoding) { + String result = ""; + try { + String url = setParmas((TreeMap) map, path, ""); + result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data, encoding); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 默认的https执行方法,返回 + * + * @param method + * 请求的方法 POST/GET + * @param path + * 请求path 路径 + * @param map + * 请求参数集合 + * @param data + * 输入的数据 允许为空 + * @return + */ + public static String HttpsDefaultExecute(String method, String path, Map map, String data, String encoding) { + String result = ""; + try { + String url = setParmas((TreeMap) map, path, ""); + result = defaultConnection(method, url, DEFAULT_CONNTIME, DEFAULT_READTIME, data, encoding); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 文件路径 + * + * @param mediaUrl + * url 例如 + * http://su.bdimg.com/static/superplus/img/logo_white_ee663702.png + * @return logo_white_ee663702.png + */ + private static String getFileName(String mediaUrl) { + String result = mediaUrl.substring(mediaUrl.lastIndexOf("/") + 1, mediaUrl.length()); + return result; + } + + /** + * 根据内容类型判断文件扩展名 + * + * @param ContentType + * 内容类型 + * @return + */ + private static String getFileExt(String contentType) { + String fileExt = ""; + if (contentType == null) { + return null; + } + if (contentType.contains("image/jpeg")) { + fileExt = ".jpg"; + } else if (contentType.contains("audio/mpeg")) { + fileExt = ".mp3"; + } else if (contentType.contains("audio/amr")) { + fileExt = ".amr"; + } else if (contentType.contains("video/mp4")) { + fileExt = ".mp4"; + } else if (contentType.contains("video/mpeg4")) { + fileExt = ".mp4"; + } else if (contentType.contains("image/png")) { + fileExt = ".png"; + } + return fileExt; + } + + + + + /** + * 改变图片大小、格式 + * + * @param is + * @param os + * @param size + * @param format + * @return + * @throws IOException + */ + public static OutputStream resizeImage(InputStream inputStream, OutputStream outputStream, int size, String format) + throws IOException { + BufferedImage prevImage = ImageIO.read(inputStream); + double width = prevImage.getWidth(); + double height = prevImage.getHeight(); + double percent = size / width; + int newWidth = (int) (width * percent); + int newHeight = (int) (height * percent); + BufferedImage image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_BGR); + Graphics graphics = image.createGraphics(); + graphics.drawImage(prevImage, 0, 0, newWidth, newHeight, null); + ImageIO.write(image, format, outputStream); + outputStream.flush(); + return outputStream; + } + + /** + * 获取客户端ip + * + * @param request + * @return + */ + public static String getRemortIP(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + + // squid的squid.conf 的配制文件中forwarded_for项改为off时 + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + // 多级反向代理 + if (ip != null && ip.indexOf(",") > 0 && ip.split(",").length > 1) { + ip = ip.split(",")[0]; + } + return ip; + } + + + + + +} + diff --git a/service/src/main/java/com/hfkj/common/pay/util/IOUtil.java b/service/src/main/java/com/hfkj/common/pay/util/IOUtil.java new file mode 100644 index 0000000..f8dba18 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/IOUtil.java @@ -0,0 +1,73 @@ +package com.hfkj.common.pay.util; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +/** + * IO流工具类 + * @author 魏真峰 + */ +public class IOUtil { + + /** + * 将输入流转换为字符串 + *待转换为字符串的输入流 + * @return 由输入流转换String的字符串 + * @throws IOException + */ + public static String inputStreamToString(InputStream inputStream, String encoding) throws IOException { + if(StringUtils.isEmpty(encoding)) { + encoding = "UTF-8"; + } + return IOUtils.toString(inputStream, encoding); + } + + /** + * 将字符串转换为输入流 + * 待转换为输入流的字符串 + * @return + * @throws IOException + */ + public static InputStream toInputStream(String inputStr, String encoding) throws IOException { + if (StringUtils.isEmpty(inputStr)) { + return null; + } + if(StringUtils.isEmpty(encoding)) { + encoding = "UTF-8"; + } + return IOUtils.toInputStream(inputStr, encoding); + } + + + /** + * 编码 + * + * @param source + * @param encode + * @return + */ + public static String urlEncode(String source, String encode) { + String result = source; + try { + result = URLEncoder.encode(source, encode); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return result; + } + + /** + * 将输入流转换字节数组 + * @return + * @throws IOException + */ + public static byte[] inputStreamToByteArray(InputStream inputStream) throws IOException { + return IOUtils.toByteArray(inputStream); + } + +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/MD5Util.java b/service/src/main/java/com/hfkj/common/pay/util/MD5Util.java new file mode 100644 index 0000000..720af70 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/MD5Util.java @@ -0,0 +1,55 @@ +package com.hfkj.common.pay.util; + +import org.apache.commons.lang3.StringUtils; + +import java.security.MessageDigest; + +/** + * MD5加密工具类 + * + * @author phil + * @date 2017年7月2日 + * + */ +public class MD5Util { + + private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", + "e", "f" }; + + private static String byteArrayToHexString(byte b[]) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < b.length; i++) + buffer.append(byteToHexString(b[i])); + return buffer.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n += 256; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if(StringUtils.isEmpty(charsetname)) { + resultString = byteArrayToHexString(md.digest(resultString.getBytes("UTF-8"))); + } else { + resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname))); + } + } catch (Exception exception) { + + } + return resultString; + } + + public static void main(String args[]) { + System.out.println(MD5Encode("ceshi", "gbk")); + System.out.println(MD5Encode("ceshi", "utf-8")); + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/MyX509TrustManager.java b/service/src/main/java/com/hfkj/common/pay/util/MyX509TrustManager.java new file mode 100644 index 0000000..6fde0b0 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/MyX509TrustManager.java @@ -0,0 +1,24 @@ +package com.hfkj.common.pay.util; + +import javax.net.ssl.X509TrustManager; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +/** + * 自定义信任管理器 + * + * @author phil + * @date 2017年7月2日 + */ +class MyX509TrustManager implements X509TrustManager { + + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + } + + public X509Certificate[] getAcceptedIssuers() { + return null; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/SignatureUtil.java b/service/src/main/java/com/hfkj/common/pay/util/SignatureUtil.java new file mode 100644 index 0000000..07758e1 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/SignatureUtil.java @@ -0,0 +1,358 @@ +package com.hfkj.common.pay.util; + +import com.hfkj.common.pay.entity.WechatPayReturnParam; +import com.hfkj.common.pay.entity.WechatReturn; +import org.apache.commons.lang3.StringUtils; +import org.dom4j.DocumentException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; +import java.util.SortedMap; + +/** + * + * @Title: + * @Description: 微信支付签名工具类 + * @author: 魏真峰 + * @param: + * @return: + * @throws + */ +public class SignatureUtil { + + private static Logger logger = LoggerFactory.getLogger(SignatureUtil.class); + + /** + * 将字节数组转换为十六进制字符串 + * @param byteArray + * @return + */ + private static String byteToStr(byte[] byteArray) { + String strDigest = ""; + for (int i = 0; i < byteArray.length; i++) { + strDigest += byteToHexStr(byteArray[i]); + } + return strDigest; + } + + /** + * 将字节转换为十六进制字符串 + * + * @param mByte + * @return + */ + private static String byteToHexStr(byte mByte) { + char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + char[] tempArr = new char[2]; + tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; + tempArr[1] = Digit[mByte & 0X0F]; + return new String(tempArr); + } + + /** + * 获取签名 + * + * @param o + * 待加密的对象 该处仅限于Class + * @return + */ + public static String createSign(Object o, String apiKey, String encoding) { + String result = notSignParams(o, apiKey); + result = MD5Util.MD5Encode(result, encoding).toUpperCase(); + return result; + } + + /** + * 签名算法 + * + * @param o + * 要参与签名的数据对象 + * @param apiKey + * API密匙 + * @return 签名 + * @throws IllegalAccessException + */ + public static String notSignParams(Object o, String apiKey) { + ArrayList list = new ArrayList<>(); + String result = ""; + try { + Class cls = o.getClass(); + Field[] fields = cls.getDeclaredFields(); + list = getFieldList(fields, o); + Field[] superFields = cls.getSuperclass().getDeclaredFields(); // 获取父类的私有属性 + list.addAll(getFieldList(superFields, o)); + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); // 严格按字母表顺序排序 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + result = sb.toString(); + if (apiKey != null && !"".equals(apiKey)) { + result += "key=" + apiKey; + } else { + result = result.substring(0, result.lastIndexOf("&")); + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 将字段集合方法转换 + * + * @param array + * @param object + * @return + * @throws IllegalArgumentException + * @throws IllegalAccessException + */ + private static ArrayList getFieldList(Field[] array, Object object) + throws IllegalArgumentException, IllegalAccessException { + ArrayList list = new ArrayList(); + for (Field f : array) { + f.setAccessible(true); + if (f.get(object) != null && f.get(object) != "" && !f.getName().equals("serialVersionUID") + && !f.getName().equals("sign")) { + if (f.getName().equals("packageStr")) { + list.add("package" + "=" + f.get(object) + "&"); + } else { + list.add(f.getName() + "=" + f.get(object) + "&"); + } + } + } + return list; + } + + /** + * 通过Map中的所有元素参与签名 + * + * @param map + * 待参与签名的map集合 + * @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名 + * @return + */ + public static String createSign(Map map, String apiKey, String characterEncoding) { + String result = notSignParams(map, apiKey); + result = MD5Util.MD5Encode(result, characterEncoding).toUpperCase(); + logger.debug("sign result {}", result); + return result; + } + + /** + * 通过Map中的所有元素参与签名 + * + * @param map + * 待参与签名的map集合 + * @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名 + * @return + */ + public static String createSign(SortedMap map, String apiKey, String characterEncoding) { + String result = notSignParams(map, apiKey); + result = MD5Util.MD5Encode(result, characterEncoding).toUpperCase(); + logger.debug("sign result {}", result); + return result; + } + + /** + * 通过Map中的所有元素参与签名 + * + * @param map + * 待参与签名的map集合 + * @params apikey apikey中 如果为空则不参与签名,如果不为空则参与签名 + * @return + */ + public static String createSha1Sign(SortedMap map, String apiKey, String characterEncoding) { + String result = notSignParams(map, apiKey); + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-1"); + byte[] digest = md.digest(result.getBytes(characterEncoding)); + result = byteToStr(digest); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return result; + } + + /** + * 返回未加密的字符串 + * + * @param params + * @param apiKey + * @return 待加密的字符串 + */ + private static String notSignParams(SortedMap params, String apiKey) { + StringBuffer buffer = new StringBuffer(); + for (Map.Entry entry : params.entrySet()) { + if (!org.springframework.util.StringUtils.isEmpty(entry.getValue())) { + buffer.append(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + buffer.append("key=" + apiKey); + return buffer.toString(); + } + + /** + * 返回未加密的字符串 + * + * @param params + * @param apiKey + * @return 待加密的字符串 + */ + public static String notSignParams(Map params, String apiKey) { + ArrayList list = new ArrayList<>(); + for (Map.Entry entry : params.entrySet()) { + if (entry.getValue() != "" && entry.getValue() != null) { + list.add(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + String result = sb.toString(); + if (apiKey != null && !"".equals(apiKey)) { + result += "key=" + apiKey; + } else { + result = result.substring(0, result.lastIndexOf("&")); + } + return result; + } + + /** + * 从API返回的XML数据里面重新计算一次签名 + * + * @param responseString + * API返回的XML数据 + * @param apiKey + * Key + * @return 新的签名 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static String reCreateSign(String responseString, String apiKey, String encoding) + throws IOException, SAXException, ParserConfigurationException { + Map map = XmlUtil.parseXmlToMap(responseString, encoding); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + map.replace("sign",""); + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + return createSign(map, apiKey, encoding); + } + + + /** + * 检验API返回的数据里面的签名是否合法,规则是:按参数名称a-z排序,遇到空值的参数不参加签名 + * + * @param resultXml + * API返回的XML数据字符串 + * @param apiKey + * Key + * @return API签名是否合法 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + * @throws DocumentException + */ + public static boolean checkIsSignValidFromWeiXin(String checktXml, String apiKey, String encoding) + throws ParserConfigurationException, IOException, SAXException, DocumentException { + SortedMap map = XmlUtil.parseXmlToTreeMap(checktXml,encoding); + String signFromresultXml = (String) map.get("sign"); + WechatReturn wechatReturn = new WechatReturn(); + wechatReturn.setAppid((String) map.get("appid")); + wechatReturn.setMch_id((String) map.get("mch_id")); + wechatReturn.setNonce_str((String) map.get("nonce_str")); + wechatReturn.setPrepay_id((String) map.get("prepay_id")); + wechatReturn.setResult_code((String) map.get("result_code")); + wechatReturn.setReturn_code((String) map.get("return_code")); + wechatReturn.setReturn_msg((String) map.get("return_msg")); + wechatReturn.setTrade_type((String) map.get("trade_type")); + if (StringUtils.isEmpty(signFromresultXml)) { + logger.debug("API返回的数据签名数据不存在"); + return false; + } + if(!("SUCCESS".equals(map.get("return_code"))) || !("SUCCESS".equals(map.get("result_code")))){ + logger.debug("返回代码不成功!"); + return false; + } + logger.debug("服务器回包里面的签名{}", signFromresultXml); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 +// String signForAPIResponse = createSign(wechatReturn, apiKey, encoding); +// if (!signForAPIResponse.equals(signFromresultXml)) { +// // 签名验不过,表示这个API返回的数据有可能已经被篡改了 +// logger.debug("API返回的数据签名验证不通过"); +// return false; +// } + logger.debug("API返回的数据签名验证通过"); + return true; + } + /** + * + * @Title: reCheckIsSignValidFromWeiXin + * @Description: 微信支付异步回调,检验签名是否正确 + * @author: 魏真峰 + * @param: [checktXml, apiKey, encoding] + * @return: boolean + * @throws + */ + public static boolean reCheckIsSignValidFromWeiXin(String checktXml, String apiKey, String encoding) + throws ParserConfigurationException, IOException, SAXException, DocumentException { + SortedMap map = XmlUtil.parseXmlToTreeMap(checktXml,encoding); + String signFromresultXml = (String) map.get("sign"); + WechatPayReturnParam wechatPayReturnParam = new WechatPayReturnParam(); + wechatPayReturnParam.setAppid((String) map.get("appid")); + wechatPayReturnParam.setAttach((String) map.get("attach")); + wechatPayReturnParam.setBank_type((String) map.get("bank_type")); + wechatPayReturnParam.setCash_fee((String) map.get("cash_fee")); + wechatPayReturnParam.setFee_type((String) map.get("fee_type")); + wechatPayReturnParam.setIs_subscribe((String) map.get("is_subscribe")); + wechatPayReturnParam.setMch_id((String) map.get("mch_id")); + wechatPayReturnParam.setNonce_str((String) map.get("nonce_str")); + wechatPayReturnParam.setOpenid((String) map.get("openid")); + wechatPayReturnParam.setOut_trade_no((String) map.get("out_trade_no")); + wechatPayReturnParam.setResult_code((String) map.get("result_code")); + wechatPayReturnParam.setReturn_code((String) map.get("return_code")); + wechatPayReturnParam.setTime_end((String) map.get("time_end")); + wechatPayReturnParam.setTotal_fee((String) map.get("total_fee")); + wechatPayReturnParam.setTrade_type((String) map.get("trade_type")); + wechatPayReturnParam.setTransaction_id((String) map.get("transaction_id")); + if (StringUtils.isEmpty(signFromresultXml)) { + logger.debug("API返回的数据签名数据不存在"); + return false; + } + if(!("SUCCESS".equals(map.get("return_code"))) || !("SUCCESS".equals(map.get("result_code")))){ + logger.debug("返回代码不成功!"); + return false; + } + logger.debug("服务器回包里面的签名{}", signFromresultXml); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + String signForAPIResponse = createSign(wechatPayReturnParam, apiKey, encoding); + if (!signForAPIResponse.equals(signFromresultXml)) { + // 签名验不过,表示这个API返回的数据有可能已经被篡改了 + logger.debug("API返回的数据签名验证不通过"); + return false; + } + logger.debug("API返回的数据签名验证通过"); + return true; + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/XmlUtil.java b/service/src/main/java/com/hfkj/common/pay/util/XmlUtil.java new file mode 100644 index 0000000..ba7c038 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/XmlUtil.java @@ -0,0 +1,274 @@ +package com.hfkj.common.pay.util; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.core.util.QuickWriter; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.xml.DomDriver; +import com.thoughtworks.xstream.io.xml.PrettyPrintWriter; +import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder; +import com.thoughtworks.xstream.io.xml.XppDriver; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.xml.sax.SAXException; + +import javax.servlet.http.HttpServletRequest; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * XML解析工具类 + * + * @author phil + * @date 2017年7月3日 + * + */ +public class XmlUtil { + + /** + * 解析微信发来的请求(XML) xml示例 + * + * 123456789 + * + * + * + * @param request + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static Map parseXmlToMap(HttpServletRequest request){ + Map map = new HashMap<>(); + InputStream inputStream = null; + try { + // 从request中取得输入流 + inputStream = request.getInputStream(); + // 读取输入流 + SAXReader reader = new SAXReader(); + Document document = reader.read(inputStream); + // 得到xml根元素 + Element root = document.getRootElement(); + // 得到根元素的所有子节点 + List elementList = root.elements(); + // 遍历所有子节点 + for (Element e : elementList) { + map.put(e.getName(), e.getText()); + } + } catch (IOException | DocumentException e) { + e.printStackTrace(); + } + return map; + } + + /** + * 解析微信发来的请求(XML) xml示例 + * + * 123456789 + * + * + * + * @param request + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static Map parseStreamToMap(InputStream inputStream) throws Exception { + Map map = new HashMap<>(); + try { + // 读取输入流 + SAXReader reader = new SAXReader(); + Document document = reader.read(inputStream); + // 得到xml根元素 + Element root = document.getRootElement(); + // 得到根元素的所有子节点 + List elementList = root.elements(); + // 遍历所有子节点 + for (Element e : elementList) { + map.put(e.getName(), e.getText()); + } + } catch (DocumentException e) { + e.printStackTrace(); + } + return map; + } + + /** + * 使用dom4将xml文件中的数据转换成SortedMap + * + * @param xmlString + * xml格式的字符串 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static TreeMap parseXmlToTreeMap(String xml, String encoding) + throws ParserConfigurationException, IOException, SAXException { + // 这里用Dom的方式解析回包的最主要目的是防止API新增回包字段 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputStream is = IOUtil.toInputStream(xml, encoding); + org.w3c.dom.Document document = builder.parse(is); + // 获取到document里面的全部结点 + org.w3c.dom.NodeList allNodes = document.getFirstChild().getChildNodes(); + org.w3c.dom.Node node; + TreeMap map = new TreeMap<>(); + int i = 0; + while (i < allNodes.getLength()) { + node = allNodes.item(i); + if (node instanceof org.w3c.dom.Element) { + map.put(node.getNodeName(), node.getTextContent()); + } + i++; + } + return map; + } + + /** + * 使用dom4将xml文件中的数据转换成Map + * + * @param xmlString xml格式的字符串 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static Map parseXmlToMap(String xml, String encoding) + throws ParserConfigurationException, IOException, SAXException { + // 这里用Dom的方式解析回包的最主要目的是防止API新增回包字段 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputStream is = IOUtil.toInputStream(xml, encoding); + org.w3c.dom.Document document = builder.parse(is); + // 获取到document里面的全部结点 + org.w3c.dom.NodeList allNodes = document.getFirstChild().getChildNodes(); + org.w3c.dom.Node node; + Map map = new HashMap<>(); + int i = 0; + while (i < allNodes.getLength()) { + node = allNodes.item(i); + if (node instanceof org.w3c.dom.Element) { + map.put(node.getNodeName(), node.getTextContent()); + } + i++; + } + return map; + } + + /** + * 示例 + * + * + * + * + * + * + * + * + * + * + * 将xml数据(格式)映射到java对象中 + * + * @param xml + * 待转换的xml格式的数据 + * @param t + * 待转换为的java对象 + * @return + */ + public static T getObjectFromXML(String xml, Class t) { + // 将从API返回的XML数据映射到Java对象 + XStream xstream = XStreamFactroy.init(true); + xstream.alias("xml", t); + xstream.ignoreUnknownElements();// 暂时忽略掉一些新增的字段 +// if(Objects.equals(xstream.fromXML(xml).getClass(), t.getClass())) { +// return t.cast(xstream.fromXML(xml)); +// } +// return null; + return t.cast(xstream.fromXML(xml)); + } + + /** + * 将java对象转换为xml(格式) + * + * @param obj + * @return + */ + public static String toXml(Object obj) { + String result = ""; + XStream xstream = XStreamFactroy.init(true); + xstream.alias("xml", obj.getClass()); + result = xstream.toXML(obj); + return result; + } + + /** + * 将java对象转换为xml文件,并去除 _ 应用场景是 去除实体中有_划线的实体, 默认会有两个_,调用该方法则会去除一个 + * + * @param obj + * @return + */ + public static String toSplitXml(Object obj) { + String result = ""; + XStream xstream = XStreamFactroy.initSplitLine(); + xstream.alias("xml", obj.getClass()); + result = xstream.toXML(obj); + return result.replaceAll(""","\""); + } + + /** + * XStream工具类 + * @author phil + * + */ + static class XStreamFactroy { + + private static final String START_CADA = ""; + + /** + * 是否启用 + * + * @param flag true 表示启用 false表示不启用 + * @return + */ + static XStream init(boolean flag) { + XStream xstream = null; + if (flag) { + xstream = new XStream(new XppDriver() { + public HierarchicalStreamWriter createWriter(Writer out) { + return new PrettyPrintWriter(out) { + @Override + protected void writeText(QuickWriter writer, String text) { + if (!text.startsWith(START_CADA)) { + text = START_CADA + text + END_CADA; + } + writer.write(text); + } + }; + } + }); + } else { + xstream = new XStream(); + } + return xstream; + } + + /** + * 用于处理在实体对象中带有_的属性,如果用上述方法,会出现有两个__,导致结果不正确! 属性中有_的属性一定要有改方法 + * + * @return 返回xstream 对象 new DomDriver("UTF-8", new + * XmlFriendlyNameCoder("-_", "_") + */ + public static XStream initSplitLine() { + XStream xstream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_"))); + return xstream; + } + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/IWXPayDomain.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/IWXPayDomain.java new file mode 100644 index 0000000..947b077 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/IWXPayDomain.java @@ -0,0 +1,42 @@ +package com.hfkj.common.pay.util.sdk; + +/** + * 域名管理,实现主备域名自动切换 + */ +public abstract interface IWXPayDomain { + /** + * 上报域名网络状况 + * @param domain 域名。 比如:api.mch.weixin.qq.com + * @param elapsedTimeMillis 耗时 + * @param ex 网络请求中出现的异常。 + * null表示没有异常 + * ConnectTimeoutException,表示建立网络连接异常 + * UnknownHostException, 表示dns解析异常 + */ + abstract void report(final String domain, long elapsedTimeMillis, final Exception ex); + + /** + * 获取域名 + * @param config 配置 + * @return 域名 + */ + abstract DomainInfo getDomain(final WXPayConfig config); + + static class DomainInfo{ + public String domain; //域名 + public boolean primaryDomain; //该域名是否为主域名。例如:api.mch.weixin.qq.com为主域名 + public DomainInfo(String domain, boolean primaryDomain) { + this.domain = domain; + this.primaryDomain = primaryDomain; + } + + @Override + public String toString() { + return "DomainInfo{" + + "domain='" + domain + '\'' + + ", primaryDomain=" + primaryDomain + + '}'; + } + } + +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPay.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPay.java new file mode 100644 index 0000000..45d7ed2 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPay.java @@ -0,0 +1,687 @@ +package com.hfkj.common.pay.util.sdk; + +import java.util.HashMap; +import java.util.Map; + +public class WXPay { + + private WXPayConfig config; + private WXPayConstants.SignType signType; + private boolean autoReport; + private boolean useSandbox; + private String notifyUrl; + private WXPayRequest wxPayRequest; + + public WXPay(final WXPayConfig config) throws Exception { + this(config, null, true, false); + } + + public WXPay(final WXPayConfig config, final boolean autoReport) throws Exception { + this(config, null, autoReport, false); + } + + + public WXPay(final WXPayConfig config, final boolean autoReport, final boolean useSandbox) throws Exception{ + this(config, null, autoReport, useSandbox); + } + + public WXPay(final WXPayConfig config, final String notifyUrl) throws Exception { + this(config, notifyUrl, true, false); + } + + public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport) throws Exception { + this(config, notifyUrl, autoReport, false); + } + + public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) throws Exception { + this.config = config; + this.notifyUrl = notifyUrl; + this.autoReport = autoReport; + this.useSandbox = useSandbox; + if (useSandbox) { + this.signType = WXPayConstants.SignType.MD5; // 沙箱环境 + } + else { + this.signType = WXPayConstants.SignType.HMACSHA256; + } + this.wxPayRequest = new WXPayRequest(config); + } + + private void checkWXPayConfig() throws Exception { + if (this.config == null) { + throw new Exception("config is null"); + } + if (this.config.getAppID() == null || this.config.getAppID().trim().length() == 0) { + throw new Exception("appid in config is empty"); + } + if (this.config.getMchID() == null || this.config.getMchID().trim().length() == 0) { + throw new Exception("appid in config is empty"); + } + if (this.config.getCertStream() == null) { + throw new Exception("cert stream in config is empty"); + } + if (this.config.getWXPayDomain() == null){ + throw new Exception("config.getWXPayDomain() is null"); + } + + if (this.config.getHttpConnectTimeoutMs() < 10) { + throw new Exception("http connect timeout is too small"); + } + if (this.config.getHttpReadTimeoutMs() < 10) { + throw new Exception("http read timeout is too small"); + } + + } + + /** + * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign
+ * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口 + * + * @param reqData + * @return + * @throws Exception + */ + public Map fillRequestData(Map reqData) throws Exception { + reqData.put("appid", config.getAppID()); + reqData.put("mch_id", config.getMchID()); + reqData.put("nonce_str", WXPayUtil.generateNonceStr()); + if (WXPayConstants.SignType.MD5.equals(this.signType)) { + reqData.put("sign_type", WXPayConstants.MD5); + } + else if (WXPayConstants.SignType.HMACSHA256.equals(this.signType)) { + reqData.put("sign_type", WXPayConstants.HMACSHA256); + } + reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType)); + return reqData; + } + + /** + * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。 + * + * @param reqData 向wxpay post的请求数据 + * @return 签名是否有效 + * @throws Exception + */ + public boolean isResponseSignatureValid(Map reqData) throws Exception { + // 返回数据的签名方式和请求中给定的签名方式是一致的 + return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), this.signType); + } + + /** + * 判断支付结果通知中的sign是否有效 + * + * @param reqData 向wxpay post的请求数据 + * @return 签名是否有效 + * @throws Exception + */ + public boolean isPayResultNotifySignatureValid(Map reqData) throws Exception { + String signTypeInData = reqData.get(WXPayConstants.FIELD_SIGN_TYPE); + WXPayConstants.SignType signType; + if (signTypeInData == null) { + signType = WXPayConstants.SignType.MD5; + } + else { + signTypeInData = signTypeInData.trim(); + if (signTypeInData.length() == 0) { + signType = WXPayConstants.SignType.MD5; + } + else if (WXPayConstants.MD5.equals(signTypeInData)) { + signType = WXPayConstants.SignType.MD5; + } + else if (WXPayConstants.HMACSHA256.equals(signTypeInData)) { + signType = WXPayConstants.SignType.HMACSHA256; + } + else { + throw new Exception(String.format("Unsupported sign_type: %s", signTypeInData)); + } + } + return WXPayUtil.isSignatureValid(reqData, this.config.getKey(), signType); + } + + + /** + * 不需要证书的请求 + * @param urlSuffix String + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 超时时间,单位是毫秒 + * @param readTimeoutMs 超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public String requestWithoutCert(String urlSuffix, Map reqData, + int connectTimeoutMs, int readTimeoutMs) throws Exception { + String msgUUID = reqData.get("nonce_str"); + String reqBody = WXPayUtil.mapToXml(reqData); + + String resp = this.wxPayRequest.requestWithoutCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, autoReport); + return resp; + } + + + /** + * 需要证书的请求 + * @param urlSuffix String + * @param reqData 向wxpay post的请求数据 Map + * @param connectTimeoutMs 超时时间,单位是毫秒 + * @param readTimeoutMs 超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public String requestWithCert(String urlSuffix, Map reqData, + int connectTimeoutMs, int readTimeoutMs) throws Exception { + String msgUUID= reqData.get("nonce_str"); + String reqBody = WXPayUtil.mapToXml(reqData); + + String resp = this.wxPayRequest.requestWithCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, this.autoReport); + return resp; + } + + /** + * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。 + * @param xmlStr API返回的XML格式数据 + * @return Map类型数据 + * @throws Exception + */ + public Map processResponseXml(String xmlStr) throws Exception { + String RETURN_CODE = "return_code"; + String return_code; + Map respData = WXPayUtil.xmlToMap(xmlStr); + if (respData.containsKey(RETURN_CODE)) { + return_code = respData.get(RETURN_CODE); + } + else { + throw new Exception(String.format("No `return_code` in XML: %s", xmlStr)); + } + + if (return_code.equals(WXPayConstants.FAIL)) { + return respData; + } + else if (return_code.equals(WXPayConstants.SUCCESS)) { + if (this.isResponseSignatureValid(respData)) { + return respData; + } + else { + throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr)); + } + } + else { + throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr)); + } + } + + /** + * 作用:提交刷卡支付
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map microPay(Map reqData) throws Exception { + return this.microPay(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:提交刷卡支付
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map microPay(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_MICROPAY_URL_SUFFIX; + } + else { + url = WXPayConstants.MICROPAY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + /** + * 提交刷卡支付,针对软POS,尽可能做成功 + * 内置重试机制,最多60s + * @param reqData + * @return + * @throws Exception + */ + public Map microPayWithPos(Map reqData) throws Exception { + return this.microPayWithPos(reqData, this.config.getHttpConnectTimeoutMs()); + } + + /** + * 提交刷卡支付,针对软POS,尽可能做成功 + * 内置重试机制,最多60s + * @param reqData + * @param connectTimeoutMs + * @return + * @throws Exception + */ + public Map microPayWithPos(Map reqData, int connectTimeoutMs) throws Exception { + int remainingTimeMs = 60*1000; + long startTimestampMs = 0; + Map lastResult = null; + Exception lastException = null; + + while (true) { + startTimestampMs = WXPayUtil.getCurrentTimestampMs(); + int readTimeoutMs = remainingTimeMs - connectTimeoutMs; + if (readTimeoutMs > 1000) { + try { + lastResult = this.microPay(reqData, connectTimeoutMs, readTimeoutMs); + String returnCode = lastResult.get("return_code"); + if (returnCode.equals("SUCCESS")) { + String resultCode = lastResult.get("result_code"); + String errCode = lastResult.get("err_code"); + if (resultCode.equals("SUCCESS")) { + break; + } + else { + // 看错误码,若支付结果未知,则重试提交刷卡支付 + if (errCode.equals("SYSTEMERROR") || errCode.equals("BANKERROR") || errCode.equals("USERPAYING")) { + remainingTimeMs = remainingTimeMs - (int)(WXPayUtil.getCurrentTimestampMs() - startTimestampMs); + if (remainingTimeMs <= 100) { + break; + } + else { + WXPayUtil.getLogger().info("microPayWithPos: try micropay again"); + if (remainingTimeMs > 5*1000) { + Thread.sleep(5*1000); + } + else { + Thread.sleep(1*1000); + } + continue; + } + } + else { + break; + } + } + } + else { + break; + } + } + catch (Exception ex) { + lastResult = null; + lastException = ex; + } + } + else { + break; + } + } + + if (lastResult == null) { + throw lastException; + } + else { + return lastResult; + } + } + + + + /** + * 作用:统一下单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map unifiedOrder(Map reqData) throws Exception { + return this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:统一下单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map unifiedOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_UNIFIEDORDER_URL_SUFFIX; + } + else { + url = WXPayConstants.UNIFIEDORDER_URL_SUFFIX; + } + if(this.notifyUrl != null) { + reqData.put("notify_url", this.notifyUrl); + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:查询订单
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map orderQuery(Map reqData) throws Exception { + return this.orderQuery(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:查询订单
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 int + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map orderQuery(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_ORDERQUERY_URL_SUFFIX; + } + else { + url = WXPayConstants.ORDERQUERY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:撤销订单
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map reverse(Map reqData) throws Exception { + return this.reverse(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:撤销订单
+ * 场景:刷卡支付
+ * 其他:需要证书 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map reverse(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REVERSE_URL_SUFFIX; + } + else { + url = WXPayConstants.REVERSE_URL_SUFFIX; + } + String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:关闭订单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map closeOrder(Map reqData) throws Exception { + return this.closeOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:关闭订单
+ * 场景:公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map closeOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_CLOSEORDER_URL_SUFFIX; + } + else { + url = WXPayConstants.CLOSEORDER_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:申请退款
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map refund(Map reqData) throws Exception { + return this.refund(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:申请退款
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付
+ * 其他:需要证书 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map refund(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REFUND_URL_SUFFIX; + } + else { + url = WXPayConstants.REFUND_URL_SUFFIX; + } + String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:退款查询
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map refundQuery(Map reqData) throws Exception { + return this.refundQuery(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:退款查询
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map refundQuery(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REFUNDQUERY_URL_SUFFIX; + } + else { + url = WXPayConstants.REFUNDQUERY_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:对账单下载(成功时返回对账单数据,失败时返回XML格式数据)
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map downloadBill(Map reqData) throws Exception { + return this.downloadBill(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:对账单下载
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付
+ * 其他:无论是否成功都返回Map。若成功,返回的Map中含有return_code、return_msg、data, + * 其中return_code为`SUCCESS`,data为对账单数据。 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return 经过封装的API返回数据 + * @throws Exception + */ + public Map downloadBill(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_DOWNLOADBILL_URL_SUFFIX; + } + else { + url = WXPayConstants.DOWNLOADBILL_URL_SUFFIX; + } + String respStr = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs).trim(); + Map ret; + // 出现错误,返回XML数据 + if (respStr.indexOf("<") == 0) { + ret = WXPayUtil.xmlToMap(respStr); + } + else { + // 正常返回csv数据 + ret = new HashMap(); + ret.put("return_code", WXPayConstants.SUCCESS); + ret.put("return_msg", "ok"); + ret.put("data", respStr); + } + return ret; + } + + + /** + * 作用:交易保障
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map report(Map reqData) throws Exception { + return this.report(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:交易保障
+ * 场景:刷卡支付、公共号支付、扫码支付、APP支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map report(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_REPORT_URL_SUFFIX; + } + else { + url = WXPayConstants.REPORT_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return WXPayUtil.xmlToMap(respXml); + } + + + /** + * 作用:转换短链接
+ * 场景:刷卡支付、扫码支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map shortUrl(Map reqData) throws Exception { + return this.shortUrl(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:转换短链接
+ * 场景:刷卡支付、扫码支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map shortUrl(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_SHORTURL_URL_SUFFIX; + } + else { + url = WXPayConstants.SHORTURL_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + + /** + * 作用:授权码查询OPENID接口
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @return API返回数据 + * @throws Exception + */ + public Map authCodeToOpenid(Map reqData) throws Exception { + return this.authCodeToOpenid(reqData, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); + } + + + /** + * 作用:授权码查询OPENID接口
+ * 场景:刷卡支付 + * @param reqData 向wxpay post的请求数据 + * @param connectTimeoutMs 连接超时时间,单位是毫秒 + * @param readTimeoutMs 读超时时间,单位是毫秒 + * @return API返回数据 + * @throws Exception + */ + public Map authCodeToOpenid(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { + String url; + if (this.useSandbox) { + url = WXPayConstants.SANDBOX_AUTHCODETOOPENID_URL_SUFFIX; + } + else { + url = WXPayConstants.AUTHCODETOOPENID_URL_SUFFIX; + } + String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); + return this.processResponseXml(respXml); + } + + +} // end class diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayConfig.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayConfig.java new file mode 100644 index 0000000..bcecc47 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayConfig.java @@ -0,0 +1,103 @@ +package com.hfkj.common.pay.util.sdk; + +import java.io.InputStream; + +public abstract class WXPayConfig { + + + + /** + * 获取 App ID + * + * @return App ID + */ + abstract String getAppID(); + + + /** + * 获取 Mch ID + * + * @return Mch ID + */ + abstract String getMchID(); + + + /** + * 获取 API 密钥 + * + * @return API密钥 + */ + abstract String getKey(); + + + /** + * 获取商户证书内容 + * + * @return 商户证书内容 + */ + abstract InputStream getCertStream(); + + /** + * HTTP(S) 连接超时时间,单位毫秒 + * + * @return + */ + public int getHttpConnectTimeoutMs() { + return 6*1000; + } + + /** + * HTTP(S) 读数据超时时间,单位毫秒 + * + * @return + */ + public int getHttpReadTimeoutMs() { + return 8*1000; + } + + /** + * 获取WXPayDomain, 用于多域名容灾自动切换 + * @return + */ + abstract IWXPayDomain getWXPayDomain(); + + /** + * 是否自动上报。 + * 若要关闭自动上报,子类中实现该函数返回 false 即可。 + * + * @return + */ + public boolean shouldAutoReport() { + return true; + } + + /** + * 进行健康上报的线程的数量 + * + * @return + */ + public int getReportWorkerNum() { + return 6; + } + + + /** + * 健康上报缓存消息的最大数量。会有线程去独立上报 + * 粗略计算:加入一条消息200B,10000消息占用空间 2000 KB,约为2MB,可以接受 + * + * @return + */ + public int getReportQueueMaxSize() { + return 10000; + } + + /** + * 批量上报,一次最多上报多个数据 + * + * @return + */ + public int getReportBatchSize() { + return 10; + } + +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayConstants.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayConstants.java new file mode 100644 index 0000000..673ea63 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayConstants.java @@ -0,0 +1,59 @@ +package com.hfkj.common.pay.util.sdk; + +import org.apache.http.client.HttpClient; + +/** + * 常量 + */ +public class WXPayConstants { + + public enum SignType { + MD5, HMACSHA256 + } + + public static final String DOMAIN_API = "api.mch.weixin.qq.com"; + public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com"; + public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com"; + public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com"; + + + public static final String FAIL = "FAIL"; + public static final String SUCCESS = "SUCCESS"; + public static final String HMACSHA256 = "HMAC-SHA256"; + public static final String MD5 = "MD5"; + + public static final String FIELD_SIGN = "sign"; + public static final String FIELD_SIGN_TYPE = "sign_type"; + + public static final String WXPAYSDK_VERSION = "WXPaySDK/3.0.9"; + public static final String USER_AGENT = WXPAYSDK_VERSION + + " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") + + ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion(); + + public static final String MICROPAY_URL_SUFFIX = "/pay/micropay"; + public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder"; + public static final String ORDERQUERY_URL_SUFFIX = "/pay/orderquery"; + public static final String REVERSE_URL_SUFFIX = "/secapi/pay/reverse"; + public static final String CLOSEORDER_URL_SUFFIX = "/pay/closeorder"; + public static final String REFUND_URL_SUFFIX = "/secapi/pay/refund"; + public static final String REFUNDQUERY_URL_SUFFIX = "/pay/refundquery"; + public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill"; + public static final String REPORT_URL_SUFFIX = "/payitil/report"; + public static final String SHORTURL_URL_SUFFIX = "/tools/shorturl"; + public static final String AUTHCODETOOPENID_URL_SUFFIX = "/tools/authcodetoopenid"; + + // sandbox + public static final String SANDBOX_MICROPAY_URL_SUFFIX = "/sandboxnew/pay/micropay"; + public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder"; + public static final String SANDBOX_ORDERQUERY_URL_SUFFIX = "/sandboxnew/pay/orderquery"; + public static final String SANDBOX_REVERSE_URL_SUFFIX = "/sandboxnew/secapi/pay/reverse"; + public static final String SANDBOX_CLOSEORDER_URL_SUFFIX = "/sandboxnew/pay/closeorder"; + public static final String SANDBOX_REFUND_URL_SUFFIX = "/sandboxnew/secapi/pay/refund"; + public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX = "/sandboxnew/pay/refundquery"; + public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill"; + public static final String SANDBOX_REPORT_URL_SUFFIX = "/sandboxnew/payitil/report"; + public static final String SANDBOX_SHORTURL_URL_SUFFIX = "/sandboxnew/tools/shorturl"; + public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid"; + +} + diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayReport.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayReport.java new file mode 100644 index 0000000..bb02326 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayReport.java @@ -0,0 +1,265 @@ +package com.hfkj.common.pay.util.sdk; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; + +/** + * 交易保障 + */ +public class WXPayReport { + + public static class ReportInfo { + + /** + * 布尔变量使用int。0为false, 1为true。 + */ + + // 基本信息 + private String version = "v1"; + private String sdk = WXPayConstants.WXPAYSDK_VERSION; + private String uuid; // 交易的标识 + private long timestamp; // 上报时的时间戳,单位秒 + private long elapsedTimeMillis; // 耗时,单位 毫秒 + + // 针对主域名 + private String firstDomain; // 第1次请求的域名 + private boolean primaryDomain; //是否主域名 + private int firstConnectTimeoutMillis; // 第1次请求设置的连接超时时间,单位 毫秒 + private int firstReadTimeoutMillis; // 第1次请求设置的读写超时时间,单位 毫秒 + private int firstHasDnsError; // 第1次请求是否出现dns问题 + private int firstHasConnectTimeout; // 第1次请求是否出现连接超时 + private int firstHasReadTimeout; // 第1次请求是否出现连接超时 + + public ReportInfo(String uuid, long timestamp, long elapsedTimeMillis, String firstDomain, boolean primaryDomain, int firstConnectTimeoutMillis, int firstReadTimeoutMillis, boolean firstHasDnsError, boolean firstHasConnectTimeout, boolean firstHasReadTimeout) { + this.uuid = uuid; + this.timestamp = timestamp; + this.elapsedTimeMillis = elapsedTimeMillis; + this.firstDomain = firstDomain; + this.primaryDomain = primaryDomain; + this.firstConnectTimeoutMillis = firstConnectTimeoutMillis; + this.firstReadTimeoutMillis = firstReadTimeoutMillis; + this.firstHasDnsError = firstHasDnsError?1:0; + this.firstHasConnectTimeout = firstHasConnectTimeout?1:0; + this.firstHasReadTimeout = firstHasReadTimeout?1:0; + } + + @Override + public String toString() { + return "ReportInfo{" + + "version='" + version + '\'' + + ", sdk='" + sdk + '\'' + + ", uuid='" + uuid + '\'' + + ", timestamp=" + timestamp + + ", elapsedTimeMillis=" + elapsedTimeMillis + + ", firstDomain='" + firstDomain + '\'' + + ", primaryDomain=" + primaryDomain + + ", firstConnectTimeoutMillis=" + firstConnectTimeoutMillis + + ", firstReadTimeoutMillis=" + firstReadTimeoutMillis + + ", firstHasDnsError=" + firstHasDnsError + + ", firstHasConnectTimeout=" + firstHasConnectTimeout + + ", firstHasReadTimeout=" + firstHasReadTimeout + + '}'; + } + + /** + * 转换成 csv 格式 + * + * @return + */ + public String toLineString(String key) { + String separator = ","; + Object[] objects = new Object[] { + version, sdk, uuid, timestamp, elapsedTimeMillis, + firstDomain, primaryDomain, firstConnectTimeoutMillis, firstReadTimeoutMillis, + firstHasDnsError, firstHasConnectTimeout, firstHasReadTimeout + }; + StringBuffer sb = new StringBuffer(); + for(Object obj: objects) { + sb.append(obj).append(separator); + } + try { + String sign = WXPayUtil.HMACSHA256(sb.toString(), key); + sb.append(sign); + return sb.toString(); + } + catch (Exception ex) { + return null; + } + + } + + } + + private static final String REPORT_URL = "http://report.mch.weixin.qq.com/wxpay/report/default"; + // private static final String REPORT_URL = "http://127.0.0.1:5000/test"; + + + private static final int DEFAULT_CONNECT_TIMEOUT_MS = 6*1000; + private static final int DEFAULT_READ_TIMEOUT_MS = 8*1000; + + private LinkedBlockingQueue reportMsgQueue = null; + private WXPayConfig config; + private ExecutorService executorService; + + private volatile static WXPayReport INSTANCE; + + private WXPayReport(final WXPayConfig config) { + this.config = config; + reportMsgQueue = new LinkedBlockingQueue(config.getReportQueueMaxSize()); + + // 添加处理线程 + executorService = Executors.newFixedThreadPool(config.getReportWorkerNum(), new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread t = Executors.defaultThreadFactory().newThread(r); + t.setDaemon(true); + return t; + } + }); + + if (config.shouldAutoReport()) { + WXPayUtil.getLogger().info("report worker num: {}", config.getReportWorkerNum()); + for (int i = 0; i < config.getReportWorkerNum(); ++i) { + executorService.execute(new Runnable() { + public void run() { + while (true) { + // 先用 take 获取数据 + try { + StringBuffer sb = new StringBuffer(); + String firstMsg = reportMsgQueue.take(); + WXPayUtil.getLogger().info("get first report msg: {}", firstMsg); + String msg = null; + sb.append(firstMsg); //会阻塞至有消息 + int remainNum = config.getReportBatchSize() - 1; + for (int j=0; jcreate() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + HttpPost httpPost = new HttpPost(REPORT_URL); + + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build(); + httpPost.setConfig(requestConfig); + + StringEntity postEntity = new StringEntity(data, "UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.addHeader("User-Agent", WXPayConstants.USER_AGENT); + httpPost.setEntity(postEntity); + + HttpResponse httpResponse = httpClient.execute(httpPost); + HttpEntity httpEntity = httpResponse.getEntity(); + return EntityUtils.toString(httpEntity, "UTF-8"); + } + +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayRequest.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayRequest.java new file mode 100644 index 0000000..919aa80 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayRequest.java @@ -0,0 +1,256 @@ +package com.hfkj.common.pay.util.sdk; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.ConnectTimeoutException; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.BasicHttpClientConnectionManager; +import org.apache.http.util.EntityUtils; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import java.io.InputStream; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.security.KeyStore; +import java.security.SecureRandom; + +public class WXPayRequest { + private WXPayConfig config; + public WXPayRequest(WXPayConfig config) throws Exception{ + + this.config = config; + } + + /** + * 请求,只请求一次,不做重试 + * @param domain + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @param useCert 是否使用证书,针对退款、撤销等操作 + * @return + * @throws Exception + */ + private String requestOnce(final String domain, String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert) throws Exception { + BasicHttpClientConnectionManager connManager; + if (useCert) { + // 证书 + char[] password = config.getMchID().toCharArray(); + InputStream certStream = config.getCertStream(); + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(certStream, password); + + // 实例化密钥库 & 初始化密钥工厂 + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password); + + // 创建 SSLContext + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(kmf.getKeyManagers(), null, new SecureRandom()); + + SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory( + sslContext, + new String[]{"TLSv1"}, + null, + new DefaultHostnameVerifier()); + + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", sslConnectionSocketFactory) + .build(), + null, + null, + null + ); + } + else { + connManager = new BasicHttpClientConnectionManager( + RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", SSLConnectionSocketFactory.getSocketFactory()) + .build(), + null, + null, + null + ); + } + + HttpClient httpClient = HttpClientBuilder.create() + .setConnectionManager(connManager) + .build(); + + String url = "https://" + domain + urlSuffix; + HttpPost httpPost = new HttpPost(url); + + RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(readTimeoutMs).setConnectTimeout(connectTimeoutMs).build(); + httpPost.setConfig(requestConfig); + + StringEntity postEntity = new StringEntity(data, "UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.addHeader("User-Agent", WXPayConstants.USER_AGENT + " " + config.getMchID()); + httpPost.setEntity(postEntity); + + HttpResponse httpResponse = httpClient.execute(httpPost); + HttpEntity httpEntity = httpResponse.getEntity(); + return EntityUtils.toString(httpEntity, "UTF-8"); + + } + + + private String request(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean useCert, boolean autoReport) throws Exception { + Exception exception = null; + long elapsedTimeMillis = 0; + long startTimestampMs = WXPayUtil.getCurrentTimestampMs(); + boolean firstHasDnsErr = false; + boolean firstHasConnectTimeout = false; + boolean firstHasReadTimeout = false; + IWXPayDomain.DomainInfo domainInfo = config.getWXPayDomain().getDomain(config); + if(domainInfo == null){ + throw new Exception("WXPayConfig.getWXPayDomain().getDomain() is empty or null"); + } + try { + String result = requestOnce(domainInfo.domain, urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, useCert); + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, null); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + return result; + } + catch (UnknownHostException ex) { // dns 解析错误,或域名不存在 + exception = ex; + firstHasDnsErr = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("UnknownHostException for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout + ); + } + catch (ConnectTimeoutException ex) { + exception = ex; + firstHasConnectTimeout = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("connect timeout happened for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout + ); + } + catch (SocketTimeoutException ex) { + exception = ex; + firstHasReadTimeout = true; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayUtil.getLogger().warn("timeout happened for domainInfo {}", domainInfo); + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + } + catch (Exception ex) { + exception = ex; + elapsedTimeMillis = WXPayUtil.getCurrentTimestampMs()-startTimestampMs; + WXPayReport.getInstance(config).report( + uuid, + elapsedTimeMillis, + domainInfo.domain, + domainInfo.primaryDomain, + connectTimeoutMs, + readTimeoutMs, + firstHasDnsErr, + firstHasConnectTimeout, + firstHasReadTimeout); + } + config.getWXPayDomain().report(domainInfo.domain, elapsedTimeMillis, exception); + throw exception; + } + + + /** + * 可重试的,非双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @return + */ + public String requestWithoutCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), false, autoReport); + } + + /** + * 可重试的,非双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @return + */ + public String requestWithoutCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, false, autoReport); + } + + /** + * 可重试的,双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @return + */ + public String requestWithCert(String urlSuffix, String uuid, String data, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, config.getHttpConnectTimeoutMs(), config.getHttpReadTimeoutMs(), true, autoReport); + } + + /** + * 可重试的,双向认证的请求 + * @param urlSuffix + * @param uuid + * @param data + * @param connectTimeoutMs + * @param readTimeoutMs + * @return + */ + public String requestWithCert(String urlSuffix, String uuid, String data, int connectTimeoutMs, int readTimeoutMs, boolean autoReport) throws Exception { + return this.request(urlSuffix, uuid, data, connectTimeoutMs, readTimeoutMs, true, autoReport); + } +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayUtil.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayUtil.java new file mode 100644 index 0000000..419dd82 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayUtil.java @@ -0,0 +1,294 @@ +package com.hfkj.common.pay.util.sdk; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.*; + + +public class WXPayUtil { + + private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + private static final Random RANDOM = new SecureRandom(); + + /** + * XML格式字符串转换为Map + * + * @param strXML XML字符串 + * @return XML数据转换后的Map + * @throws Exception + */ + public static Map xmlToMap(String strXML) throws Exception { + try { + Map data = new HashMap(); + DocumentBuilder documentBuilder = WXPayXmlUtil.newDocumentBuilder(); + InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); + org.w3c.dom.Document doc = documentBuilder.parse(stream); + doc.getDocumentElement().normalize(); + NodeList nodeList = doc.getDocumentElement().getChildNodes(); + for (int idx = 0; idx < nodeList.getLength(); ++idx) { + Node node = nodeList.item(idx); + if (node.getNodeType() == Node.ELEMENT_NODE) { + org.w3c.dom.Element element = (org.w3c.dom.Element) node; + data.put(element.getNodeName(), element.getTextContent()); + } + } + try { + stream.close(); + } catch (Exception ex) { + // do nothing + } + return data; + } catch (Exception ex) { + WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML); + throw ex; + } + + } + + /** + * 将Map转换为XML格式的字符串 + * + * @param data Map类型数据 + * @return XML格式的字符串 + * @throws Exception + */ + public static String mapToXml(Map data) throws Exception { + org.w3c.dom.Document document = WXPayXmlUtil.newDocument(); + org.w3c.dom.Element root = document.createElement("xml"); + document.appendChild(root); + for (String key: data.keySet()) { + String value = data.get(key); + if (value == null) { + value = ""; + } + value = value.trim(); + org.w3c.dom.Element filed = document.createElement(key); + filed.appendChild(document.createTextNode(value)); + root.appendChild(filed); + } + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + DOMSource source = new DOMSource(document); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); + try { + writer.close(); + } + catch (Exception ex) { + } + return output; + } + + + /** + * 生成带有 sign 的 XML 格式字符串 + * + * @param data Map类型数据 + * @param key API密钥 + * @return 含有sign字段的XML + */ + public static String generateSignedXml(final Map data, String key) throws Exception { + return generateSignedXml(data, key, WXPayConstants.SignType.MD5); + } + + /** + * 生成带有 sign 的 XML 格式字符串 + * + * @param data Map类型数据 + * @param key API密钥 + * @param signType 签名类型 + * @return 含有sign字段的XML + */ + public static String generateSignedXml(final Map data, String key, WXPayConstants.SignType signType) throws Exception { + String sign = generateSignature(data, key, signType); + data.put(WXPayConstants.FIELD_SIGN, sign); + return mapToXml(data); + } + + + /** + * 判断签名是否正确 + * + * @param xmlStr XML格式数据 + * @param key API密钥 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(String xmlStr, String key) throws Exception { + Map data = xmlToMap(xmlStr); + if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { + return false; + } + String sign = data.get(WXPayConstants.FIELD_SIGN); + return generateSignature(data, key).equals(sign); + } + + /** + * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。 + * + * @param data Map类型数据 + * @param key API密钥 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(Map data, String key) throws Exception { + return isSignatureValid(data, key, WXPayConstants.SignType.MD5); + } + + /** + * 判断签名是否正确,必须包含sign字段,否则返回false。 + * + * @param data Map类型数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名是否正确 + * @throws Exception + */ + public static boolean isSignatureValid(Map data, String key, WXPayConstants.SignType signType) throws Exception { + if (!data.containsKey(WXPayConstants.FIELD_SIGN) ) { + return false; + } + String sign = data.get(WXPayConstants.FIELD_SIGN); + return generateSignature(data, key, signType).equals(sign); + } + + /** + * 生成签名 + * + * @param data 待签名数据 + * @param key API密钥 + * @return 签名 + */ + public static String generateSignature(final Map data, String key) throws Exception { + return generateSignature(data, key, WXPayConstants.SignType.MD5); + } + + /** + * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 + * + * @param data 待签名数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名 + */ + public static String generateSignature(final Map data, String key, WXPayConstants.SignType signType) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 + sb.append(k).append("=").append(data.get(k).trim()).append("&"); + } + sb.append("key=").append(key); + if (WXPayConstants.SignType.MD5.equals(signType)) { + return MD5(sb.toString()).toUpperCase(); + } + else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) { + return HMACSHA256(sb.toString(), key); + } + else { + throw new Exception(String.format("Invalid sign_type: %s", signType)); + } + } + + + /** + * 获取随机字符串 Nonce Str + * + * @return String 随机字符串 + */ + public static String generateNonceStr() { + char[] nonceChars = new char[32]; + for (int index = 0; index < nonceChars.length; ++index) { + nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + return new String(nonceChars); + } + + + /** + * 生成 MD5 + * + * @param data 待处理数据 + * @return MD5结果 + */ + public static String MD5(String data) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] array = md.digest(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 生成 HMACSHA256 + * @param data 待处理数据 + * @param key 密钥 + * @return 加密结果 + * @throws Exception + */ + public static String HMACSHA256(String data, String key) throws Exception { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 日志 + * @return + */ + public static Logger getLogger() { + Logger logger = LoggerFactory.getLogger("wxpay java sdk"); + return logger; + } + + /** + * 获取当前时间戳,单位秒 + * @return + */ + public static long getCurrentTimestamp() { + return System.currentTimeMillis()/1000; + } + + /** + * 获取当前时间戳,单位毫秒 + * @return + */ + public static long getCurrentTimestampMs() { + return System.currentTimeMillis(); + } + +} diff --git a/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayXmlUtil.java b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayXmlUtil.java new file mode 100644 index 0000000..77f5f29 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/pay/util/sdk/WXPayXmlUtil.java @@ -0,0 +1,30 @@ +package com.hfkj.common.pay.util.sdk; + +import org.w3c.dom.Document; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * 2018/7/3 + */ +public final class WXPayXmlUtil { + public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + documentBuilderFactory.setXIncludeAware(false); + documentBuilderFactory.setExpandEntityReferences(false); + + return documentBuilderFactory.newDocumentBuilder(); + } + + public static Document newDocument() throws ParserConfigurationException { + return newDocumentBuilder().newDocument(); + } +} diff --git a/service/src/main/java/com/hfkj/common/security/AESEncodeUtil.java b/service/src/main/java/com/hfkj/common/security/AESEncodeUtil.java new file mode 100644 index 0000000..6dc3bf5 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/AESEncodeUtil.java @@ -0,0 +1,76 @@ +package com.hfkj.common.security; + +import org.apache.commons.lang3.StringUtils; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.spec.SecretKeySpec; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.Base64; + +public class AESEncodeUtil { + + private static final String SEC_KEY="Skufk5oi85wDFGl888i6wsRSTkdd5df5"; + public static String binary(byte[] bytes, int radix){ + return new BigInteger(1, bytes).toString(radix); + } + + public static String base64Encode(byte[] bytes){ + return Base64.getEncoder().encodeToString(bytes);//.replaceAll("\\s*", ""); + } + + public static byte[] base64Decode(String base64Code) throws Exception{ + return StringUtils.isEmpty(base64Code) ? null : Base64.getDecoder().decode(base64Code); + } + + public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception{ + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); + secureRandom.setSeed(encryptKey.getBytes()); + kgen.init(128, secureRandom); + Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES")); + return cipher.doFinal(content.getBytes("utf-8")); + + } + + public static String aesEncrypt(String content) throws Exception{ + return base64Encode(aesEncryptToBytes(content, SEC_KEY)); + //return content; + } + + public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception{ + KeyGenerator kgen = KeyGenerator.getInstance("AES"); + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); + secureRandom.setSeed(decryptKey.getBytes()); + kgen.init(128, secureRandom); + +// byte[] key = {86, -42, -11, 12, 92, 41, 31, -48, 104, 31, -38, 106, -51, -16, -55, -96}; + + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES")); + byte[] decryptBytes = cipher.doFinal(encryptBytes); + + return new String(decryptBytes); + } + + public static String aesDecrypt(String encryptStr) throws Exception{ + return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), SEC_KEY); + } + + public static void main(String[] args) throws Exception{ + long currentTimeMillis = System.currentTimeMillis(); + + System.out.println(AESEncodeUtil.aesEncrypt("123456")); + /* String content = "{\"create_time\":1573544092110,\"order_serial_no\":\"40280e816db49c0b016db4a2c31f0004\",\"product_code\":\"8a9e80045cf85e54015cf8809fcd\",\"product_name\":\"平安发票贷\",\"uscc\":\"91370781687233838E\"}"; + System.out.println("加密前" + content); + + String encrypt = com.sun.org.apache.xml.internal.security.utils.Base64.encode(aesEncryptToBytes(content, "WdOjUqtRxcBshw")); + System.out.println("加密后" + encrypt);*/ + +/* String decrypt = aesDecryptByBytes(base64Decode("i98CPRG2UI2kRzP9WE6WyF7hQQmZB5nOvc9s8BoISUJlrt59R3TPFiDYI9FNpj3BtKKR8P9JMoTSRP0/lP+SzA=="), "WdOjUqtRxcBshw"); + System.out.println("解密后" + decrypt); + System.out.println(System.currentTimeMillis() - currentTimeMillis);*/ + } +} diff --git a/service/src/main/java/com/hfkj/common/security/AuthManager.java b/service/src/main/java/com/hfkj/common/security/AuthManager.java new file mode 100644 index 0000000..6ca9af4 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/AuthManager.java @@ -0,0 +1,13 @@ +package com.hfkj.common.security; + + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface AuthManager { + + String desc() default ""; + +} diff --git a/service/src/main/java/com/hfkj/common/security/Base64Util.java b/service/src/main/java/com/hfkj/common/security/Base64Util.java new file mode 100644 index 0000000..a78fbaf --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/Base64Util.java @@ -0,0 +1,42 @@ +package com.hfkj.common.security; + +import java.util.Base64; + +public class Base64Util { + /** + * @param data + * @return str + * @throws Exception + */ + public static String encode(String data) throws Exception{ +// String encodeBase64 = new BASE64Encoder().encode(data.getBytes("utf-8")); + String encodeBase64 = Base64.getEncoder().encodeToString(data.getBytes("utf-8")); + String safeBase64Str = encodeBase64.replace('+', '-'); + safeBase64Str = safeBase64Str.replace('/', '_'); + safeBase64Str = safeBase64Str.replaceAll("=", ""); + return safeBase64Str.replaceAll("\\s*", ""); + } + + /** + * @param safeBase64Str + * @return str + * @throws Exception + */ + public static String decode(final String safeBase64Str) throws Exception{ + String base64Str = safeBase64Str.replace('-', '+'); + base64Str = base64Str.replace('_', '/'); + int mod4 = base64Str.length() % 4; + if(mod4 > 0){ + base64Str += "====".substring(mod4); + } + +// byte[] ret = new BASE64Decoder().decodeBuffer(base64Str); + byte[] ret = Base64.getDecoder().decode(base64Str); + return new String(ret, "utf-8"); + } + + public static void main(String[] args) throws Exception { + System.out.println(encode("abcd1234")); + System.out.println(decode("YWJjZDEyMzQ")); + } +} diff --git a/service/src/main/java/com/hfkj/common/security/CookieUtil.java b/service/src/main/java/com/hfkj/common/security/CookieUtil.java new file mode 100644 index 0000000..93618a9 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/CookieUtil.java @@ -0,0 +1,123 @@ +package com.hfkj.common.security; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.Map; + +public class CookieUtil { + /** + * 保存cookie + * + * @param request + * @param response + * @param name + * @param value + * @param expire + * unit:second + */ + public static void saveCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, int expire){ + Cookie cookie; + if(containsName(request, name)){ + cookie = getCookieByName(request, name); + cookie.setValue(value); + }else{ + cookie = new Cookie(name, value); + } + cookie.setMaxAge(expire); + cookie.setPath("/"); + response.addCookie(cookie); + } + + /** + * 保存cookie + * + * @param request + * @param response + * @param name + * @param value + * @param expire + */ + public static void saveCookie(HttpServletResponse response, String name, String value, int expire){ + Cookie cookie = new Cookie(name, value); + cookie.setMaxAge(expire); + cookie.setPath("/"); + response.addCookie(cookie); + } + + /** + * 根据名字获取cookie + * + * @param request + * @param name + * cookie名字 + * @return cookie + */ + public static Cookie getCookieByName(HttpServletRequest request, String name){ + Map cookieMap = readCookieMap(request); + if(cookieMap.containsKey(name)){ + return cookieMap.get(name); + } + return null; + } + + /** + * 判断cookie中是否存在该名字 + * + * @param request + * @param name + * @return true if contains + */ + public static boolean containsName(HttpServletRequest request, String name){ + Map cookieMap = readCookieMap(request); + return cookieMap.containsKey(name); + } + + /** + * 删除cookie + * + * @param request + * @param response + * @param name + */ + public static void delCookie(HttpServletResponse response, String name){ + saveCookie(response, name, null, 0); + } + + /** + * 刷新cookie + * + * @param request + * @param response + * @param name + * @param expire + */ + public static void refreshCookie(HttpServletRequest request, HttpServletResponse response, String name, int expire){ + if(containsName(request, name)){ + Cookie cookie = getCookieByName(request, name); + cookie.setMaxAge(expire); + cookie.setPath("/"); + response.addCookie(cookie); + } + } + + /** + * 将cookie封装到Map里面 + * + * @param request + * @return + */ + private static Map readCookieMap(HttpServletRequest request){ + Map cookieMap = new HashMap(); + Cookie[] cookies = request.getCookies(); + /* request.getCookies(); + Cookie[] cookies = request.getHeader("");*/ + if(cookies != null){ + for(Cookie cookie : cookies){ + cookieMap.put(cookie.getName(), cookie); + } + } + return cookieMap; + } +} diff --git a/service/src/main/java/com/hfkj/common/security/DesUtil.java b/service/src/main/java/com/hfkj/common/security/DesUtil.java new file mode 100644 index 0000000..e409578 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/DesUtil.java @@ -0,0 +1,277 @@ +package com.hfkj.common.security; + +import java.nio.charset.Charset; +import java.security.Key; +import java.security.SecureRandom; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import javax.crypto.spec.DESedeKeySpec; +import javax.crypto.spec.IvParameterSpec; + +import org.apache.commons.codec.binary.Base64; +//import org.apache.commons.lang3.RandomStringUtils; + + +import com.thoughtworks.xstream.core.util.Base64Encoder; + +public class DesUtil { + + public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding"; + + /** + * DES算法,加密 + * + * @param data + * 待加密字符串 + * @param key + * 加密私钥,长度不能够小于8位 + * @return 加密后的字节数组,一般结合Base64编码使用 + * @throws CryptException + * 异常 + */ + public static byte[] encode(String key, String data) throws Exception { + return encode(key, data.getBytes()); + } + + /** + * DES算法,加密 + * + * @param data + * 待加密字符串 + * @param key + * 加密私钥,长度不能够小于8位 + * @return 加密后的字节数组,一般结合Base64编码使用 + * @throws CryptException + * 异常 + */ + public static byte[] encode(String key, byte[] data) throws Exception { + try { + DESKeySpec dks = new DESKeySpec(key.getBytes()); + + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + // key的长度不能够小于8位字节 + Key secretKey = keyFactory.generateSecret(dks); + Cipher cipher = Cipher.getInstance(ALGORITHM_DES); + IvParameterSpec iv = new IvParameterSpec(key.getBytes()); + AlgorithmParameterSpec paramSpec = iv; + cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec); + + byte[] bytes = cipher.doFinal(data); + return bytes; + // return byte2HexStr(bytes); + // return byte2hex(new String(bytes)); + // return new String(new BASE64Encoder().encode(bytes)); + // return new String(bytes); + } catch (Exception e) { + throw new Exception(e); + } + } + + /** + * DES算法,解密 + * + * @param data + * 待解密字符串 + * @param key + * 解密私钥,长度不能够小于8位 + * @return 解密后的字节数组 + * @throws Exception + * 异常 + */ + public static byte[] decode(String key, byte[] data) throws Exception { + try { + // SecureRandom sr = new SecureRandom(); + DESKeySpec dks = new DESKeySpec(key.getBytes()); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + // key的长度不能够小于8位字节 + Key secretKey = keyFactory.generateSecret(dks); + Cipher cipher = Cipher.getInstance(ALGORITHM_DES); + IvParameterSpec iv = new IvParameterSpec(key.getBytes()); + AlgorithmParameterSpec paramSpec = iv; + cipher.init(Cipher.DECRYPT_MODE, secretKey, paramSpec); + return cipher.doFinal(data); + } catch (Exception e) { + throw new Exception(e); + } + } + + /** + * 获取编码后的值 + * + * @param key + * @param data + * @return + * @throws Exception + */ + public static String decode(String key, String data) { + byte[] datas; + String value = null; + try { + + datas = decode(key, new Base64Encoder().decode(data)); + + value = new String(datas); + } catch (Exception e) { + value = ""; + } + return value; + } + + public static String byte2HexStr(byte[] b) { + String hs = ""; + String stmp = ""; + for (int n = 0; n < b.length; n++) { + stmp = (Integer.toHexString(b[n] & 0XFF)); + if (stmp.length() == 1) + hs = hs + "0" + stmp; + else + hs = hs + stmp; + // if (n8800030132003900701123120457349857394500000188000301650001000402016-07-28 13:20:50150"; + // String s = HexUtil.byte2HexStr(DesUtil.encode(key, data)); + // System.err.println(s); + // System.err.println(DesUtil.encode(key, data.getBytes()).length); + // String s2 = new String(DesUtil.decode(key, HexUtil.hexStr2Bytes(s))); + // System.err.println(s2); + + // String s = encode("123", Charset.forName("GBK"), "d0fb65e5"); + // System.out.println(s); + // + // String e = decode("d0fb65e5", "258946d6143e30f9", + // Charset.forName("UTF-8")); + // System.out.println(e); + + /*String s = encode("中国", Charset.forName("UTF-8"),"12345678"); + System.out.println(s);*/ + //String data = "T3xbPEKEXV9+CbBw8D1B+N2jk8xwa55s0Bde48c49YDwYfnUdBVz6Kj4HS2oCA1TTiqJkCUIYa5ckMhJeByBCAMsqu21LmFjb/hdW0y1Tt0Wk5PqmO8FAg=="; + String data = "T3xbPEKEXV9+CbBw8D1B+N2jk8xwa55s0Bde48c49YDMmj1rv5nOrkawWt8fskSihNw0wugKUT1xWjHhIN8af7NylRVfhJvbeja2Zjjxnwk3FEKgyvIvJnk3QgiY4aghqQcGKxDOlAxT/kjrkDd2ESu1IWkpi+0HGnG3rKSL6+a1Nu7aW+rPHwXUOmHSgWFZFb9HhlfKI/jml3GhMZBWsZFirayyMMi8UKrdYN7ANPEB/6uV9iVtpLF5Kz8M2+GpI0EqRhPFAH2u3Q/RSgW8ei2ZbOY9NnbkdwuOjU93wgJxdY1Y93hvLYNe1i9QkSM1"; + String data1 = "T3xbPEKEXV9+CbBw8D1B+N2jk8xwa55s0Bde48c49YBr4/b4yBwN2FIVZZn+Xg9KQTDoTCLu3YtByaWh7zPmdcpBr9FGARduhPrwSnYTFJ0VVVSK/UzPWdHN2YYd4yHGQRJ2HEr/1egt2JUHpWr0JA=="; +/* { + "success": true, + "message": "ok", + "cards": [{ + "cardNo": "8800030115015107746" + }, { + "cardNo": "8800030115015119428" + }, { + "cardNo": "8800030128003170055" + }, { + "cardNo": "8800030132003656709" + }, { + "cardNo": "8800030132004014510" + }, { + "cardNo": "8800031104000000248" + }] + }*/ + + String a = decode("F8E91A3C", data,Charset.forName("UTF-8")); + System.out.println(a); + System.out.println("完成"); + } +} diff --git a/service/src/main/java/com/hfkj/common/security/LoginCache.java b/service/src/main/java/com/hfkj/common/security/LoginCache.java new file mode 100644 index 0000000..34f9bce --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/LoginCache.java @@ -0,0 +1,60 @@ +package com.hfkj.common.security; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class LoginCache { + + private static Map CACHE_DATA = new ConcurrentHashMap<>(); + + public static T getData(String key) { + CacheData data = CACHE_DATA.get(key); + if (data != null){ + if(data.getExpire() <= 0 || data.getSaveTime() >= System.currentTimeMillis()) { + return data.getData(); + }else{ + clear(key); + } + } + return null; + } + + public static void setData(String key, T data, int expire) { + CACHE_DATA.put(key, new CacheData(data, expire)); + } + + public static void activeData(String key,int expire){ + Object data = getData(key); + if(data != null){ + setData(key,data,expire); + } + } + + public static void clear(String key) { + CACHE_DATA.remove(key); + } + + private static class CacheData { + CacheData(T t, int expire) { + this.data = t; + this.expire = expire <= 0 ? 0 : expire*1000; + this.saveTime = System.currentTimeMillis() + this.expire; + } + + private T data; + private long saveTime; // 存活时间 + private long expire; // 过期时间 小于等于0标识永久存活 + + public T getData() { + return data; + } + + public long getExpire() { + return expire; + } + + public long getSaveTime() { + return saveTime; + } + } +} diff --git a/service/src/main/java/com/hfkj/common/security/SessionObject.java b/service/src/main/java/com/hfkj/common/security/SessionObject.java new file mode 100644 index 0000000..80bbb1f --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/SessionObject.java @@ -0,0 +1,57 @@ +package com.hfkj.common.security; + +import org.apache.commons.lang3.StringUtils; + +public class SessionObject { + + /** + * 登录用户的唯一标识 + */ + private String uniqueCode; + + /** + * 1:会员;2:渠道;3.管理员 + */ + private Integer type; + + /** + * 存储用户基本信息 + */ + private Object object; + + public SessionObject(){ + + } + public SessionObject(String uniqueCode, Integer type, Object object){ + this.uniqueCode = uniqueCode; + this.type = type; + this.object = object; + } + + public String getUniqueCode() throws Exception { + if(StringUtils.isEmpty(uniqueCode)){ + throw new Exception("SessionObject uniqueCode is null"); + } + return uniqueCode; + } + + public void setUniqueCode(String uniqueCode) { + this.uniqueCode = uniqueCode; + } + + public Object getObject() { + return object; + } + + public void setObject(Object object) { + this.object = object; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } +} diff --git a/service/src/main/java/com/hfkj/common/security/UserCenter.java b/service/src/main/java/com/hfkj/common/security/UserCenter.java new file mode 100644 index 0000000..6d71623 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/UserCenter.java @@ -0,0 +1,153 @@ +package com.hfkj.common.security; + +import com.hfkj.common.exception.ErrorCode; +import com.hfkj.common.exception.ErrorHelp; +import com.hfkj.common.exception.SysCode; +import com.hfkj.common.utils.RedisUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@Component +public class UserCenter { + + private static Logger log = LoggerFactory.getLogger(UserCenter.class); + + @Autowired + private RedisUtil redisUtil; + + private final String COOKIE_FIELD = "_ida"; + private final int EXPIRE = 3600 * 24 * 7;//cookie过期时间为7天 + + /** + * 判断用户是否登录,并且不能单个用户同时登录 + * @param request + * @return boolean + * @throws Exception + */ + public boolean isLogin(HttpServletRequest request){ + String token = request.getHeader("Authorization"); + if(StringUtils.isBlank(token)){ + Cookie cookie = CookieUtil.getCookieByName(request, COOKIE_FIELD); + if(cookie != null && StringUtils.isNotBlank(cookie.getValue())){ + token = cookie.getValue(); + } + } + if(StringUtils.isBlank(token)){ + return false; + } + try { + if (!StringUtils.isEmpty(token)) { + SessionObject cacheStr = (SessionObject)redisUtil.get(token); + if (cacheStr != null) { + redisUtil.expire(token,EXPIRE); + return true; + } + } + }catch (Exception e){ + e.printStackTrace(); + } + return false; + } + + /** + * + * @Title: isTokenLogin + * @Description: 支持token形式的校验登录 + * @author: 机器猫 + * @param: @param token + * @param: @return + * @param: @throws Exception + * @return: boolean + * @throws + */ + public boolean isTokenLogin(String token){ + try { + log.error("------------------------------" + token); + if(!StringUtils.isEmpty(token)){ + SessionObject cacheStr = (SessionObject)redisUtil.get(token); + if (cacheStr != null) { + redisUtil.expire(token,EXPIRE); + return true; + } + } + return false; + } catch (Exception e) { + log.error("isTokenLogin failed",e); + return false; + } + } + + public String read(HttpServletRequest request){ + Cookie cookie = CookieUtil.getCookieByName(request, COOKIE_FIELD); + if(cookie == null){ + return null; + } + return cookie.getValue(); + } + + public SessionObject getSessionObject(HttpServletRequest request) throws Exception{ + String token = request.getHeader("Authorization"); + if (StringUtils.isBlank(token)) { + if (StringUtils.isNotBlank(read(request))) { + token = read(request); + } + } + if (redisUtil.get(token) == null) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.USE_VISIT_ILLEGAL, ""); + } + return (SessionObject) redisUtil.get(token); + } + + /** + * @param request + * @param response + * @param response + * @throws Exception + */ + public void save(HttpServletRequest request, HttpServletResponse response, SessionObject seObj) throws Exception{ + CookieUtil.saveCookie(request, response, COOKIE_FIELD, seObj.getUniqueCode(), EXPIRE); + redisUtil.set(seObj.getUniqueCode(), seObj, EXPIRE); + } + + /** + * 刷新cookie信息 + * + * @param request + * @param response + * @throws Exception + */ + public void refreshCookie(HttpServletRequest request, HttpServletResponse response) throws Exception{ + CookieUtil.refreshCookie(request, response, COOKIE_FIELD, EXPIRE); + } + + /** + * @param request + * @param response + * @throws Exception + */ + public void remove(HttpServletRequest request, HttpServletResponse response) { + String token = request.getHeader("Authorization"); + if(StringUtils.isNotBlank(token)){ + //通过token方式登录 + redisUtil.del(token); + CookieUtil.delCookie(response, COOKIE_FIELD); + }else{ + String jo = read(request); + if(StringUtils.isNotBlank(jo)){ + redisUtil.del(jo); + CookieUtil.delCookie(response, COOKIE_FIELD); + } + } + + + + } + +} diff --git a/service/src/main/java/com/hfkj/common/security/VerifyCode.java b/service/src/main/java/com/hfkj/common/security/VerifyCode.java new file mode 100644 index 0000000..2ffc3e3 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/VerifyCode.java @@ -0,0 +1,44 @@ +package com.hfkj.common.security; + +import org.apache.commons.lang3.StringUtils; + +public class VerifyCode { + + /** + * 验证码唯一标识 手机号 + */ + private String uniqueCode; + + /** + * 存储验证码 + */ + private String verifyCode; + + public VerifyCode(){ + + } + public VerifyCode(String uniqueCode, String verifyCode){ + this.uniqueCode = uniqueCode; + this.verifyCode = verifyCode; + } + + public String getUniqueCode() throws Exception { + if(StringUtils.isEmpty(uniqueCode)){ + throw new Exception("VerifyCode uniqueCode is null"); + } + return uniqueCode; + } + + public void setUniqueCode(String uniqueCode) { + this.uniqueCode = uniqueCode; + } + + public String getObject() { + return verifyCode; + } + + public void setObject(String verifyCode) { + this.verifyCode = verifyCode; + } + +} diff --git a/service/src/main/java/com/hfkj/common/security/VerifyCodeStorage.java b/service/src/main/java/com/hfkj/common/security/VerifyCodeStorage.java new file mode 100644 index 0000000..eeedf5a --- /dev/null +++ b/service/src/main/java/com/hfkj/common/security/VerifyCodeStorage.java @@ -0,0 +1,29 @@ +package com.hfkj.common.security; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VerifyCodeStorage { + + private static Logger log = LoggerFactory.getLogger(VerifyCodeStorage.class); + + private static final int EXPIRE = 600;//cookie过期时间为10分钟,600秒 + + + /** + * @param + * @throws Exception + */ + public static void save(VerifyCode verifyCode) throws Exception{ + LoginCache.setData(verifyCode.getUniqueCode(), verifyCode, EXPIRE); + } + + + public static VerifyCode getDate(String uniqueCode) throws Exception{ + return LoginCache.getData(uniqueCode); + } + + public static void remove(String uniqueCode) throws Exception{ + LoginCache.clear(uniqueCode); + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/CoordCommonUtil.java b/service/src/main/java/com/hfkj/common/utils/CoordCommonUtil.java new file mode 100644 index 0000000..b1266d8 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/CoordCommonUtil.java @@ -0,0 +1,38 @@ +package com.hfkj.common.utils; + +/** + * @Auther: 胡锐 + * @Description: + * @Date: 2021/4/1 20:32 + */ +public class CoordCommonUtil { + + + private static final double EARTH_RADIUS = 6371000; // 平均半径,单位:m;不是赤道半径。赤道为6378左右 + + /** + * 获得球面(地球)上两个点之间的距离(坐标可以为WGS84、GCJ02等任何一种坐标,但两个点的坐标类型必须相同) + * + * @param lon1 起点的经度 + * @param lat1 起点的纬度 + * @param lon2 终点的经度 + * @param lat2 终点的纬度 + * @return 两点之间的距离,单位是米 + */ + public static double getDistance(Double lat1,Double lng1,Double lat2,Double lng2) { + // 经纬度(角度)转弧度。弧度用作参数,以调用Math.cos和Math.sin + double radiansAX = Math.toRadians(lng1); // A经弧度 + double radiansAY = Math.toRadians(lat1); // A纬弧度 + double radiansBX = Math.toRadians(lng2); // B经弧度 + double radiansBY = Math.toRadians(lat2); // B纬弧度 + + // 公式中“cosβ1cosβ2cos(α1-α2)+sinβ1sinβ2”的部分,得到∠AOB的cos值 + double cos = Math.cos(radiansAY) * Math.cos(radiansBY) * Math.cos(radiansAX - radiansBX) + + Math.sin(radiansAY) * Math.sin(radiansBY); +// System.out.println("cos = " + cos); // 值域[-1,1] + double acos = Math.acos(cos); // 反余弦值 +// System.out.println("acos = " + acos); // 值域[0,π] +// System.out.println("∠AOB = " + Math.toDegrees(acos)); // 球心角 值域[0,180] + return EARTH_RADIUS * acos; // 最终结果附上原文出处链接及本声明。 + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/DateUtil.java b/service/src/main/java/com/hfkj/common/utils/DateUtil.java new file mode 100644 index 0000000..706a5bd --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/DateUtil.java @@ -0,0 +1,773 @@ +package com.hfkj.common.utils; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.time.*; +import java.util.Calendar; +import java.util.Date; + +public class DateUtil { + + private static Logger log = LoggerFactory.getLogger(DateUtil.class); + public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + public static SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM"); + public static SimpleDateFormat dateFormatDB = new SimpleDateFormat("yyyyMMdd");// 数据库使用的日期格式 + public static SimpleDateFormat dataTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + public static final String Y_M_D = "yyyy-MM-dd"; + public static final String Y_M_D_HM = "yyyy-MM-dd HH:mm"; + public static final String Y_M_D_HMS = "yyyy-MM-dd HH:mm:ss"; + public static final String YMD = "yyyyMMdd"; + public static final String YMDHM = "yyyyMMddHHmm"; + public static final String YMDHMS = "yyyyMMddHHmmss"; + public static final String YYMMDDH = "yyMMddHH"; + public static final String ymd = "yyyy/MM/dd"; + public static final String ymd_HM = "yyyy/MM/dd HH:mm"; + public static final String ymd_HMS = "yyyy/MM/dd HH:mm:ss"; + public static final String ymd_point = "yyyy.MM.dd"; + public static final String md_point = "MM.dd"; + public static final String Y_M = "yyyy-MM"; + private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + + + public static Integer getThisYear(){ + Calendar calendar = Calendar.getInstance(); + return calendar.get(Calendar.YEAR); + } + public static String date2String(Date date,String format) throws Exception{ + String str = null; + SimpleDateFormat sdf = new SimpleDateFormat(format); + if(date != null){ + str = sdf.format(date); + } + return str; + } + + public static Date long2Date(Long time) throws Exception{ + if(time != null){ + return new Date(time); + }else{ + return null; + } + } + /** + * 获取最近几个月的日期,例如今天是2018年6月26日,输入-3,返回最近三个月的日期2018年3月26日 + * @param delta + * @return + * @throws Exception + */ + public static Date getLastMonth(int delta){ + try { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.MONTH, delta); + return calendar.getTime(); + } catch (Exception e) { + log.error("getLastMonth error",e); + } + return null; + } + + /** + * 字符串转时间 + * + * @param date + * @param format + * @return + */ + public static Date StringToDate(String date, String format) { + if(StringUtils.isBlank(date)){ + return null; + } + SimpleDateFormat formatter = new SimpleDateFormat(format); + ParsePosition pos = new ParsePosition(0); + Date strtodate = formatter.parse(date, pos); + return strtodate; + } + + /** + * @throws + * @Title: getDateBegin + * @Description: TODO(获取指定日期开始) + * @author: 杜江 + * @param: [date] + * @return: java.util.Date + */ + public static Date getDateBegin(Date date) { + LocalDate nowDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + //设置零点 + LocalDateTime beginTime = LocalDateTime.of(nowDate, LocalTime.MIN); + //将时间进行格式化 + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zdt = beginTime.atZone(zoneId); + return Date.from(zdt.toInstant()); + } + + /** + * date转换成UNIX时间戳,毫秒 + * + * @param date + * @return + * @throws ParseException + */ + public static Long timesTamp(Date date,String formats) { + try { + // 获取系统时间 + SimpleDateFormat simpleDateFormat = new SimpleDateFormat( + formats); + String time = simpleDateFormat.format(date); + Long timeStemp = (simpleDateFormat.parse(time).getTime()); + return timeStemp; + }catch (Exception e){ + return null; + } + + } + + /** + * 获取某月第一天日期 + * @return Date + */ + public static Date getFisrtDayOfMonth(String dateString) throws ParseException { + DateFormat dateFormat = new SimpleDateFormat("yyyyMM"); + Date inputDate = dateFormat.parse(dateString); + + Calendar cal = Calendar.getInstance(); + cal.setTime(inputDate); + + int firstDay = cal.getActualMinimum(Calendar.DAY_OF_MONTH); + cal.set(Calendar.DAY_OF_MONTH, firstDay); + + return cal.getTime(); + } + + /** + * @throws + * @Title: addSeconds + * @Description: TODO(指定日期 , 指定秒后的时间) + * @author: 杜江 + * @param: [date, seconds] + * @return: java.util.Date + */ + public static Date addSeconds(Date date, int seconds) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.SECOND, seconds); + return calendar.getTime(); + } + + /** + * 获取某月最后一天日期 + * @return Date + */ + public static Date getLastDayOfMonth(String dateString) throws ParseException { + DateFormat dateFormat = new SimpleDateFormat("yyyyMM"); + Date inputDate = dateFormat.parse(dateString); + + Calendar cal = Calendar.getInstance(); + cal.setTime(inputDate); + + int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH); + cal.set(Calendar.DAY_OF_MONTH, lastDay); + + return cal.getTime(); + } + + /** + * + * @Title: getDaysOfMonth + * @Description: TODO(获取某月天数) + * @author: 杜江 + * @param: [date] + * @return: int + * @throws + */ + public static int getDaysOfMonth(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + return calendar.getActualMaximum(Calendar.DAY_OF_MONTH); + } + + /** + * @throws + * @Title: getDateBegin + * @Description: TODO(获取指定日期结束) + * @author: 杜江 + * @param: [date] + * @return: java.util.Date + */ + public static Date getDateEnd(Date date) { + LocalDate nowDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + //设置最大时间 + LocalDateTime beginTime = LocalDateTime.of(nowDate, LocalTime.MAX); + //将时间进行格式化 + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zdt = beginTime.atZone(zoneId); + return Date.from(zdt.toInstant()); + } + + /** + * 功能:传入时间字符串按所需格式返回时间 + * + * @param dateStr 时间字符串 + * @param format 跟传入dateStr时间的格式必须一样 yyyy-MM-dd HH:mm:ss | yyyy年MM月dd日 HH时mm分ss秒 + * @return + */ + public static Date format(String dateStr, String format) { + if (dateStr == null || dateStr == "") { + return new Date(); + } + if (dateStr == null || dateStr == "") { + format = "yyyy-MM-dd"; + } + Date date = null; + try { + DateFormat f = new SimpleDateFormat(format); + date = f.parse(dateStr); + } catch (ParseException e) { + e.printStackTrace(); + } + return date; + + } + + /** + * 功能:传入时间按所需格式返回时间字符串 + * + * @param date java.util.Date格式 + * @param format yyyy-MM-dd HH:mm:ss | yyyy年MM月dd日 HH时mm分ss秒 + * @return + */ + public static String format(Date date, String format) { + String result = ""; + try { + if (date == null) { + date = new Date();// 如果时间为空,则默认为当前时间 + } + if (format == null || format == "") {// 默认格式化形式 + format = "yyyy-MM-dd"; + } + DateFormat df = new SimpleDateFormat(format); + result = df.format(date); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * + * @Title: UtcToDate + * @Description: 转为+8区标准时间 + * @author: + * @param: [date, format] + * @return: java.util.Date + * @throws + */ + public static Date UtcToDate(String date, String format) { + try { + String newDate = date.replace("Z", " UTC"); + SimpleDateFormat formatter = new SimpleDateFormat(format); + Date strtodate = formatter.parse(newDate); + return strtodate; + } catch (ParseException e) { + e.printStackTrace(); + } + return null; + } + + /** + * + * @Title: getNewDate + * @Description: 指定日期加上制定月份得到新的日期 + * @author: + * @param: [cur, addNum] + * @return: java.util.Date + * @throws + */ + public static Date getNewDate(Date cur,Integer addNum) { + Calendar c = Calendar.getInstance(); + c.setTime(cur); //设置时间 + c.add(Calendar.MONTH, addNum); //日期分钟加1,Calendar.DATE(天),Calendar.HOUR(小时) + Date date = c.getTime(); //结果 + return date; + } + /** + * + * @Title: getTimeInterval + * @Description: 获取本周的星期数所对应的日期 + * @author: 杜江 + * @param: [dayWeek] + * @return: java.lang.String + * @throws + */ + public static String getTimeInterval(int dayWeek) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Calendar cal = Calendar.getInstance(); + cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天,按中国的习惯一个星期的第一天是星期一 + int day = 0; + if(dayWeek==1){ + day=-3; + } + if(dayWeek==2){ + day=-2; + } + if(dayWeek==3){ + day=-1; + } + if (dayWeek==4){ + day=0; + } + if(dayWeek==5){ + day=1; + } + if(dayWeek==6){ + day=2; + } + if(dayWeek==7){ + day=3; + } + cal.add(Calendar.DATE, cal.getFirstDayOfWeek() +day);// 根据日历的规则,给当前日期减去星期几与一个星期第一天的差值 + Date mondayDate = cal.getTime(); + String weekBegin = sdf.format(mondayDate); + return weekBegin; + } + /** + * + * @Title: getDayInWeek + * @Description: 获取今天是本周的第几天 + * @author: 杜江 + * @param: [] + * @return: int + * @throws + */ + public static int getDayInWeek(){ + Date today = new Date(); + Calendar c=Calendar.getInstance(); + c.setTime(today); + int weekday=c.get(Calendar.DAY_OF_WEEK); + if(weekday==1){ + weekday = weekday+6; + return weekday; + }else{ + weekday = weekday-1; + return weekday; + } + } + /** + * + * @Title: getLastWeekInDay + * @Description: 获取下周的星期几的日期 + * @author: 杜江 + * @param: [] + * @return: java.lang.String + * @throws + */ + public static Date getLastWeekInDay(int day){ + Calendar calendar = Calendar.getInstance(); + int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1; + int offset1 = day - dayOfWeek; + calendar.add(Calendar.DATE, offset1 + 7); + return calendar.getTime(); + } + /** + * + * @Title: changeDate + * @Description: 指定的日期减去天数后得到的日期 + * @author: 杜江 + * @param: [date, day] + * @return: java.util.Date + * @throws + */ + public static Date reduceDate(Date date,int day) throws ParseException { + long time = date.getTime(); // 得到指定日期的毫秒数 + day = day*24*60*60*1000; // 要减去的天数转换成毫秒数 + time-=day; // 相减得到新的毫秒数 + return new Date(time); // 将毫秒数转换成日期 + } + + /** + * + * @Title: changeDate + * @Description: 指定的日期加上天数后得到的日期 + * @author: 杜江 + * @param: [date, day] + * @return: java.util.Date + * @throws + */ + public static Date addDate(Date date,int day) throws ParseException { + long time = date.getTime(); // 得到指定日期的毫秒数 + long longTime = (long)day; + long addDay = longTime*24*60*60*1000; // 要加上的天数转换成毫秒数 + time+=addDay; // 相减得到新的毫秒数 + return new Date(time); // 将毫秒数转换成日期 + } + + /** + * + * @Title: getChinaWeek + * @Description: 功能:返回星期 1:星期一,2:星期二 ... 6:星期六 7:星期日 + * @author: 杜江 + * @param: [date] + * @return: int + * @throws + */ + public static int getChinaWeek(Date date) { + Calendar c = Calendar.getInstance(); + c.setTime(date); + int week = c.get(Calendar.DAY_OF_WEEK) - 1; + if (week == 0) { + return 7; + } else { + return week; + } + } + + /** + * + * @Title: getNextDay + * @Description: TODO(当前日期加一天) + * @author: 杜江 + * @param: [date] + * @return: java.util.Date + * @throws + */ + public static Date getNextDay(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + calendar.add(Calendar.DAY_OF_MONTH, +1);//+1今天的时间加一天 + date = calendar.getTime(); + return date; + } + + /** + * + * @Title: getNowBegin + * @Description: TODO(获取今天开始时间) + * @author: 杜江 + * @param: [] + * @return: java.util.Date + * @throws + */ + public static Date getNowBegin() { + //获取当前日期 + LocalDate nowDate = LocalDate.now(); + //设置零点 + LocalDateTime beginTime = LocalDateTime.of(nowDate, LocalTime.MIN); + //将时间进行格式化 + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zdt = beginTime.atZone(zoneId); + return Date.from(zdt.toInstant()); + } + + /** + * + * @Title: numberChange + * @Description: TODO(星期转换) + * @author: + * @param: [number] + * @return: java.lang.String + * @throws + */ + public static String numberChange(Integer number) { + if (number == 1) { + return "一"; + }else if (number == 2) { + return "二"; + } + else if (number == 3) { + return "三"; + } + else if (number == 4) { + return "四"; + } + else if (number == 5) { + return "五"; + } + else if (number == 6) { + return "六"; + } + else if (number == 7) { + return "日"; + }else { + return null; + } + } + + + /** + * + * @Title: getNowEnd + * @Description: TODO(获取今天结束时间) + * @author: 杜江 + * @param: [] + * @return: java.util.Date + * @throws + */ + public static Date getNowEnd() { + //获取当前日期 + LocalDate nowDate = LocalDate.now(); + //设置最大时间 + LocalDateTime endTime = LocalDateTime.of(nowDate,LocalTime.MAX); + //将时间进行格式化 + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zdt = endTime.atZone(zoneId); + return Date.from(zdt.toInstant()); + } + + /** + * * 获取当月的 天数 + * + */ + public static int getCurrentMonthDay() { + Calendar a = Calendar.getInstance(); + a.set(Calendar.DATE, 1); + a.roll(Calendar.DATE, -1); + int maxDate = a.get(Calendar.DATE); + return maxDate; + } + + /** + * 获取当前月第一天日期 + * @return Date + */ + public static String getCurrentMonthFirstDay() { + Calendar c = Calendar.getInstance(); + c.add(Calendar.MONTH, 0); + c.set(Calendar.DAY_OF_MONTH, 1); + String first = format.format(c.getTime()); + return first; + } + + /** + * 获取当前月最后一天日期 + * @return Date + */ + public static String getCurrentMonthlastDay() { + Calendar ca = Calendar.getInstance(); + ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH)); + String last = format.format(ca.getTime()); + return last; + } + + /** + * + * @Title: getMinutesDiff + * @Description: 获取newTime-oldTime相差分钟数 + * @author: gongjia + * @param: [oldTime, newTime] + * @return: int + * @throws + */ + public static long getMinutesDiff(Date oldTime, Date newTime) throws Exception{ + long oldTimeStamp = oldTime.getTime(); + long newTimeStamp = newTime.getTime(); + + long diffTimeStamp = newTimeStamp - oldTimeStamp; + + return diffTimeStamp / (1000 * 60); + } + + /** + * + * @Title: addDatetime + * @Description: 1.指定日期加上'年、月、日、时、分、秒' + * 2.'年、月、日、时、分、秒'允许负数 + * 3.下级时间会向上级传递(如增加1天25小时,实际增加2天1小时) + * 4.无需改变的值可指定为0 + * @author: gongjia + * @param: [date, year, month, day, hour, minute, second] + * @return: java.util.Date + * @throws + */ + public static Date addDatetime(Date date, int year, int month, int day, int hour, int minute, int second) throws Exception { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + calendar.add(Calendar.YEAR, year); + calendar.add(Calendar.MONTH, month); + calendar.add(Calendar.DAY_OF_MONTH, day); + calendar.add(Calendar.HOUR_OF_DAY, hour); + calendar.add(Calendar.MINUTE, minute); + calendar.add(Calendar.SECOND, second); + + return calendar.getTime(); + } + + public static Date getDateArea(Date oldDate) throws Exception { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + String strOld = format.format(oldDate); + + return format.parse(strOld); + } + + public static Date addMinute(Date time, int minute) { + Calendar c = Calendar.getInstance(); + c.setTime(time); //设置时间 + c.add(Calendar.MINUTE, minute); //日期分钟加1,Calendar.DATE(天),Calendar.HOUR(小时) + Date date = c.getTime(); //结果 + return date; + } + + /** + * 通过时间秒毫秒数判断两个时间的间隔 + * @param date1 + * @param date2 + * @return + */ + public static int differentDaysByMillisecond(Date date1,Date date2) + { + int days = (int)Math.ceil(((date2.getTime() - date1.getTime()) / (1000*3600*24))); + return days; + } + + /** + * date2比date1多的天数 + * @param date1 + * @param date2 + * @return + */ + public static int differentDays(Date date1,Date date2) + { + Calendar cal1 = Calendar.getInstance(); + cal1.setTime(date1); + + Calendar cal2 = Calendar.getInstance(); + cal2.setTime(date2); + int day1= cal1.get(Calendar.DAY_OF_YEAR); + int day2 = cal2.get(Calendar.DAY_OF_YEAR); + + int year1 = cal1.get(Calendar.YEAR); + int year2 = cal2.get(Calendar.YEAR); + if(year1 != year2) //同一年 + { + int timeDistance = 0 ; + for(int i = year1 ; i < year2 ; i ++) + { + if(i%4==0 && i%100!=0 || i%400==0) //闰年 + { + timeDistance += 366; + } + else //不是闰年 + { + timeDistance += 365; + } + } + + return timeDistance + (day2-day1) ; + } + else //不同年 + { + System.out.println("判断day2 - day1 : " + (day2-day1)); + return day2-day1; + } + } + + + /** + * 字符串日期转换成中文格式日期 + * + * @param date 字符串日期 yyyy-MM-dd + * @return yyyy年MM月dd日 + * @throws Exception + */ + public static String dateToCnDate(Date date) { + try { + String dateString = date2String(date, Y_M_D); + String result = ""; + String[] cnDate = new String[]{"〇", "一", "二", "三", "四", "五", "六", "七", "八", "九"}; + String ten = "十"; + String[] dateStr = dateString.split("-"); + for (int i = 0; i < dateStr.length; i++) { + for (int j = 0; j < dateStr[i].length(); j++) { + String charStr = dateStr[i]; + String str = String.valueOf(charStr.charAt(j)); + if (charStr.length() == 2) { + if (charStr.equals("10")) { + result += ten; + break; + } else { + if (j == 0) { + if (charStr.charAt(j) == '1') + result += ten; + else if (charStr.charAt(j) == '0') + result += ""; + else + result += cnDate[Integer.parseInt(str)] + ten; + } + if (j == 1) { + if (charStr.charAt(j) == '0') + result += ""; + else + result += cnDate[Integer.parseInt(str)]; + } + } + } else { + result += cnDate[Integer.parseInt(str)]; + } + } + if (i == 0) { + result += "年"; + continue; + } + if (i == 1) { + result += "月"; + continue; + } + if (i == 2) { + result += "日"; + continue; + } + } + return result; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 判断当前时间是否在[startTime, endTime]区间,注意时间格式要一致 + * + * @param nowTime 当前时间 + * @param startTime 开始时间 + * @param endTime 结束时间 + * @return + * @author jqlin + */ + public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) { + if (nowTime.getTime() == startTime.getTime() + || nowTime.getTime() == endTime.getTime()) { + return true; + } + + Calendar date = Calendar.getInstance(); + date.setTime(nowTime); + + Calendar begin = Calendar.getInstance(); + begin.setTime(startTime); + + Calendar end = Calendar.getInstance(); + end.setTime(endTime); + + if (date.after(begin) && date.before(end)) { + return true; + } else { + return false; + } + } + + + public static void main(String[] args) throws Exception { + String a = "51130319931105651X"; + System.out.println(a.substring(6,10)); + System.out.println(a.substring(10,12)); + System.out.println(a.substring(12,14)); + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/HttpUtils.java b/service/src/main/java/com/hfkj/common/utils/HttpUtils.java new file mode 100644 index 0000000..f9e682d --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/HttpUtils.java @@ -0,0 +1,311 @@ +package com.hfkj.common.utils; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.conn.ClientConnectionManager; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.scheme.SchemeRegistry; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class HttpUtils { + + /** + * get + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doGet(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpGet request = new HttpGet(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + /** + * post form + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param bodys + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + Map bodys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (bodys != null) { + List nameValuePairList = new ArrayList(); + + for (String key : bodys.keySet()) { + nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key))); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8"); + formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8"); + request.setEntity(formEntity); + } + + return httpClient.execute(request); + } + + /** + * Post String + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Post stream + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPost(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPost request = new HttpPost(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Put String + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + String body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (StringUtils.isNotBlank(body)) { + request.setEntity(new StringEntity(body, "utf-8")); + } + + return httpClient.execute(request); + } + + /** + * Put stream + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @param body + * @return + * @throws Exception + */ + public static HttpResponse doPut(String host, String path, String method, + Map headers, + Map querys, + byte[] body) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpPut request = new HttpPut(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + if (body != null) { + request.setEntity(new ByteArrayEntity(body)); + } + + return httpClient.execute(request); + } + + /** + * Delete + * + * @param host + * @param path + * @param method + * @param headers + * @param querys + * @return + * @throws Exception + */ + public static HttpResponse doDelete(String host, String path, String method, + Map headers, + Map querys) + throws Exception { + HttpClient httpClient = wrapClient(host); + + HttpDelete request = new HttpDelete(buildUrl(host, path, querys)); + for (Map.Entry e : headers.entrySet()) { + request.addHeader(e.getKey(), e.getValue()); + } + + return httpClient.execute(request); + } + + private static String buildUrl(String host, String path, Map querys) throws UnsupportedEncodingException { + StringBuilder sbUrl = new StringBuilder(); + sbUrl.append(host); + if (!StringUtils.isBlank(path)) { + sbUrl.append(path); + } + if (null != querys) { + StringBuilder sbQuery = new StringBuilder(); + for (Map.Entry query : querys.entrySet()) { + if (0 < sbQuery.length()) { + sbQuery.append("&"); + } + if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) { + sbQuery.append(query.getValue()); + } + if (!StringUtils.isBlank(query.getKey())) { + sbQuery.append(query.getKey()); + if (!StringUtils.isBlank(query.getValue())) { + sbQuery.append("="); + sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8")); + } + } + } + if (0 < sbQuery.length()) { + sbUrl.append("?").append(sbQuery); + } + } + + return sbUrl.toString(); + } + + private static HttpClient wrapClient(String host) { + HttpClient httpClient = new DefaultHttpClient(); + if (host.startsWith("https://")) { + sslClient(httpClient); + } + + return httpClient; + } + + private static void sslClient(HttpClient httpClient) { + try { + SSLContext ctx = SSLContext.getInstance("TLS"); + X509TrustManager tm = new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] xcs, String str) { + + } + public void checkServerTrusted(X509Certificate[] xcs, String str) { + + } + }; + ctx.init(null, new TrustManager[] { tm }, null); + SSLSocketFactory ssf = new SSLSocketFactory(ctx); + ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + ClientConnectionManager ccm = httpClient.getConnectionManager(); + SchemeRegistry registry = ccm.getSchemeRegistry(); + registry.register(new Scheme("https", 443, ssf)); + } catch (KeyManagementException ex) { + throw new RuntimeException(ex); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/HttpsUtils.java b/service/src/main/java/com/hfkj/common/utils/HttpsUtils.java new file mode 100644 index 0000000..41315bf --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/HttpsUtils.java @@ -0,0 +1,836 @@ +package com.hfkj.common.utils; + + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLContexts; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HttpsUtils { + + private static final Logger log = LoggerFactory.getLogger(HttpsUtils.class); + + private static PoolingHttpClientConnectionManager connMgr; + private static RequestConfig requestConfig; + private static final int MAX_TIMEOUT = 7000; + + static { + // 设置连接池 + connMgr = new PoolingHttpClientConnectionManager(); + // 设置连接池大小 + connMgr.setMaxTotal(100); + connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal()); + // Validate connections after 1 sec of inactivity + connMgr.setValidateAfterInactivity(1000); + RequestConfig.Builder configBuilder = RequestConfig.custom(); + // 设置连接超时 + configBuilder.setConnectTimeout(MAX_TIMEOUT); + // 设置读取超时 + configBuilder.setSocketTimeout(MAX_TIMEOUT); + // 设置从连接池获取连接实例的超时 + configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT); + + requestConfig = configBuilder.build(); + } + + /** + * 发送 GET 请求(HTTP),不带输入数据 + * + * @param url + * @return + */ + public static JSONObject doGet(String url) { + return doGet(url, new HashMap()); + } + + /** + * 发送 GET 请求(HTTP),K-V形式 + * + * @param url + * @param params + * @return + */ + public static JSONObject doGet(String url, Map params) { + String apiUrl = url; + StringBuffer param = new StringBuffer(); + int i = 0; + for (String key : params.keySet()) { + if (i == 0) + param.append("?"); + else + param.append("&"); + param.append(key).append("=").append(params.get(key)); + i++; + } + apiUrl += param; + String result = null; + HttpClient httpClient = null; + try { + + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + + HttpGet httpGet = new HttpGet(apiUrl); + HttpResponse response = httpClient.execute(httpGet); + HttpEntity entity = response.getEntity(); + if (entity != null) { + InputStream instream = entity.getContent(); + result = IOUtils.toString(instream, "UTF-8"); + } + return JSON.parseObject(result); + } catch (Exception e) { + log.error(e.getMessage(),e); + } + return null; + } + + public static JSONObject doGet(String url, Map params , String o) { + String apiUrl = url; + StringBuffer param = new StringBuffer(); + int i = 0; + for (String key : params.keySet()) { + if (i == 0) + param.append("?"); + else + param.append("&"); + param.append(key).append("=").append(params.get(key)); + i++; + } + apiUrl += param; + String result = null; + HttpClient httpClient = null; + try { + + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + + HttpGet httpGet = new HttpGet(apiUrl); + HttpResponse response = httpClient.execute(httpGet); + HttpEntity entity = response.getEntity(); + if (entity != null) { + InputStream instream = entity.getContent(); + result = IOUtils.toString(instream, "UTF-8"); + } + return JSON.parseObject(result); + } catch (Exception e) { + log.error(e.getMessage(),e); + } + return null; + } + + public static JSONObject doGet(String url, Map params , Map headers) { + String apiUrl = url; + StringBuffer param = new StringBuffer(); + int i = 0; + for (String key : params.keySet()) { + if (i == 0) + param.append("?"); + else + param.append("&"); + param.append(key).append("=").append(params.get(key)); + i++; + } + apiUrl += param; + String result = null; + HttpClient httpClient = null; + try { + + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + + HttpGet httpGet = new HttpGet(apiUrl); + for (Map.Entry e : headers.entrySet()) { + httpGet.addHeader(e.getKey(), e.getValue()); + } + HttpResponse response = httpClient.execute(httpGet); + HttpEntity entity = response.getEntity(); + if (entity != null) { + InputStream instream = entity.getContent(); + result = IOUtils.toString(instream, "UTF-8"); + } + return JSON.parseObject(result); + } catch (Exception e) { + log.error(e.getMessage(),e); + } + return null; + } + + public static JSONObject doWxGet(String url, Map params) { + String apiUrl = url; + StringBuffer param = new StringBuffer(); + int i = 0; + for (String key : params.keySet()) { + if (i == 0) + param.append("?"); + else + param.append("&"); + param.append(key).append("=").append(params.get(key)); + i++; + } + apiUrl += param + "#wechat_redirect"; + String result = null; + HttpClient httpClient = null; + try { + + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + + HttpGet httpGet = new HttpGet(apiUrl); + HttpResponse response = httpClient.execute(httpGet); + HttpEntity entity = response.getEntity(); + if (entity != null) { + InputStream instream = entity.getContent(); + result = IOUtils.toString(instream, "UTF-8"); + } + return JSON.parseObject(result); + } catch (Exception e) { + log.error(e.getMessage(),e); + } + return null; + } + + /** + * 发送 POST 请求(HTTP),不带输入数据 + * + * @param apiUrl + * @return + */ + public static JSONObject doPost(String apiUrl) { + return doPost(apiUrl, new HashMap()); + } + + /** + * 发送 POST 请求,K-V形式 + * + * @param apiUrl + * API接口URL + * @param params + * 参数map + * @return + */ + public static JSONObject doPost(String apiUrl, Map params) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + List pairList = new ArrayList<>(params.size()); + for (Map.Entry entry : params.entrySet()) { + NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString()); + pairList.add(pair); + } + httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8"))); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + + /** + * 发送 POST 请求,K-V形式 + * + * @param apiUrl + * API接口URL + * @param params + * 参数map + * @return + */ + public static JSONObject doPostSendSms(String apiUrl, Map params) { + CloseableHttpClient httpClient = null; + + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + List pairList = new ArrayList<>(params.size()); + for (Map.Entry entry : params.entrySet()) { + NameValuePair pair = new BasicNameValuePair(entry.getKey(), entry.getValue().toString()); + pairList.add(pair); + } + httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8"))); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + /** + * 发送 POST 请求,JSON形式 + * + * @param apiUrl + * @param json + * json对象 + * @return + */ + public static JSONObject doPost(String apiUrl, JSONObject json) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + StringEntity stringEntity = new StringEntity(json.toString(), "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doHuiLianTongPost(String apiUrl) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + StringEntity stringEntity = new StringEntity("", "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/x-www-form-urlencoded"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doWxPost(String apiUrl, Map body, Map header) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue().toString()); + } + StringEntity stringEntity = new StringEntity(JSON.toJSONString(body), "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doPost(String apiUrl, Map body, Map header) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue().toString()); + } + StringEntity stringEntity = new StringEntity(JSON.toJSONString(body), "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doPostForm(String apiUrl, String body, Map header) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue().toString()); + } + StringEntity stringEntity = new StringEntity(body,"UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/x-www-form-urlencoded"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doSmsPost(String apiUrl, Map body, Map header) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue().toString()); + } + StringEntity stringEntity = new StringEntity(body.get("from").toString());// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/x-www-form-urlencoded"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doWxH5PayPost(String apiUrl, Map body, Map header) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + for (Map.Entry entry : header.entrySet()) { + httpPost.setHeader(entry.getKey(), entry.getValue().toString()); + } + StringEntity stringEntity = new StringEntity(body.get("from").toString());// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/x-www-form-urlencoded"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + /** + * 发送 POST 请求,JSON形式 + * + * @param apiUrl + * @return + */ + public static JSONObject doPost(String apiUrl, String str) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + StringEntity stringEntity = new StringEntity(str, "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static JSONObject doPost(String apiUrl, String str, String token, String sign, Long ts) { + CloseableHttpClient httpClient = null; + if (apiUrl.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(apiUrl); + httpPost.setConfig(requestConfig); + httpPost.setHeader("token", token); + httpPost.setHeader("sign", sign); + httpPost.setHeader("ts", ts.toString()); + StringEntity stringEntity = new StringEntity(str, "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + stringEntity.setContentType("application/json"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + /** + * @Author Sum1Dream + * @Description // 不带证书请求xml + * @Date 11:42 2021/6/8 + * @Param [url, str] + * @return com.alibaba.fastjson.JSONObject + **/ + public static JSONObject postData(String url, String str) { + CloseableHttpClient httpClient = null; + if (url.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(createSSLConnSocketFactory()) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + + StringEntity stringEntity = new StringEntity(str, "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + /** + * @Author Sum1Dream + * @Description // 带证书请求 xml + * @Date 11:45 2021/6/8 + * @Param [url, mchId, str] + * @return com.alibaba.fastjson.JSONObject + **/ + public static JSONObject postData(String url, String mchId , String str) { + CloseableHttpClient httpClient = null; + if (url.startsWith("https")) { + httpClient = HttpClients.custom().setSSLSocketFactory(readCertificate(mchId)) + .setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build(); + } else { + httpClient = HttpClients.createDefault(); + } + String httpStr = null; + CloseableHttpResponse response = null; + + try { + HttpPost httpPost = new HttpPost(url); + httpPost.setConfig(requestConfig); + + StringEntity stringEntity = new StringEntity(str, "UTF-8");// 解决中文乱码问题 + stringEntity.setContentEncoding("UTF-8"); + httpPost.addHeader("Content-Type", "text/xml"); + httpPost.setEntity(stringEntity); + response = httpClient.execute(httpPost); + HttpEntity entity = response.getEntity(); + httpStr = EntityUtils.toString(entity, "UTF-8"); + return JSON.parseObject(httpStr); + } catch (Exception e) { + log.error(e.getMessage(),e); + } finally { + if (response != null) { + try { + EntityUtils.consume(response.getEntity()); + } catch (IOException e) { + log.error(e.getMessage(),e); + } + } + } + return null; + } + + public static SSLConnectionSocketFactory readCertificate(String mchId) { + try { + KeyStore keyStore = KeyStore.getInstance("PKCS12"); + FileInputStream stream = new FileInputStream( "F:/mine/hai-server/hai-service/src/main/java/privatekey/apiclient_cert.p12"); + keyStore.load(stream , mchId.toCharArray()); + stream.close(); + SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build(); + return new SSLConnectionSocketFactory( + sslcontext, + new String[]{"TLSv1"}, + null, + SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); + } catch (Exception e) { + System.out.println("证书双向认证出现异常" + e); + } + return null; + } + + /** + * 创建SSL安全连接 + * + * @return + */ + private static SSLConnectionSocketFactory createSSLConnSocketFactory() { + SSLConnectionSocketFactory sslsf = null; + try { + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { + + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { + return true; + } + }).build(); + sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() { + + @Override + public boolean verify(String arg0, SSLSession arg1) { + return true; + } + }); + } catch (GeneralSecurityException e) { + log.error(e.getMessage(),e); + } + return sslsf; + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/IDGenerator.java b/service/src/main/java/com/hfkj/common/utils/IDGenerator.java new file mode 100644 index 0000000..c5b185b --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/IDGenerator.java @@ -0,0 +1,63 @@ +package com.hfkj.common.utils; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public class IDGenerator { + + private static final long ONE_STEP = 10; + private static final Lock LOCK = new ReentrantLock(); + private static long lastTime = System.nanoTime(); + private static short lastCount = 0; + private static int count = 0; + /** + * 可传入指定长度的值 + * @param length + * @return + */ + @SuppressWarnings("finally") + public static String nextId(int... length) + { + LOCK.lock(); + try { + if (lastCount == ONE_STEP) { + boolean done = false; + while (!done) { + long now = System.nanoTime(); + if (now == lastTime) { + try { + Thread.currentThread(); + Thread.sleep(1); + } catch (InterruptedException e) { + } + continue; + } else { + lastTime = now; + lastCount = 0; + done = true; + } + } + } + count = lastCount++; + } + finally + { + LOCK.unlock(); + String idStr = lastTime+""+String.format("%02d",count); + if(length.length > 0 && length[0] > 0){ + idStr = idStr.substring(idStr.length()-length[0]<0?0:idStr.length()-length[0], idStr.length()); + } + return idStr; + } + } + public static void main(String[] args) + { +// for(int i=0;i<100;i++) +// { +// System.out.println(nextId()); +// } +// nextId(20); + System.out.println(System.currentTimeMillis()); + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/IdCardUtil.java b/service/src/main/java/com/hfkj/common/utils/IdCardUtil.java new file mode 100644 index 0000000..f5b128e --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/IdCardUtil.java @@ -0,0 +1,99 @@ +package com.hfkj.common.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @ClassName IdCardUtil + * @Description + * @Author 杜江 + * @Date 2020/8/11 11:38 + * @Version 1.0 + */ +public class IdCardUtil { + public static boolean isIdCard(String card){ + card = replaceBlank(card); + if(card == null || "".equals(card)){ + return false; + } + //定义 叛别用户 身份证号的正则表达式 (15位 或 18位,最后一位可以为字母) + String requal = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|(10|20|30|31))\\d{3}[0-9Xx]$)|" + +"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)"; + + // 假设18位 身份证号码: + // ^ 表示开头 + // [1-9] 第一位1-9 中的一个 4 注意!! 前六位代表地址,此处是 拆分 讲解 对正则 的注释 + // \\d{5} 五位数字 10001(前六位省市县地区) + // (18|19|20) 19 (现阶段可能取值范围18xx-20xx年) + // \\d{2} 91 (年份) + // ((0[1-9])|(10|11|12)) 01(月份) + // (([0-2][1-9])|10|20|30|31) 01(日期) 也可写成(([0-2][1-9])|(10|20|30|31)) + // \\d{3} 三位数字 123(第十七位奇数表示男,偶数表示女) + // [0-9Xx] 0123456789Xx 其中的一个 X(第十八位为校验值) + // $结尾 + + // 假设15位身份证号码: 410001910101123 + // ^ 开头 + // [1-9] 第一位1-9中的一个 4 + // \\d{5} 五位数字 10001(前六位省市县地区) + // \\d{2} 91(年份) 表示 91年 + // ((0[1-9])|(10|11|12)) 01(月份) + // (([0-2][1-9])|10|20|30|31) 01(日期) + // \\d{3} 123(第十五位奇数代表男,偶数代表女),15位身份证不含X + // $结尾 + boolean matches = card.matches(requal); + + //判断 第 18位 校验值 ,校验算法涉及两次mod 11的过程 + // 二代身份证中的 号码第十八位的计算方法为: + if(matches){ + if (card.length() == 18){ + try { + char[] charArray = card.toCharArray(); + //1,将前面的身份证号码17位数分别乘以不同的系数,系数为此处的 加权因子 + //前十七位加权因子 + int[] idCardWi = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; + int sum = 0; + // 2,将这17位数字 和系数相乘 的结果相加 + for (int i = 0;i < idCardWi.length;i++){ + int current = Integer.parseInt(String.valueOf(charArray[i])); + // 相乘对应的 加权因子系数 + int count = current * idCardWi[i]; + // 结果相加 + sum += count; + } + char idCardLast = charArray[17]; + // 3,结果和 除以11,查看余数 + int idCardMod = sum % 11; + // 4,这是除以 11后,可能产生的 11位余数对应的验证码(--对应下标),其中 X 代表罗马数字 10 + String[] idCardY = {"1","0","X","9","8","7","6","5","4","3","2"}; + if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())){ + return true; + }else { + System.out.println("身份证最后一位:"+String.valueOf(idCardLast).toUpperCase()+ + "错误,正确的应该是:"+idCardY[idCardMod].toUpperCase()); + return false; + } + }catch (Exception e){ + e.printStackTrace(); + System.out.println("异常:"+card); + return false; + } + } + } + return matches; + } + + public static String replaceBlank(String str) { + String dest = ""; + if (str!=null) { + Pattern p = Pattern.compile("\\s*|\t|\r|\n"); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } + + public static void main(String[] args) { + System.out.println(isIdCard("5113221999409035038")); + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/IdentifyUtil.java b/service/src/main/java/com/hfkj/common/utils/IdentifyUtil.java new file mode 100644 index 0000000..8d0af33 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/IdentifyUtil.java @@ -0,0 +1,40 @@ +package com.hfkj.common.utils; + +import java.text.SimpleDateFormat; + +/** + * 生成唯一标识 + * + * @author + * @createDate + */ +public class IdentifyUtil { + public static void main(String[] args) { + //调用生成id方法 + System.out.println(getGuid()); + } + + /** + * 20位的数字id + */ + public static int Guid = 100; + + public static String getGuid() { + IdentifyUtil.Guid += 1; + long now = System.currentTimeMillis(); + //获取4位年份数字 + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy"); + //获取时间戳 + String time = dateFormat.format(now); + String info = now + ""; + //获取三位随机数 + //int ran=(int) ((Math.random()*9+1)*100); + //要是一段时间内的数据连过大会有重复的情况,所以做以下修改 + int ran = 0; + if (IdentifyUtil.Guid > 999) { + IdentifyUtil.Guid = 100; + } + ran = IdentifyUtil.Guid; + return time + info.substring(2, info.length()) + ran; + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/MD5Util.java b/service/src/main/java/com/hfkj/common/utils/MD5Util.java new file mode 100644 index 0000000..2f36b75 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/MD5Util.java @@ -0,0 +1,69 @@ +package com.hfkj.common.utils; + +import javax.xml.bind.annotation.adapters.HexBinaryAdapter; +import java.security.MessageDigest; + +/** + * + * @ClassName: MD5Util + * @Description:TODO(MD5 加密工具) + * @author: 胡锐 + * @date: 2019年5月6日 上午10:13:26 + * + * @Copyright: 2019 www.shinwoten.com Inc. All rights reserved. + */ +public class MD5Util { + + + /** + * + * @Title: encode + * @Description: TODO(MD5 32位加密) + * @author: 胡锐 + * @param: @param data + * @param: @return + * @param: @throws Exception + * @return: String + * @throws + */ + public static String encode(byte[] data) throws Exception { + // 初始化MessageDigest + MessageDigest md = MessageDigest.getInstance("MD5"); + // 执行摘要信息 + byte[] digest = md.digest(data); + // 将摘要信息转换为32位的十六进制字符串 + return new String(new HexBinaryAdapter().marshal(digest)); + } + /* public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException{ + //确定计算方法 + MessageDigest md5=MessageDigest.getInstance("MD5"); + Encoder base64en = Base64.getEncoder(); + //加密后的字符串 + String newstr=base64en.encodeToString(md5.digest(str.getBytes("utf-8"))); + return newstr; + }*/ + + public static String encodeS(byte[] data) throws Exception { + // 初始化MessageDigest + MessageDigest md = MessageDigest.getInstance("MD5"); + // 执行摘要信息 + byte[] digest = md.digest(data); + // 将摘要信息转换为32位的十六进制字符串 + return new HexBinaryAdapter().marshal(digest); + } + /* public static String EncoderByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException{ + //确定计算方法 + MessageDigest md5=MessageDigest.getInstance("MD5"); + Encoder base64en = Base64.getEncoder(); + //加密后的字符串 + String newstr=base64en.encodeToString(md5.digest(str.getBytes("utf-8"))); + return newstr; + }*/ + + + public static void main(String[] args) throws Exception { + String str = "123456"; + System.out.println(MD5Util.encode(str.getBytes("UTF-8"))); + //String ee = "29AD0E3FD3DB681FB9F8091C756313F7"; + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/MathUtils.java b/service/src/main/java/com/hfkj/common/utils/MathUtils.java new file mode 100644 index 0000000..fac8059 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/MathUtils.java @@ -0,0 +1,25 @@ +package com.hfkj.common.utils; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class MathUtils { + + public static BigDecimal objectConvertBigDecimal(Object value) { + BigDecimal ret = null; + if (value != null) { + if (value instanceof BigDecimal) { + ret = (BigDecimal) value; + } else if (value instanceof String) { + ret = new BigDecimal((String) value); + } else if (value instanceof BigInteger) { + ret = new BigDecimal((BigInteger) value); + } else if (value instanceof Number) { + ret = new BigDecimal(((Number) value).doubleValue()); + } else { + throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + " into a BigDecimal."); + } + } + return ret; + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/MemberValidateUtil.java b/service/src/main/java/com/hfkj/common/utils/MemberValidateUtil.java new file mode 100644 index 0000000..09c3303 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/MemberValidateUtil.java @@ -0,0 +1,112 @@ +package com.hfkj.common.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @ClassName: FormatValidateUtil + * @Description:TODO(格式校验) + * @author: 胡锐 + * @date: 2018年8月2日 上午10:12:43 + * + * @Copyright: 2018 www.shinwoten.com Inc. All rights reserved. + */ +public class MemberValidateUtil { + + /** + * + * @Title: validateName + * @Description: TODO(用户名验证) + * @author: 胡锐 + * @param: @param name + * @param: @return + * @return: boolean + * @throws + */ + public static boolean validateName(String name) { + if(name.length() < 2 || name.length() > 20) { + return false; + } + + return true; + } + + /** + * + * @Title: validatePhone + * @Description: TODO(手机号格式校验) + * @author: 胡锐 + * @param: @param phone + * @param: @return + * @return: boolean + * @throws + */ + public static boolean validatePhone(String phone) { + phone = replaceBlank(phone); + String regex = "^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$"; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(phone); + boolean isMatch = m.matches(); + return isMatch; + } + + + /** + * + * @Title: validatePass + * @Description: TODO(密码格式校验) + * @author: 胡锐 + * @param: @param password + * @param: @return + * @return: boolean + * @throws + */ + public static boolean validatePass(String password) { + String regex = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$"; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(password); + boolean isMatch = m.matches(); + return isMatch; + + } + + /** + * + * @Title: validatePass + * @Description: TODO(校验身份证) + * @author: 胡锐 + * @param: @param password + * @param: @return + * @return: boolean + * @throws + */ + public static boolean validateIdCard(String idCard) { + String regex = "(^\\\\d{18}$)|(^\\\\d{15}$)"; + return Pattern.matches(regex,idCard); + } + + public static boolean isNumber(String str) { + Pattern pattern = Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,2})?$"); // 判断小数点后2位的数字的正则表达式 + Matcher match = pattern.matcher(str); + if (match.matches() == false) { + return false; + } else { + return true; + } + } + + public static String replaceBlank(String str) { + String dest = ""; + if (str!=null) { + Pattern p = Pattern.compile("\\s*|\t|\r|\n"); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } + + public static void main(String[] args) throws Exception { + System.out.println(validatePhone("15983795288")); + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/PageUtil.java b/service/src/main/java/com/hfkj/common/utils/PageUtil.java new file mode 100644 index 0000000..248ddc7 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/PageUtil.java @@ -0,0 +1,98 @@ +package com.hfkj.common.utils; + +import com.github.pagehelper.PageInfo; + +import java.util.List; + +/** + * 分页工具 + */ +public class PageUtil { + + /** + * 初始化 + * @param currentPage + * @param total + * @param pageSize + * @param pageInfo + * @param + * @return + */ + public static PageInfo initPageInfoObj(int currentPage, int total, int pageSize, PageInfo pageInfo) { + List list = pageInfo.getList(); + int fromIndex = 0; + int toIndex = 0; + if (total / pageSize == 0 && total % pageSize > 0) { + fromIndex = 0; + toIndex = total; + } else { + if (total / pageSize >= 1 && total % pageSize >= 0) { + fromIndex = pageSize * (currentPage - 1); + if (pageSize * currentPage >= total) { + toIndex = total; + } else { + toIndex = pageSize * currentPage; + } + } + } + + try { + list = list.subList(fromIndex, toIndex); + } catch (IndexOutOfBoundsException e) { + fromIndex = 0; + toIndex= pageSize; + list = list.subList(fromIndex, toIndex); + }catch(IllegalArgumentException e) { + fromIndex = total-pageSize; + toIndex =total; + list = list.subList(fromIndex, toIndex); + } + pageInfo.setList(list); + pageInfo.setNextPage(currentPage < ((total + pageSize - 1) / pageSize) ? currentPage + 1 : currentPage); + pageInfo.setTotal(total); + pageInfo.setPageNum(currentPage); + pageInfo.setPages((total + pageSize - 1) / pageSize); + pageInfo.setNavigateLastPage((total + pageSize - 1) / pageSize); + pageInfo.setPrePage(currentPage > 1 ? currentPage - 1 : currentPage); + pageInfo.setIsFirstPage(currentPage == 1 ? true : false); + pageInfo.setIsLastPage(currentPage == (total + pageSize - 1) / pageSize ? true : false); + pageInfo.setHasPreviousPage(currentPage == 1 ? false : true); + pageInfo.setHasNextPage(currentPage == (total + pageSize - 1) / pageSize ? false : true); + return calcNavigatepageNums(pageInfo); + } + + private static PageInfo calcNavigatepageNums(PageInfo pageInfo) { + // 当总页数小于或等于导航页码数时 + if (pageInfo.getPages() <= pageInfo.getNavigatePages()) { + pageInfo.setNavigatepageNums(new int[pageInfo.getPages()]); + for (int i = 0; i < pageInfo.getPages(); i++) { + pageInfo.getNavigatepageNums()[i] = i + 1; + } + } else { // 当总页数大于导航页码数时 + pageInfo.setNavigatepageNums(new int[pageInfo.getNavigatePages()]); + int startNum = pageInfo.getPageNum() - pageInfo.getNavigatePages() / 2; + int endNum = pageInfo.getPageNum() + pageInfo.getNavigatePages() / 2; + + if (startNum < 1) { + startNum = 1; + // (最前navigatePages页 + for (int i = 0; i < pageInfo.getNavigatePages(); i++) { + pageInfo.getNavigatepageNums()[i] = startNum++; + } + } else if (endNum > pageInfo.getPages()) { + endNum = pageInfo.getPages(); + // 最后navigatePages页 + for (int i = pageInfo.getNavigatePages() - 1; i >= 0; i--) { + pageInfo.getNavigatepageNums()[i] = endNum--; + } + } else { + // 所有中间页 + for (int i = 0; i < pageInfo.getNavigatePages(); i++) { + pageInfo.getNavigatepageNums()[i] = startNum++; + } + } + } + return pageInfo; + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/RedisUtil.java b/service/src/main/java/com/hfkj/common/utils/RedisUtil.java new file mode 100644 index 0000000..cfdc008 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/RedisUtil.java @@ -0,0 +1,533 @@ +package com.hfkj.common.utils; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +@Component +public class RedisUtil { + + @Autowired + private RedisTemplate redisTemplate; + + public RedisUtil(RedisTemplate redisTemplate) { + this.redisTemplate = redisTemplate; + } + + /** + * 指定缓存失效时间 + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key,long time){ + try { + if(time>0){ + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key){ + return redisTemplate.getExpire(key,TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key){ + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String ... key){ + if(key!=null&&key.length>0){ + if(key.length==1){ + redisTemplate.delete(key[0]); + }else{ + redisTemplate.delete(CollectionUtils.arrayToList(key)); + } + } + } + + //============================String============================= + /** + * 普通缓存获取 + * @param key 键 + * @return 值 + */ + public Object get(String key){ + return key==null?null:redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key,Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key,Object value,long time){ + try { + if(time>0){ + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + }else{ + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * @param key 键 + * @param delta 要增加几(大于0) + * @return + */ + public long incr(String key, long delta){ + if(delta<0){ + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public long decr(String key, long delta){ + if(delta<0){ + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + //================================Map================================= + /** + * HashGet + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key,String item){ + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key){ + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map){ + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time){ + try { + redisTemplate.opsForHash().putAll(key, map); + if(time>0){ + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key,String item,Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key,String item,Object value,long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if(time>0){ + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item){ + redisTemplate.opsForHash().delete(key,item); + } + + /** + * 判断hash表中是否有该项的值 + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item){ + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item,double by){ + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item,double by){ + return redisTemplate.opsForHash().increment(key, item,-by); + } + + //============================set============================= + /** + * 根据key获取Set中的所有值 + * @param key 键 + * @return + */ + public Set sGet(String key){ + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key,Object value){ + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object...values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key,long time,Object...values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if(time>0) { + expire(key, time); + } + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * @param key 键 + * @return + */ + public long sGetSetSize(String key){ + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object ...values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + //===============================list================================= + + /** + * 获取list缓存的内容 + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end){ + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * @param key 键 + * @return + */ + public long lGetListSize(String key){ + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * @param key 键 + * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key,long index){ + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index,Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key,long count,Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/RequestUtils.java b/service/src/main/java/com/hfkj/common/utils/RequestUtils.java new file mode 100644 index 0000000..2454d4e --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/RequestUtils.java @@ -0,0 +1,38 @@ +package com.hfkj.common.utils; +import javax.servlet.http.HttpServletRequest; + +public class RequestUtils { + + public static String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/ResponseMsgUtil.java b/service/src/main/java/com/hfkj/common/utils/ResponseMsgUtil.java new file mode 100644 index 0000000..6caa712 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/ResponseMsgUtil.java @@ -0,0 +1,70 @@ +package com.hfkj.common.utils; + + + +import com.hfkj.common.exception.BaseException; +import com.hfkj.common.exception.BizException; + +import com.hfkj.model.ResponseData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ResponseMsgUtil { + + static Logger log = LoggerFactory.getLogger(ResponseMsgUtil.class); + + /** + * + * @Title: success + * @Description: 请求成功后,组装返回给前台的对象 + * @author: 机器猫 + * @param: @param data + * @param: @return + * @return: ResponseData + * @throws + */ + public static ResponseData success(Object data){ + ResponseData res = new ResponseData(); + res.setReturn_code("000000"); + res.setReturn_data(data); + return res; + } + + /** + * 根据消息码等生成接口返回对象 + * + * @param code 结果返回码 + * @param msg 结果返回消息 + * @param data 数据对象 + * @param + * @return + */ + public static ResponseData builderResponse(String code, String msg, Object data) { + ResponseData res = new ResponseData(); + res.setReturn_code(code); + res.setReturn_msg(msg); + res.setReturn_data(data); + return res; + } + + /** + * 请求异常返回结果 + * + * @param + * @return + */ + public static ResponseData exception(Exception e) { + + log.error("---controller error---",e); + + if(e instanceof BizException){//业务异常处理 + return builderResponse(((BizException)e).getErrorCode(), ((BizException)e).getErrorMsg(), null); + } else if(e instanceof BaseException){//系统异常处理 + return builderResponse(((BaseException)e).getErrorCode(),"服务异常",null); + } else{//未知异常 + return builderResponse("999999", "未知异常", null); + } + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/SpringContextUtil.java b/service/src/main/java/com/hfkj/common/utils/SpringContextUtil.java new file mode 100644 index 0000000..693bf31 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/SpringContextUtil.java @@ -0,0 +1,28 @@ +package com.hfkj.common.utils; + + +import org.springframework.context.ApplicationContext; + +public class SpringContextUtil { + private static ApplicationContext applicationContext; + + //获取上下文 + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + //设置上下文 + public static void setApplicationContext(ApplicationContext applicationContext) { + SpringContextUtil.applicationContext = applicationContext; + } + + //通过名字获取上下文中的bean + public static Object getBean(String name){ + return applicationContext.getBean(name); + } + + //通过类型获取上下文中的bean + public static Object getBean(Class requiredType){ + return applicationContext.getBean(requiredType); + } +} diff --git a/service/src/main/java/com/hfkj/common/utils/UnionUtils.java b/service/src/main/java/com/hfkj/common/utils/UnionUtils.java new file mode 100644 index 0000000..bd648a2 --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/UnionUtils.java @@ -0,0 +1,487 @@ +package com.hfkj.common.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.WebResource.Builder; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.client.urlconnection.HTTPSProperties; +import org.apache.commons.codec.binary.Base64; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.net.ssl.*; +import javax.ws.rs.core.MediaType; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +public class UnionUtils { + private static Client c = null; + private static Client secureClient =null; + private static Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + public static String DATE_FORMAT = "yyyy-MM-dd"; + /** + * 初始化设置 + */ + static{ + initalizationJersyClient(); + initalizationSecureJersyClient(); + } + /** + * 设置调用参数 + */ + private static void initalizationJersyClient(){ + try { + c = Client.create(); + c.setFollowRedirects(true); + c.setConnectTimeout(10000); + c.setReadTimeout(10000); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void initalizationSecureJersyClient(){ + try { + SSLContext context = SSLContext.getInstance("SSL"); + context.init(null, new TrustManager[] { new X509TrustManager() { + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted( + java.security.cert.X509Certificate[] chain, String authType) + throws CertificateException {} + public void checkServerTrusted( + java.security.cert.X509Certificate[] chain, + String authType) throws CertificateException {} + } }, new SecureRandom()); + HostnameVerifier hv = new HostnameVerifier(){ + public boolean verify(String urlHostName, SSLSession session){ + return true; + } + }; + + HTTPSProperties prop = new HTTPSProperties(hv, context); + DefaultClientConfig dcc = new DefaultClientConfig(); + dcc.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, prop); + secureClient = Client.create(dcc); + secureClient.setFollowRedirects(true); + secureClient.setConnectTimeout(10000); + secureClient.setReadTimeout(10000); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 调用接口 + */ + public static String sendPOSTRequest(String url, Object map, String contentTpye){ + if(null==c){ + initalizationJersyClient(); + } + Client client = null; + if(url.indexOf("https://") == 0){ + if(null==secureClient){ + initalizationJersyClient(); + } + client = secureClient; + }else{ + if(null==c){ + initalizationJersyClient(); + } + client = c; + } + WebResource resource = client.resource(url); + String resultStr = null; + try { + Builder builder = resource.accept("*/*"); + ClientResponse res = builder.type(contentTpye).entity(map).post(ClientResponse.class); + if(res.getStatus() != 200){ + throw new Exception("url:"+url+",response code:" + res.getStatus()); + } + resultStr = res.getEntity(String.class); + return resultStr; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 参数 转为json格式 + * @param url 调用地址 + * @param map 设置的参数 + * @return + */ + public static String sendPostGson(String url, Map map){ + String ps = gson.toJson(map); + + System.out.println("生成加密后的报文:"+ps); + return sendPOSTRequest(url, ps, MediaType.APPLICATION_JSON); + } + + + /** + * 使用公钥加密对称密钥 + * @param publicKey 公钥 + * @param symmetricKeyByte 对称密钥字节 + * @return 加密后的对称密钥字节 + * @throws Exception + */ + public static byte[] encrypt(String publicKey, byte[] symmetricKeyByte) throws Exception { + byte[] encodedKey = Base64.decodeBase64(publicKey); + KeySpec keySpec = new X509EncodedKeySpec(encodedKey); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey pk = keyFactory.generatePublic(keySpec); + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, pk); + byte[] result = cipher.doFinal(symmetricKeyByte); + return result; + } + + /** + * 签名加密后的数据装载进map + * @param key 对称秘钥 + * @param params 待加密的字符串 + * @param encryptKeys 加密字段 + * @throws Exception + */ + public static void encryptedParamMap(String key, Map params, String ... encryptKeys) throws Exception{ + if(encryptKeys != null && encryptKeys.length > 0){ + for(String encryptKey : encryptKeys){ + params.put(encryptKey, getEncryptedValue(params.get(encryptKey), key)); + } + } + } + + /** + * 3DES加密 + * @param value 待加密的字符串 + * @param key 加密密钥 + * @return 加密后的字符串 + * @throws Exception + */ + public static String getEncryptedValue(String value, String key) throws Exception { + if (null == value || "".equals(value)) { + return ""; + } + byte[] valueByte = value.getBytes(); + byte[] sl = encrypt3DES(valueByte, hexToBytes(key)); + String result = Base64.encodeBase64String(sl); + // String result = BytesUtil.bytesToHex(sl); + return result; + } + + /** + * 解密 + * @param value 待解密的字符串 + * @param key 解密秘钥 + * @return 解密后字符串 + * @throws Exception + */ + public static String getDecryptedValue(String value, String key) throws Exception { + if (null == value || "".equals(value)) { + return ""; + } + byte[] valueByte = Base64.decodeBase64(value); + byte[] sl = decrypt3DES(valueByte, hexStr2Bytes(key)); + String result = new String(sl); + return result; + } + + /** + * 3DES解密 + * @param input + * @param key + * @return + * @throws Exception + */ + public static byte[] decrypt3DES(byte[] input, byte[] key) throws Exception { + Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding"); + c.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "DESede")); + return c.doFinal(input); + } + + + /** + * bytes字符串转换为Byte值 + * @param src String Byte字符串,每个Byte之间没有分隔符(字符范围:0-9 A-F) + * @return byte[] + */ + public static byte[] hexStr2Bytes(String src){ + /*对输入值进行规范化整理*/ + src = src.trim().replace(" ", "").toUpperCase(Locale.US); + //处理值初始化 + int m=0,n=0; + int iLen=src.length()/2; //计算长度 + byte[] ret = new byte[iLen]; //分配存储空间 + + for (int i = 0; i < iLen; i++){ + m=i*2+1; + n=m+1; + ret[i] = (byte)(Integer.decode("0x"+ src.substring(i*2, m) + src.substring(m,n)) & 0xFF); + } + return ret; + } + + /** + * 3DES加密 + * @param input 待加密的字节 + * @param key 密钥 + * @return 加密后的字节 + * @throws Exception + */ + private static byte[] encrypt3DES(byte[] input, byte[] key) throws Exception { + Cipher c = Cipher.getInstance("DESede/ECB/PKCS5Padding"); + c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "DESede")); + return c.doFinal(input); + } + + /** + * 获取随机字符串 + * @return 随机字符串 + */ + public static String createNonceStr(){ + String sl = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + StringBuilder sb = new StringBuilder(); + for(int i = 0 ; i < 16 ; i ++){ + sb.append(sl.charAt(new Random().nextInt(sl.length()))); + } + return sb.toString(); + } + + /** + * h获取32位随机数字字符串 + * @return + */ + public static String createNonceNumber(){ + String sl = "0123456789"; + StringBuilder sb = new StringBuilder(); + for(int i = 0 ; i < 32 ; i ++){ + sb.append(sl.charAt(new Random().nextInt(sl.length()))); + } + return sb.toString(); + } + /** + * 获取当前日期时间 + * + * @return + */ + public static String getCurrentDateTime(String Dateformat) { + String datestr = null; + SimpleDateFormat df = new SimpleDateFormat(Dateformat); + datestr = df.format(new Date()); + return datestr; + } + + /** + * 在输入日期上增加(+)或减去(-)天数 + * + * @param date 输入日期 + */ + public static Date addDay(Date date, int iday) { + Calendar cd = Calendar.getInstance(); + + cd.setTime(date); + + cd.add(Calendar.DAY_OF_MONTH, iday); + + return cd.getTime(); + } + /** + * 将日期格式日期转换为字符串格式 自定義格式 + * + * @param date + * @param dateformat + * @return + */ + public static String dateToString(Date date, String dateformat) { + String datestr = null; + SimpleDateFormat df = new SimpleDateFormat(dateformat); + datestr = df.format(date); + return datestr; + } + + /** + * 将字符串日期转换为日期格式 + * + * @param datestr + * @return + */ + public static Date stringToDate(String datestr) throws Exception{ + + if (datestr == null || datestr.equals("")) { + return null; + } + Date date = new Date(); + SimpleDateFormat df = new SimpleDateFormat(DATE_FORMAT); + try { + date = df.parse(datestr); + } catch (ParseException e) { + date = stringToDate(datestr, "yyyyMMdd"); + } + return date; + } + + /** + * 将字符串日期转换为日期格式 + * 自定義格式 + * + * @param datestr + * @return + */ + public static Date stringToDate(String datestr, String dateformat) throws Exception{ + Date date = new Date(); + SimpleDateFormat df = new SimpleDateFormat(dateformat); + date = df.parse(datestr); + return date; + } + /** + * 签名 + * @param param 待签名的参数 + * @param signKey 签名密钥 + * @return 签名结果字符串 + * @throws Exception + */ + public static String sign(Map param, String signKey) throws Exception { + String value = sortMap(param); + byte[] keyBytes = Base64.decodeBase64(signKey); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyf = KeyFactory.getInstance("RSA"); + PrivateKey priKey = keyf.generatePrivate(keySpec); + Signature signature = Signature.getInstance("SHA256WithRSA"); + signature.initSign(priKey); + signature.update(value.getBytes()); + byte[] signed = signature.sign(); + String result = Base64.encodeBase64String(signed); + return result; + } + + + + /** + * 排序 + * @param param 待排序的参数 + * @return 排序结果字符串 + */ + public static String sortMap(Map param){ + StringBuilder result = new StringBuilder(); + Collection keySet = param.keySet(); + List list = new ArrayList(keySet); + Collections.sort(list); + for (int i = 0; i < list.size(); ++i) { + String key = list.get(i); + if("symmetricKey".equals(key)){ + continue; + } +// 非空字段需要参与签名 +// if(param.get(key) == null || "".equals(param.get(key).trim())){ +// continue; +// } + result.append(key).append("=").append(param.get(key)).append("&"); + } + return result.substring(0, result.length() - 1); + } + + + public static String sha256(byte[] data) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + return bytesToHex(md.digest(data)); + + } catch (Exception ex) { + + return null; + } + } + + /** + * 将byte数组转换成16进制字符串 + * + * @param bytes + * @return 16进制字符串 + */ + public static String bytesToHex(byte[] bytes) { + String hexArray = "0123456789abcdef"; + StringBuilder sb = new StringBuilder(bytes.length * 2); + for (byte b : bytes) { + int bi = b & 0xff; + sb.append(hexArray.charAt(bi >> 4)); + sb.append(hexArray.charAt(bi & 0xf)); + } + return sb.toString(); + } + + public static byte[] hexToBytes(String hex) { + return hexToBytes(hex.toCharArray()); + } + + public static byte[] hexToBytes(char[] hex) { + int length = hex.length / 2; + byte[] raw = new byte[length]; + for (int i = 0; i < length; i++) { + int high = Character.digit(hex[i * 2], 16); + int low = Character.digit(hex[i * 2 + 1], 16); + int value = (high << 4) | low; + if (value > 127) { + value -= 256; + } + raw[i] = (byte) value; + } + return raw; + } + + public static String createSign(Map params){ + StringBuilder sb = new StringBuilder(); + // 将参数以参数名的字典升序排序 + Map sortParams = new TreeMap(params); + // 遍历排序的字典,并拼接"key=value"格式 + for (Map.Entry entry : sortParams.entrySet()) { + String key = entry.getKey(); + String value = entry.getValue().trim(); + if (null != value && !"".equals(value)) + sb.append("&").append(key).append("=").append(value); + } + String stringA = sb.toString().replaceFirst("&",""); + String stringSignTemp = stringA ; + String signValue = sha256(stringSignTemp.getBytes()); + return signValue; + } + + + + + /** + * 签名 + * @param param 待签名的参数 + * @param sign 签名结果字符串 + * @return 签名结果 + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + * @throws InvalidKeyException + * @throws SignatureException + */ + public static boolean verify(Map param, String sign,String rescissionPublicKey) throws Exception { + String value = sortMap(param); + byte[] keyBytes = Base64.decodeBase64(rescissionPublicKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + KeyFactory keyf = KeyFactory.getInstance("RSA"); + PublicKey pubkey = keyf.generatePublic(keySpec); + Signature signature = Signature.getInstance("SHA256WithRSA"); + signature.initVerify(pubkey); + signature.update(value.getBytes()); + boolean result = signature.verify(Base64.decodeBase64(sign.getBytes())); + return result; + } + +} diff --git a/service/src/main/java/com/hfkj/common/utils/WxUtils.java b/service/src/main/java/com/hfkj/common/utils/WxUtils.java new file mode 100644 index 0000000..0dbb81d --- /dev/null +++ b/service/src/main/java/com/hfkj/common/utils/WxUtils.java @@ -0,0 +1,373 @@ +package com.hfkj.common.utils; + +import com.google.common.collect.Maps; +import com.hfkj.common.pay.util.sdk.WXPayConstants; +import com.hfkj.common.pay.util.sdk.WXPayXmlUtil; +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.io.naming.NoNameCoder; +import com.thoughtworks.xstream.io.xml.XppDriver; +import net.sf.cglib.beans.BeanMap; +import org.apache.commons.lang3.StringUtils; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.StringWriter; +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.*; + +public class WxUtils { + + private static final Random RANDOM = new SecureRandom(); + + private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + + /** + * 生成签名 + * + * @param signMaps + * @return + * @throws Exception + */ + public static String generateSign(SortedMap signMaps, String mchKey) { + StringBuffer sb = new StringBuffer(); + + // 字典序 + for (Map.Entry signMap : signMaps.entrySet()) { + String key = (String) signMap.getKey(); + String value = (String) signMap.getValue(); + + // 为空不参与签名、参数名区分大小写 + if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) { + sb.append(key).append("=").append(value).append("&"); + } + } + + // 拼接key + sb.append("key=").append(mchKey); + // MD5加密 + String sign = MD5Encode(sb.toString(), "UTF-8").toUpperCase(); + return sign; + } + + public static String generateSignSHA256(SortedMap signMaps,String mchKey)throws Exception{ + StringBuffer sb = new StringBuffer(); + + // 字典序 + for (Map.Entry signMap : signMaps.entrySet()) { + String key = (String) signMap.getKey(); + String value = (String) signMap.getValue(); + + // 为空不参与签名、参数名区分大小写 + if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) { + sb.append(key).append("=").append(value).append("&"); + } + } + + // 拼接key + sb.append("key=").append(mchKey); + // HMACSHA256加密 + String sign = HMACSHA256(sb.toString(), mchKey).toUpperCase(); + return sign; + } + + private static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) + resultSb.append(byteToHexString(b[i])); + + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n += 256; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)) + resultString = byteArrayToHexString(md.digest(resultString + .getBytes())); + else + resultString = byteArrayToHexString(md.digest(resultString + .getBytes(charsetname))); + } catch (Exception exception) { + } + return resultString; + } + + private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; + + + + private static HashMap sortAsc(Map map) { + HashMap tempMap = new LinkedHashMap(); + List> infoIds = new ArrayList>(map.entrySet()); + //排序 + infoIds.sort(new Comparator>() { + @Override + public int compare(Map.Entry o1, Map.Entry o2) { + return o1.getKey().compareTo(o2.getKey()); + } + }); + + for (int i = 0; i < infoIds.size(); i++) { + Map.Entry item = infoIds.get(i); + tempMap.put(item.getKey(), item.getValue()); + } + return tempMap; + } + + + + /** + * 生成 HMACSHA256 + * @param data 待处理数据 + * @param key 密钥 + * @return 加密结果 + * @throws Exception + */ + public static String HMACSHA256(String data, String key) throws Exception { + Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); + SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256"); + sha256_HMAC.init(secret_key); + byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + return sb.toString().toUpperCase(); + } + + /** + * 获取随机字符串 Nonce Str + * + * @return String 随机字符串 + */ + public static String makeNonStr() { + char[] nonceChars = new char[32]; + for (int index = 0; index < nonceChars.length; ++index) { + nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length())); + } + return new String(nonceChars); + } + + /** + * 拼接签名数据 + * + */ + public static String makeSign(BeanMap beanMap, String mchKey, String signType)throws Exception { + SortedMap signMaps = Maps.newTreeMap(); + + for (Object key : beanMap.keySet()) { + Object value = beanMap.get(key); + + // 排除空数据 + if (value == null) { + continue; + } + signMaps.put(key + "", String.valueOf(value)); + } + if(signType.equals("MD5")) { + // 生成签名 + return generateSign(signMaps, mchKey); + }else if(signType.equals("SHA256")){ + return generateSignSHA256(signMaps, mchKey); + }else{ + return null; + } + } + + /** + * 数据转换为xml格式 + * + * @param object + * @param obj + * @return + */ + public static String truncateDataToXML(Class object, Object obj) { + XStream xStream = new XStream(new XppDriver(new NoNameCoder())); + xStream.alias("xml", object); + return xStream.toXML(obj); + } + + + /** + * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。 + * + * @param data 待签名数据 + * @param key API密钥 + * @param signType 签名方式 + * @return 签名 + */ + public static String generateSignature(final Map data, String key, WXPayConstants.SignType signType) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 + sb.append(k).append("=").append(data.get(k).trim()).append("&"); + } + sb.append("key=").append(key); + if (WXPayConstants.SignType.MD5.equals(signType)) { + return MD5(sb.toString() , true); + } + else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) { + return HMACSHA256(sb.toString(), key); + } + else { + throw new Exception(String.format("Invalid sign_type: %s", signType)); + } + } + + public static String generateSignature(final Map data) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (StringUtils.isBlank(sb.toString())) { + sb.append(k).append("=").append(data.get(k)); + } else { + sb.append("&").append(k).append("=").append(data.get(k)); + } + } + return sb.toString(); + } + + public static String generateSignature2(final Map data, String sign, String key) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (data.get(k) != null) // 参数值为空,则不参与签名 + sb.append(k).append("=").append(data.get(k)).append("&"); + } + if (key != null) { + sb.append("app_secret=").append(key); + } + return sb.toString(); + } + + /** + * 生成 MD5 + * + * @param data 待处理数据 + * @return MD5结果 + */ + public static String MD5(String data , Boolean isUpperCase) throws Exception { + java.security.MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] array = md.digest(data.getBytes("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (byte item : array) { + sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); + } + if (isUpperCase) { + return sb.toString().toUpperCase(); + } else { + return sb.toString(); + } + } + + + + /** + * 将Map转换为XML格式的字符串 + * + * @param data Map类型数据 + * @return XML格式的字符串 + * @throws Exception + */ + public static String mapToXml(Map data) throws Exception { + org.w3c.dom.Document document = WXPayXmlUtil.newDocument(); + org.w3c.dom.Element root = document.createElement("xml"); + document.appendChild(root); + for (String key: data.keySet()) { + String value = data.get(key); + if (value == null) { + value = ""; + } + value = value.trim(); + org.w3c.dom.Element filed = document.createElement(key); + filed.appendChild(document.createTextNode(value)); + root.appendChild(filed); + } + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer = tf.newTransformer(); + DOMSource source = new DOMSource(document); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + StringWriter writer = new StringWriter(); + StreamResult result = new StreamResult(writer); + transformer.transform(source, result); + String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); + try { + writer.close(); + } + catch (Exception ex) { + } + return output; + } + + + /** + * 千猪生成签名。 + * + * @param data 待签名数据 + * @param secret API密钥 + * @param signType 签名方式 + * @return 签名 + */ + public static String generateSignaturePig(final Map data, String secret, WXPayConstants.SignType signType) throws Exception { + Set keySet = data.keySet(); + String[] keyArray = keySet.toArray(new String[keySet.size()]); + Arrays.sort(keyArray); + StringBuilder sb = new StringBuilder(); + for (String k : keyArray) { + if (k.equals(WXPayConstants.FIELD_SIGN)) { + continue; + } + if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 + sb.append(k).append("=").append(data.get(k).trim()).append("&"); + } + String s = sb.substring(0, sb.length() - 1) + secret; + + if (WXPayConstants.SignType.MD5.equals(signType)) { + return MD5(sb.toString() , false); + } + else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) { + return HMACSHA256(s, secret); + } + else { + throw new Exception(String.format("Invalid sign_type: %s", signType)); + } + } + + +} diff --git a/service/src/main/java/com/hfkj/config/CommonSysConfig.java b/service/src/main/java/com/hfkj/config/CommonSysConfig.java new file mode 100644 index 0000000..22d5352 --- /dev/null +++ b/service/src/main/java/com/hfkj/config/CommonSysConfig.java @@ -0,0 +1,12 @@ +package com.hfkj.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("commonSysConfig") +@ConfigurationProperties +@PropertySource("classpath:/commonConfig.properties") +public class CommonSysConfig { + +} diff --git a/service/src/main/java/com/hfkj/config/CommonSysConst.java b/service/src/main/java/com/hfkj/config/CommonSysConst.java new file mode 100644 index 0000000..c15122c --- /dev/null +++ b/service/src/main/java/com/hfkj/config/CommonSysConst.java @@ -0,0 +1,19 @@ +package com.hfkj.config; + +public class CommonSysConst { + + private static CommonSysConfig sysConfig; + + public static void setSysConfig(CommonSysConfig arg){ + sysConfig = arg; + } + + public static CommonSysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new CommonSysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/service/src/main/java/com/hfkj/config/ConfigListener.java b/service/src/main/java/com/hfkj/config/ConfigListener.java new file mode 100644 index 0000000..7677905 --- /dev/null +++ b/service/src/main/java/com/hfkj/config/ConfigListener.java @@ -0,0 +1,23 @@ +package com.hfkj.config; + +import javax.annotation.Resource; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Resource + private CommonSysConfig commonSysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + CommonSysConst.setSysConfig(commonSysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/service/src/main/java/com/hfkj/dao/SecDictionaryMapper.java b/service/src/main/java/com/hfkj/dao/SecDictionaryMapper.java new file mode 100644 index 0000000..bf349ed --- /dev/null +++ b/service/src/main/java/com/hfkj/dao/SecDictionaryMapper.java @@ -0,0 +1,105 @@ +package com.hfkj.dao; + +import com.hfkj.entity.SecDictionary; +import com.hfkj.entity.SecDictionaryExample; +import com.hfkj.entity.SecDictionaryKey; +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.type.JdbcType; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * + * 代码由工具生成,请勿修改!!! + * 如果需要扩展请在其父类进行扩展 + * + **/ +@Repository +public interface SecDictionaryMapper extends SecDictionaryMapperExt { + @SelectProvider(type= SecDictionarySqlProvider.class, method="countByExample") + long countByExample(SecDictionaryExample example); + + @DeleteProvider(type= SecDictionarySqlProvider.class, method="deleteByExample") + int deleteByExample(SecDictionaryExample example); + + @Delete({ + "delete from sec_dictionary", + "where code_type = #{codeType,jdbcType=VARCHAR}", + "and code_value = #{codeValue,jdbcType=VARCHAR}" + }) + int deleteByPrimaryKey(SecDictionaryKey key); + + @Insert({ + "insert into sec_dictionary (code_type, code_value, ", + "code_name, code_desc, ", + "sort_id, `status`, ", + "ext_1, ext_2, ext_3)", + "values (#{codeType,jdbcType=VARCHAR}, #{codeValue,jdbcType=VARCHAR}, ", + "#{codeName,jdbcType=VARCHAR}, #{codeDesc,jdbcType=VARCHAR}, ", + "#{sortId,jdbcType=INTEGER}, #{status,jdbcType=INTEGER}, ", + "#{ext1,jdbcType=VARCHAR}, #{ext2,jdbcType=VARCHAR}, #{ext3,jdbcType=VARCHAR})" + }) + int insert(SecDictionary record); + + @InsertProvider(type= SecDictionarySqlProvider.class, method="insertSelective") + int insertSelective(SecDictionary record); + + @SelectProvider(type= SecDictionarySqlProvider.class, method="selectByExample") + @Results({ + @Result(column="code_type", property="codeType", jdbcType=JdbcType.VARCHAR, id=true), + @Result(column="code_value", property="codeValue", jdbcType=JdbcType.VARCHAR, id=true), + @Result(column="code_name", property="codeName", jdbcType=JdbcType.VARCHAR), + @Result(column="code_desc", property="codeDesc", jdbcType=JdbcType.VARCHAR), + @Result(column="sort_id", property="sortId", jdbcType=JdbcType.INTEGER), + @Result(column="status", property="status", jdbcType=JdbcType.INTEGER), + @Result(column="ext_1", property="ext1", jdbcType=JdbcType.VARCHAR), + @Result(column="ext_2", property="ext2", jdbcType=JdbcType.VARCHAR), + @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR) + }) + List selectByExample(SecDictionaryExample example); + + @Select({ + "select", + "code_type, code_value, code_name, code_desc, sort_id, `status`, ext_1, ext_2, ", + "ext_3", + "from sec_dictionary", + "where code_type = #{codeType,jdbcType=VARCHAR}", + "and code_value = #{codeValue,jdbcType=VARCHAR}" + }) + @Results({ + @Result(column="code_type", property="codeType", jdbcType=JdbcType.VARCHAR, id=true), + @Result(column="code_value", property="codeValue", jdbcType=JdbcType.VARCHAR, id=true), + @Result(column="code_name", property="codeName", jdbcType=JdbcType.VARCHAR), + @Result(column="code_desc", property="codeDesc", jdbcType=JdbcType.VARCHAR), + @Result(column="sort_id", property="sortId", jdbcType=JdbcType.INTEGER), + @Result(column="status", property="status", jdbcType=JdbcType.INTEGER), + @Result(column="ext_1", property="ext1", jdbcType=JdbcType.VARCHAR), + @Result(column="ext_2", property="ext2", jdbcType=JdbcType.VARCHAR), + @Result(column="ext_3", property="ext3", jdbcType=JdbcType.VARCHAR) + }) + SecDictionary selectByPrimaryKey(SecDictionaryKey key); + + @UpdateProvider(type= SecDictionarySqlProvider.class, method="updateByExampleSelective") + int updateByExampleSelective(@Param("record") SecDictionary record, @Param("example") SecDictionaryExample example); + + @UpdateProvider(type= SecDictionarySqlProvider.class, method="updateByExample") + int updateByExample(@Param("record") SecDictionary record, @Param("example") SecDictionaryExample example); + + @UpdateProvider(type= SecDictionarySqlProvider.class, method="updateByPrimaryKeySelective") + int updateByPrimaryKeySelective(SecDictionary record); + + @Update({ + "update sec_dictionary", + "set code_name = #{codeName,jdbcType=VARCHAR},", + "code_desc = #{codeDesc,jdbcType=VARCHAR},", + "sort_id = #{sortId,jdbcType=INTEGER},", + "`status` = #{status,jdbcType=INTEGER},", + "ext_1 = #{ext1,jdbcType=VARCHAR},", + "ext_2 = #{ext2,jdbcType=VARCHAR},", + "ext_3 = #{ext3,jdbcType=VARCHAR}", + "where code_type = #{codeType,jdbcType=VARCHAR}", + "and code_value = #{codeValue,jdbcType=VARCHAR}" + }) + int updateByPrimaryKey(SecDictionary record); +} diff --git a/service/src/main/java/com/hfkj/dao/SecDictionaryMapperExt.java b/service/src/main/java/com/hfkj/dao/SecDictionaryMapperExt.java new file mode 100644 index 0000000..997fe10 --- /dev/null +++ b/service/src/main/java/com/hfkj/dao/SecDictionaryMapperExt.java @@ -0,0 +1,7 @@ +package com.hfkj.dao; + +/** + * mapper扩展类 + */ +public interface SecDictionaryMapperExt { +} diff --git a/service/src/main/java/com/hfkj/dao/SecDictionarySqlProvider.java b/service/src/main/java/com/hfkj/dao/SecDictionarySqlProvider.java new file mode 100644 index 0000000..efe822d --- /dev/null +++ b/service/src/main/java/com/hfkj/dao/SecDictionarySqlProvider.java @@ -0,0 +1,292 @@ +package com.hfkj.dao; + +import com.hfkj.entity.SecDictionary; +import com.hfkj.entity.SecDictionaryExample; +import com.hfkj.entity.SecDictionaryExample.Criteria; +import com.hfkj.entity.SecDictionaryExample.Criterion; +import org.apache.ibatis.jdbc.SQL; + +import java.util.List; +import java.util.Map; + +public class SecDictionarySqlProvider { + + public String countByExample(SecDictionaryExample example) { + SQL sql = new SQL(); + sql.SELECT("count(*)").FROM("sec_dictionary"); + applyWhere(sql, example, false); + return sql.toString(); + } + + public String deleteByExample(SecDictionaryExample example) { + SQL sql = new SQL(); + sql.DELETE_FROM("sec_dictionary"); + applyWhere(sql, example, false); + return sql.toString(); + } + + public String insertSelective(SecDictionary record) { + SQL sql = new SQL(); + sql.INSERT_INTO("sec_dictionary"); + + if (record.getCodeType() != null) { + sql.VALUES("code_type", "#{codeType,jdbcType=VARCHAR}"); + } + + if (record.getCodeValue() != null) { + sql.VALUES("code_value", "#{codeValue,jdbcType=VARCHAR}"); + } + + if (record.getCodeName() != null) { + sql.VALUES("code_name", "#{codeName,jdbcType=VARCHAR}"); + } + + if (record.getCodeDesc() != null) { + sql.VALUES("code_desc", "#{codeDesc,jdbcType=VARCHAR}"); + } + + if (record.getSortId() != null) { + sql.VALUES("sort_id", "#{sortId,jdbcType=INTEGER}"); + } + + if (record.getStatus() != null) { + sql.VALUES("`status`", "#{status,jdbcType=INTEGER}"); + } + + if (record.getExt1() != null) { + sql.VALUES("ext_1", "#{ext1,jdbcType=VARCHAR}"); + } + + if (record.getExt2() != null) { + sql.VALUES("ext_2", "#{ext2,jdbcType=VARCHAR}"); + } + + if (record.getExt3() != null) { + sql.VALUES("ext_3", "#{ext3,jdbcType=VARCHAR}"); + } + + return sql.toString(); + } + + public String selectByExample(SecDictionaryExample example) { + SQL sql = new SQL(); + if (example != null && example.isDistinct()) { + sql.SELECT_DISTINCT("code_type"); + } else { + sql.SELECT("code_type"); + } + sql.SELECT("code_value"); + sql.SELECT("code_name"); + sql.SELECT("code_desc"); + sql.SELECT("sort_id"); + sql.SELECT("`status`"); + sql.SELECT("ext_1"); + sql.SELECT("ext_2"); + sql.SELECT("ext_3"); + sql.FROM("sec_dictionary"); + applyWhere(sql, example, false); + + if (example != null && example.getOrderByClause() != null) { + sql.ORDER_BY(example.getOrderByClause()); + } + + return sql.toString(); + } + + public String updateByExampleSelective(Map parameter) { + SecDictionary record = (SecDictionary) parameter.get("record"); + SecDictionaryExample example = (SecDictionaryExample) parameter.get("example"); + + SQL sql = new SQL(); + sql.UPDATE("sec_dictionary"); + + if (record.getCodeType() != null) { + sql.SET("code_type = #{record.codeType,jdbcType=VARCHAR}"); + } + + if (record.getCodeValue() != null) { + sql.SET("code_value = #{record.codeValue,jdbcType=VARCHAR}"); + } + + if (record.getCodeName() != null) { + sql.SET("code_name = #{record.codeName,jdbcType=VARCHAR}"); + } + + if (record.getCodeDesc() != null) { + sql.SET("code_desc = #{record.codeDesc,jdbcType=VARCHAR}"); + } + + if (record.getSortId() != null) { + sql.SET("sort_id = #{record.sortId,jdbcType=INTEGER}"); + } + + if (record.getStatus() != null) { + sql.SET("`status` = #{record.status,jdbcType=INTEGER}"); + } + + if (record.getExt1() != null) { + sql.SET("ext_1 = #{record.ext1,jdbcType=VARCHAR}"); + } + + if (record.getExt2() != null) { + sql.SET("ext_2 = #{record.ext2,jdbcType=VARCHAR}"); + } + + if (record.getExt3() != null) { + sql.SET("ext_3 = #{record.ext3,jdbcType=VARCHAR}"); + } + + applyWhere(sql, example, true); + return sql.toString(); + } + + public String updateByExample(Map parameter) { + SQL sql = new SQL(); + sql.UPDATE("sec_dictionary"); + + sql.SET("code_type = #{record.codeType,jdbcType=VARCHAR}"); + sql.SET("code_value = #{record.codeValue,jdbcType=VARCHAR}"); + sql.SET("code_name = #{record.codeName,jdbcType=VARCHAR}"); + sql.SET("code_desc = #{record.codeDesc,jdbcType=VARCHAR}"); + sql.SET("sort_id = #{record.sortId,jdbcType=INTEGER}"); + sql.SET("`status` = #{record.status,jdbcType=INTEGER}"); + sql.SET("ext_1 = #{record.ext1,jdbcType=VARCHAR}"); + sql.SET("ext_2 = #{record.ext2,jdbcType=VARCHAR}"); + sql.SET("ext_3 = #{record.ext3,jdbcType=VARCHAR}"); + + SecDictionaryExample example = (SecDictionaryExample) parameter.get("example"); + applyWhere(sql, example, true); + return sql.toString(); + } + + public String updateByPrimaryKeySelective(SecDictionary record) { + SQL sql = new SQL(); + sql.UPDATE("sec_dictionary"); + + if (record.getCodeName() != null) { + sql.SET("code_name = #{codeName,jdbcType=VARCHAR}"); + } + + if (record.getCodeDesc() != null) { + sql.SET("code_desc = #{codeDesc,jdbcType=VARCHAR}"); + } + + if (record.getSortId() != null) { + sql.SET("sort_id = #{sortId,jdbcType=INTEGER}"); + } + + if (record.getStatus() != null) { + sql.SET("`status` = #{status,jdbcType=INTEGER}"); + } + + if (record.getExt1() != null) { + sql.SET("ext_1 = #{ext1,jdbcType=VARCHAR}"); + } + + if (record.getExt2() != null) { + sql.SET("ext_2 = #{ext2,jdbcType=VARCHAR}"); + } + + if (record.getExt3() != null) { + sql.SET("ext_3 = #{ext3,jdbcType=VARCHAR}"); + } + + sql.WHERE("code_type = #{codeType,jdbcType=VARCHAR}"); + sql.WHERE("code_value = #{codeValue,jdbcType=VARCHAR}"); + + return sql.toString(); + } + + protected void applyWhere(SQL sql, SecDictionaryExample example, boolean includeExamplePhrase) { + if (example == null) { + return; + } + + String parmPhrase1; + String parmPhrase1_th; + String parmPhrase2; + String parmPhrase2_th; + String parmPhrase3; + String parmPhrase3_th; + if (includeExamplePhrase) { + parmPhrase1 = "%s #{example.oredCriteria[%d].allCriteria[%d].value}"; + parmPhrase1_th = "%s #{example.oredCriteria[%d].allCriteria[%d].value,typeHandler=%s}"; + parmPhrase2 = "%s #{example.oredCriteria[%d].allCriteria[%d].value} and #{example.oredCriteria[%d].criteria[%d].secondValue}"; + parmPhrase2_th = "%s #{example.oredCriteria[%d].allCriteria[%d].value,typeHandler=%s} and #{example.oredCriteria[%d].criteria[%d].secondValue,typeHandler=%s}"; + parmPhrase3 = "#{example.oredCriteria[%d].allCriteria[%d].value[%d]}"; + parmPhrase3_th = "#{example.oredCriteria[%d].allCriteria[%d].value[%d],typeHandler=%s}"; + } else { + parmPhrase1 = "%s #{oredCriteria[%d].allCriteria[%d].value}"; + parmPhrase1_th = "%s #{oredCriteria[%d].allCriteria[%d].value,typeHandler=%s}"; + parmPhrase2 = "%s #{oredCriteria[%d].allCriteria[%d].value} and #{oredCriteria[%d].criteria[%d].secondValue}"; + parmPhrase2_th = "%s #{oredCriteria[%d].allCriteria[%d].value,typeHandler=%s} and #{oredCriteria[%d].criteria[%d].secondValue,typeHandler=%s}"; + parmPhrase3 = "#{oredCriteria[%d].allCriteria[%d].value[%d]}"; + parmPhrase3_th = "#{oredCriteria[%d].allCriteria[%d].value[%d],typeHandler=%s}"; + } + + StringBuilder sb = new StringBuilder(); + List oredCriteria = example.getOredCriteria(); + boolean firstCriteria = true; + for (int i = 0; i < oredCriteria.size(); i++) { + Criteria criteria = oredCriteria.get(i); + if (criteria.isValid()) { + if (firstCriteria) { + firstCriteria = false; + } else { + sb.append(" or "); + } + + sb.append('('); + List criterions = criteria.getAllCriteria(); + boolean firstCriterion = true; + for (int j = 0; j < criterions.size(); j++) { + Criterion criterion = criterions.get(j); + if (firstCriterion) { + firstCriterion = false; + } else { + sb.append(" and "); + } + + if (criterion.isNoValue()) { + sb.append(criterion.getCondition()); + } else if (criterion.isSingleValue()) { + if (criterion.getTypeHandler() == null) { + sb.append(String.format(parmPhrase1, criterion.getCondition(), i, j)); + } else { + sb.append(String.format(parmPhrase1_th, criterion.getCondition(), i, j,criterion.getTypeHandler())); + } + } else if (criterion.isBetweenValue()) { + if (criterion.getTypeHandler() == null) { + sb.append(String.format(parmPhrase2, criterion.getCondition(), i, j, i, j)); + } else { + sb.append(String.format(parmPhrase2_th, criterion.getCondition(), i, j, criterion.getTypeHandler(), i, j, criterion.getTypeHandler())); + } + } else if (criterion.isListValue()) { + sb.append(criterion.getCondition()); + sb.append(" ("); + List listItems = (List) criterion.getValue(); + boolean comma = false; + for (int k = 0; k < listItems.size(); k++) { + if (comma) { + sb.append(", "); + } else { + comma = true; + } + if (criterion.getTypeHandler() == null) { + sb.append(String.format(parmPhrase3, i, j, k)); + } else { + sb.append(String.format(parmPhrase3_th, i, j, k, criterion.getTypeHandler())); + } + } + sb.append(')'); + } + } + sb.append(')'); + } + } + + if (sb.length() > 0) { + sql.WHERE(sb.toString()); + } + } +} diff --git a/service/src/main/java/com/hfkj/entity/SecDictionary.java b/service/src/main/java/com/hfkj/entity/SecDictionary.java new file mode 100644 index 0000000..f2361a3 --- /dev/null +++ b/service/src/main/java/com/hfkj/entity/SecDictionary.java @@ -0,0 +1,156 @@ +package com.hfkj.entity; + +import java.io.Serializable; + +/** + * sec_dictionary + * @author + */ + +/** + * + * 代码由工具生成 + * + **/ +public class SecDictionary extends SecDictionaryKey implements Serializable { + /** + * 码值名称 + */ + private String codeName; + + /** + * 描述 + */ + private String codeDesc; + + /** + * 排序 + */ + private Integer sortId; + + /** + * 状态:0:不可用,1:可用 + */ + private Integer status; + + private String ext1; + + private String ext2; + + private String ext3; + + private static final long serialVersionUID = 1L; + + public String getCodeName() { + return codeName; + } + + public void setCodeName(String codeName) { + this.codeName = codeName; + } + + public String getCodeDesc() { + return codeDesc; + } + + public void setCodeDesc(String codeDesc) { + this.codeDesc = codeDesc; + } + + public Integer getSortId() { + return sortId; + } + + public void setSortId(Integer sortId) { + this.sortId = sortId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getExt1() { + return ext1; + } + + public void setExt1(String ext1) { + this.ext1 = ext1; + } + + public String getExt2() { + return ext2; + } + + public void setExt2(String ext2) { + this.ext2 = ext2; + } + + public String getExt3() { + return ext3; + } + + public void setExt3(String ext3) { + this.ext3 = ext3; + } + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + SecDictionary other = (SecDictionary) that; + return (this.getCodeType() == null ? other.getCodeType() == null : this.getCodeType().equals(other.getCodeType())) + && (this.getCodeValue() == null ? other.getCodeValue() == null : this.getCodeValue().equals(other.getCodeValue())) + && (this.getCodeName() == null ? other.getCodeName() == null : this.getCodeName().equals(other.getCodeName())) + && (this.getCodeDesc() == null ? other.getCodeDesc() == null : this.getCodeDesc().equals(other.getCodeDesc())) + && (this.getSortId() == null ? other.getSortId() == null : this.getSortId().equals(other.getSortId())) + && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus())) + && (this.getExt1() == null ? other.getExt1() == null : this.getExt1().equals(other.getExt1())) + && (this.getExt2() == null ? other.getExt2() == null : this.getExt2().equals(other.getExt2())) + && (this.getExt3() == null ? other.getExt3() == null : this.getExt3().equals(other.getExt3())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getCodeType() == null) ? 0 : getCodeType().hashCode()); + result = prime * result + ((getCodeValue() == null) ? 0 : getCodeValue().hashCode()); + result = prime * result + ((getCodeName() == null) ? 0 : getCodeName().hashCode()); + result = prime * result + ((getCodeDesc() == null) ? 0 : getCodeDesc().hashCode()); + result = prime * result + ((getSortId() == null) ? 0 : getSortId().hashCode()); + result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode()); + result = prime * result + ((getExt1() == null) ? 0 : getExt1().hashCode()); + result = prime * result + ((getExt2() == null) ? 0 : getExt2().hashCode()); + result = prime * result + ((getExt3() == null) ? 0 : getExt3().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", codeName=").append(codeName); + sb.append(", codeDesc=").append(codeDesc); + sb.append(", sortId=").append(sortId); + sb.append(", status=").append(status); + sb.append(", ext1=").append(ext1); + sb.append(", ext2=").append(ext2); + sb.append(", ext3=").append(ext3); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} diff --git a/service/src/main/java/com/hfkj/entity/SecDictionaryExample.java b/service/src/main/java/com/hfkj/entity/SecDictionaryExample.java new file mode 100644 index 0000000..f025edf --- /dev/null +++ b/service/src/main/java/com/hfkj/entity/SecDictionaryExample.java @@ -0,0 +1,832 @@ +package com.hfkj.entity; + +import java.util.ArrayList; +import java.util.List; + +public class SecDictionaryExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + private Integer limit; + + private Long offset; + + public SecDictionaryExample() { + oredCriteria = new ArrayList(); + } + + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + public String getOrderByClause() { + return orderByClause; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public List getOredCriteria() { + return oredCriteria; + } + + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + public void setLimit(Integer limit) { + this.limit = limit; + } + + public Integer getLimit() { + return limit; + } + + public void setOffset(Long offset) { + this.offset = offset; + } + + public Long getOffset() { + return offset; + } + + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andCodeTypeIsNull() { + addCriterion("code_type is null"); + return (Criteria) this; + } + + public Criteria andCodeTypeIsNotNull() { + addCriterion("code_type is not null"); + return (Criteria) this; + } + + public Criteria andCodeTypeEqualTo(String value) { + addCriterion("code_type =", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeNotEqualTo(String value) { + addCriterion("code_type <>", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeGreaterThan(String value) { + addCriterion("code_type >", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeGreaterThanOrEqualTo(String value) { + addCriterion("code_type >=", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeLessThan(String value) { + addCriterion("code_type <", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeLessThanOrEqualTo(String value) { + addCriterion("code_type <=", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeLike(String value) { + addCriterion("code_type like", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeNotLike(String value) { + addCriterion("code_type not like", value, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeIn(List values) { + addCriterion("code_type in", values, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeNotIn(List values) { + addCriterion("code_type not in", values, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeBetween(String value1, String value2) { + addCriterion("code_type between", value1, value2, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeTypeNotBetween(String value1, String value2) { + addCriterion("code_type not between", value1, value2, "codeType"); + return (Criteria) this; + } + + public Criteria andCodeValueIsNull() { + addCriterion("code_value is null"); + return (Criteria) this; + } + + public Criteria andCodeValueIsNotNull() { + addCriterion("code_value is not null"); + return (Criteria) this; + } + + public Criteria andCodeValueEqualTo(String value) { + addCriterion("code_value =", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueNotEqualTo(String value) { + addCriterion("code_value <>", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueGreaterThan(String value) { + addCriterion("code_value >", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueGreaterThanOrEqualTo(String value) { + addCriterion("code_value >=", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueLessThan(String value) { + addCriterion("code_value <", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueLessThanOrEqualTo(String value) { + addCriterion("code_value <=", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueLike(String value) { + addCriterion("code_value like", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueNotLike(String value) { + addCriterion("code_value not like", value, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueIn(List values) { + addCriterion("code_value in", values, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueNotIn(List values) { + addCriterion("code_value not in", values, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueBetween(String value1, String value2) { + addCriterion("code_value between", value1, value2, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeValueNotBetween(String value1, String value2) { + addCriterion("code_value not between", value1, value2, "codeValue"); + return (Criteria) this; + } + + public Criteria andCodeNameIsNull() { + addCriterion("code_name is null"); + return (Criteria) this; + } + + public Criteria andCodeNameIsNotNull() { + addCriterion("code_name is not null"); + return (Criteria) this; + } + + public Criteria andCodeNameEqualTo(String value) { + addCriterion("code_name =", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameNotEqualTo(String value) { + addCriterion("code_name <>", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameGreaterThan(String value) { + addCriterion("code_name >", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameGreaterThanOrEqualTo(String value) { + addCriterion("code_name >=", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameLessThan(String value) { + addCriterion("code_name <", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameLessThanOrEqualTo(String value) { + addCriterion("code_name <=", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameLike(String value) { + addCriterion("code_name like", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameNotLike(String value) { + addCriterion("code_name not like", value, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameIn(List values) { + addCriterion("code_name in", values, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameNotIn(List values) { + addCriterion("code_name not in", values, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameBetween(String value1, String value2) { + addCriterion("code_name between", value1, value2, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeNameNotBetween(String value1, String value2) { + addCriterion("code_name not between", value1, value2, "codeName"); + return (Criteria) this; + } + + public Criteria andCodeDescIsNull() { + addCriterion("code_desc is null"); + return (Criteria) this; + } + + public Criteria andCodeDescIsNotNull() { + addCriterion("code_desc is not null"); + return (Criteria) this; + } + + public Criteria andCodeDescEqualTo(String value) { + addCriterion("code_desc =", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescNotEqualTo(String value) { + addCriterion("code_desc <>", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescGreaterThan(String value) { + addCriterion("code_desc >", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescGreaterThanOrEqualTo(String value) { + addCriterion("code_desc >=", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescLessThan(String value) { + addCriterion("code_desc <", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescLessThanOrEqualTo(String value) { + addCriterion("code_desc <=", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescLike(String value) { + addCriterion("code_desc like", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescNotLike(String value) { + addCriterion("code_desc not like", value, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescIn(List values) { + addCriterion("code_desc in", values, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescNotIn(List values) { + addCriterion("code_desc not in", values, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescBetween(String value1, String value2) { + addCriterion("code_desc between", value1, value2, "codeDesc"); + return (Criteria) this; + } + + public Criteria andCodeDescNotBetween(String value1, String value2) { + addCriterion("code_desc not between", value1, value2, "codeDesc"); + return (Criteria) this; + } + + public Criteria andSortIdIsNull() { + addCriterion("sort_id is null"); + return (Criteria) this; + } + + public Criteria andSortIdIsNotNull() { + addCriterion("sort_id is not null"); + return (Criteria) this; + } + + public Criteria andSortIdEqualTo(Integer value) { + addCriterion("sort_id =", value, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdNotEqualTo(Integer value) { + addCriterion("sort_id <>", value, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdGreaterThan(Integer value) { + addCriterion("sort_id >", value, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdGreaterThanOrEqualTo(Integer value) { + addCriterion("sort_id >=", value, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdLessThan(Integer value) { + addCriterion("sort_id <", value, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdLessThanOrEqualTo(Integer value) { + addCriterion("sort_id <=", value, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdIn(List values) { + addCriterion("sort_id in", values, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdNotIn(List values) { + addCriterion("sort_id not in", values, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdBetween(Integer value1, Integer value2) { + addCriterion("sort_id between", value1, value2, "sortId"); + return (Criteria) this; + } + + public Criteria andSortIdNotBetween(Integer value1, Integer value2) { + addCriterion("sort_id not between", value1, value2, "sortId"); + return (Criteria) this; + } + + public Criteria andStatusIsNull() { + addCriterion("`status` is null"); + return (Criteria) this; + } + + public Criteria andStatusIsNotNull() { + addCriterion("`status` is not null"); + return (Criteria) this; + } + + public Criteria andStatusEqualTo(Integer value) { + addCriterion("`status` =", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotEqualTo(Integer value) { + addCriterion("`status` <>", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThan(Integer value) { + addCriterion("`status` >", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThanOrEqualTo(Integer value) { + addCriterion("`status` >=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThan(Integer value) { + addCriterion("`status` <", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThanOrEqualTo(Integer value) { + addCriterion("`status` <=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusIn(List values) { + addCriterion("`status` in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotIn(List values) { + addCriterion("`status` not in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusBetween(Integer value1, Integer value2) { + addCriterion("`status` between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotBetween(Integer value1, Integer value2) { + addCriterion("`status` not between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andExt1IsNull() { + addCriterion("ext_1 is null"); + return (Criteria) this; + } + + public Criteria andExt1IsNotNull() { + addCriterion("ext_1 is not null"); + return (Criteria) this; + } + + public Criteria andExt1EqualTo(String value) { + addCriterion("ext_1 =", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1NotEqualTo(String value) { + addCriterion("ext_1 <>", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1GreaterThan(String value) { + addCriterion("ext_1 >", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1GreaterThanOrEqualTo(String value) { + addCriterion("ext_1 >=", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1LessThan(String value) { + addCriterion("ext_1 <", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1LessThanOrEqualTo(String value) { + addCriterion("ext_1 <=", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1Like(String value) { + addCriterion("ext_1 like", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1NotLike(String value) { + addCriterion("ext_1 not like", value, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1In(List values) { + addCriterion("ext_1 in", values, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1NotIn(List values) { + addCriterion("ext_1 not in", values, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1Between(String value1, String value2) { + addCriterion("ext_1 between", value1, value2, "ext1"); + return (Criteria) this; + } + + public Criteria andExt1NotBetween(String value1, String value2) { + addCriterion("ext_1 not between", value1, value2, "ext1"); + return (Criteria) this; + } + + public Criteria andExt2IsNull() { + addCriterion("ext_2 is null"); + return (Criteria) this; + } + + public Criteria andExt2IsNotNull() { + addCriterion("ext_2 is not null"); + return (Criteria) this; + } + + public Criteria andExt2EqualTo(String value) { + addCriterion("ext_2 =", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2NotEqualTo(String value) { + addCriterion("ext_2 <>", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2GreaterThan(String value) { + addCriterion("ext_2 >", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2GreaterThanOrEqualTo(String value) { + addCriterion("ext_2 >=", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2LessThan(String value) { + addCriterion("ext_2 <", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2LessThanOrEqualTo(String value) { + addCriterion("ext_2 <=", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2Like(String value) { + addCriterion("ext_2 like", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2NotLike(String value) { + addCriterion("ext_2 not like", value, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2In(List values) { + addCriterion("ext_2 in", values, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2NotIn(List values) { + addCriterion("ext_2 not in", values, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2Between(String value1, String value2) { + addCriterion("ext_2 between", value1, value2, "ext2"); + return (Criteria) this; + } + + public Criteria andExt2NotBetween(String value1, String value2) { + addCriterion("ext_2 not between", value1, value2, "ext2"); + return (Criteria) this; + } + + public Criteria andExt3IsNull() { + addCriterion("ext_3 is null"); + return (Criteria) this; + } + + public Criteria andExt3IsNotNull() { + addCriterion("ext_3 is not null"); + return (Criteria) this; + } + + public Criteria andExt3EqualTo(String value) { + addCriterion("ext_3 =", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3NotEqualTo(String value) { + addCriterion("ext_3 <>", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3GreaterThan(String value) { + addCriterion("ext_3 >", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3GreaterThanOrEqualTo(String value) { + addCriterion("ext_3 >=", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3LessThan(String value) { + addCriterion("ext_3 <", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3LessThanOrEqualTo(String value) { + addCriterion("ext_3 <=", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3Like(String value) { + addCriterion("ext_3 like", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3NotLike(String value) { + addCriterion("ext_3 not like", value, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3In(List values) { + addCriterion("ext_3 in", values, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3NotIn(List values) { + addCriterion("ext_3 not in", values, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3Between(String value1, String value2) { + addCriterion("ext_3 between", value1, value2, "ext3"); + return (Criteria) this; + } + + public Criteria andExt3NotBetween(String value1, String value2) { + addCriterion("ext_3 not between", value1, value2, "ext3"); + return (Criteria) this; + } + } + + /** + */ + public static class Criteria extends GeneratedCriteria { + + protected Criteria() { + super(); + } + } + + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} diff --git a/service/src/main/java/com/hfkj/entity/SecDictionaryKey.java b/service/src/main/java/com/hfkj/entity/SecDictionaryKey.java new file mode 100644 index 0000000..5ad3f02 --- /dev/null +++ b/service/src/main/java/com/hfkj/entity/SecDictionaryKey.java @@ -0,0 +1,75 @@ +package com.hfkj.entity; + +import java.io.Serializable; + +/** + * sec_dictionary + * @author + */ +public class SecDictionaryKey implements Serializable { + /** + * 码值类型 + */ + private String codeType; + + /** + * 码值 + */ + private String codeValue; + + private static final long serialVersionUID = 1L; + + public String getCodeType() { + return codeType; + } + + public void setCodeType(String codeType) { + this.codeType = codeType; + } + + public String getCodeValue() { + return codeValue; + } + + public void setCodeValue(String codeValue) { + this.codeValue = codeValue; + } + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + SecDictionaryKey other = (SecDictionaryKey) that; + return (this.getCodeType() == null ? other.getCodeType() == null : this.getCodeType().equals(other.getCodeType())) + && (this.getCodeValue() == null ? other.getCodeValue() == null : this.getCodeValue().equals(other.getCodeValue())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getCodeType() == null) ? 0 : getCodeType().hashCode()); + result = prime * result + ((getCodeValue() == null) ? 0 : getCodeValue().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", codeType=").append(codeType); + sb.append(", codeValue=").append(codeValue); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} diff --git a/service/src/main/java/com/hfkj/model/CommonTreeModel.java b/service/src/main/java/com/hfkj/model/CommonTreeModel.java new file mode 100644 index 0000000..79b71b0 --- /dev/null +++ b/service/src/main/java/com/hfkj/model/CommonTreeModel.java @@ -0,0 +1,80 @@ +package com.hfkj.model; + +import java.util.ArrayList; +import java.util.List; + +public class CommonTreeModel { + + private String text; + + private Long id; + + private Long pId; + + private Integer showOnMobile; + + private List nodes; + + + + public Integer getShowOnMobile() { + return showOnMobile; + } + + + public void setShowOnMobile(Integer showOnMobile) { + this.showOnMobile = showOnMobile; + } + + + public String getText() { + return text; + } + + + public void setText(String text) { + this.text = text; + } + + public Long getId() { + return id; + } + + + public void setId(Long id) { + this.id = id; + } + + + public Long getpId() { + return pId; + } + + + public void setpId(Long pId) { + this.pId = pId; + } + + + public List getNodes() { + return nodes; + } + + + public void setNodes(List nodes) { + this.nodes = nodes; + } + + + /** + * 添加子节点. + * @param child + */ + public void add(CommonTreeModel child) { + if (nodes == null) { + nodes = new ArrayList<>(); + } + nodes.add(child); + } + +} diff --git a/service/src/main/java/com/hfkj/model/MenuTreeModel.java b/service/src/main/java/com/hfkj/model/MenuTreeModel.java new file mode 100644 index 0000000..9897fe2 --- /dev/null +++ b/service/src/main/java/com/hfkj/model/MenuTreeModel.java @@ -0,0 +1,130 @@ +package com.hfkj.model; + +import java.util.ArrayList; +import java.util.List; + +public class MenuTreeModel { + + private Long sid; + + private String menuName; + + private String menuUrl; + + private String menuUrlImg; + + private Long menuPSid; + + //父名称 + private String parentName; + + private Integer menuSort; + + private String menuDesc; + + private String menuMobileUrl;//手机端URL + + private Integer showOnMobile;//是否在手机端展示 + + private List children; + + public String getMenuMobileUrl() { + return menuMobileUrl; + } + + public void setMenuMobileUrl(String menuMobileUrl) { + this.menuMobileUrl = menuMobileUrl; + } + + public Integer getShowOnMobile() { + return showOnMobile; + } + + public void setShowOnMobile(Integer showOnMobile) { + this.showOnMobile = showOnMobile; + } + + public Long getSid() { + return sid; + } + + public void setSid(Long sid) { + this.sid = sid; + } + + public String getMenuName() { + return menuName; + } + + public void setMenuName(String menuName) { + this.menuName = menuName; + } + + public String getMenuUrl() { + return menuUrl; + } + + public void setMenuUrl(String menuUrl) { + this.menuUrl = menuUrl; + } + + public String getMenuUrlImg() { + return menuUrlImg; + } + + public void setMenuUrlImg(String menuUrlImg) { + this.menuUrlImg = menuUrlImg; + } + + public Long getMenuPSid() { + return menuPSid; + } + + public void setMenuPSid(Long menuPSid) { + this.menuPSid = menuPSid; + } + + public String getParentName() { + return parentName; + } + + public void setParentName(String parentName) { + this.parentName = parentName; + } + + public Integer getMenuSort() { + return menuSort; + } + + public void setMenuSort(Integer menuSort) { + this.menuSort = menuSort; + } + + public String getMenuDesc() { + return menuDesc; + } + + public void setMenuDesc(String menuDesc) { + this.menuDesc = menuDesc; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + /** + * 添加子节点. + * @param child + */ + public void add(MenuTreeModel child) { + if (children == null) { + children = new ArrayList<>(); + } + children.add(child); + } + +} diff --git a/service/src/main/java/com/hfkj/model/ResponseData.java b/service/src/main/java/com/hfkj/model/ResponseData.java new file mode 100644 index 0000000..64dd429 --- /dev/null +++ b/service/src/main/java/com/hfkj/model/ResponseData.java @@ -0,0 +1,36 @@ +package com.hfkj.model; + +public class ResponseData { + + private String return_code; + + //错误描述 + private String return_msg; + + private Object return_data; + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public Object getReturn_data() { + return return_data; + } + + public void setReturn_data(Object return_data) { + this.return_data = return_data; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + +} diff --git a/service/src/main/java/com/hfkj/model/UserInfoModel.java b/service/src/main/java/com/hfkj/model/UserInfoModel.java new file mode 100644 index 0000000..3007b75 --- /dev/null +++ b/service/src/main/java/com/hfkj/model/UserInfoModel.java @@ -0,0 +1,6 @@ +package com.hfkj.model; + +public class UserInfoModel { + + +} diff --git a/service/src/main/java/com/hfkj/service/FileUploadService.java b/service/src/main/java/com/hfkj/service/FileUploadService.java new file mode 100644 index 0000000..dc612ec --- /dev/null +++ b/service/src/main/java/com/hfkj/service/FileUploadService.java @@ -0,0 +1,39 @@ +package com.hfkj.service; + +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; +import java.util.Map; + +/** + * @ClassName: FileUploadService + * @Description: 文件上传 + * @author: gongjia + * @date: 2019/10/30 11:36 + * @Copyright: 2019 www.shinwoten.com Inc. All rights reserved. + */ +public interface FileUploadService { + + /** + * + * @Title: upload + * @Description: 上传文件 + * @author: gongjia + * @param: [files, paramsMap] + * @return: java.util.List + * @throws + */ + Map upload(List files, Map paramsMap) throws Exception; + + /** + * + * @Title: deleteFile + * @Description: 删除文件 + * @author: 杜江 + * @Date: 2020/7/9 10:12 + * @param: [filePath] + * @return: boolean + * @throws + */ + boolean deleteFile(String filePath); +} diff --git a/service/src/main/java/com/hfkj/service/impl/FileUploadServiceImpl.java b/service/src/main/java/com/hfkj/service/impl/FileUploadServiceImpl.java new file mode 100644 index 0000000..ac82530 --- /dev/null +++ b/service/src/main/java/com/hfkj/service/impl/FileUploadServiceImpl.java @@ -0,0 +1,118 @@ +package com.hfkj.service.impl; + +import com.hfkj.common.exception.ErrorCode; +import com.hfkj.common.exception.ErrorHelp; +import com.hfkj.common.exception.SysCode; +import com.hfkj.common.security.Base64Util; +import com.hfkj.service.FileUploadService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service(value = "fileUploadService") +public class FileUploadServiceImpl implements FileUploadService { + + @Override + @Transactional + public Map upload(List files, Map paramsMap) throws Exception { + + String pathPrefix = paramsMap.get("pathPrefix"); // 文件前缀 + String fileNameGenerator = paramsMap.get("fileNameGenerator"); // 文件名生成方式 + if (StringUtils.isBlank(pathPrefix) + || StringUtils.isBlank(fileNameGenerator)) { + throw ErrorHelp.genException(SysCode.System, ErrorCode.REQ_PARAMS_ERROR, ""); + } + + Map result = new HashMap<>(); + for (MultipartFile file : files) { + if (!file.isEmpty()) { + String fileName = file.getOriginalFilename(); // 获取文件名 + fileName = generateFileName(fileName, paramsMap); // 按照生成规则生成文件名 + result.put(file.getOriginalFilename(), fileName); + + File dest = new File(pathPrefix + File.separator + fileName); + if (!dest.getParentFile().exists()) { + dest.getParentFile().mkdirs(); + } + file.transferTo(dest); + } + } + + return result; + } + + @Override + public boolean deleteFile(String filePath) { + boolean delete_flag = false; + File file = new File(filePath); + if (file.exists() && file.isFile() && file.delete()) + delete_flag = true; + else + delete_flag = false; + return delete_flag; + } + + /** + * 根据不同规则生成文件名 + */ + private String generateFileName(String fileName, Map paramsMap) throws Exception{ + + /** + * 获取文件名后缀 + * (1)如果指定后缀,用指定的后缀名称 + * (2)如果未指定后缀,且文件有后缀,用文件自己的后缀 + * (3)如果未指定后缀,且文件无后缀,则生成的文件也没有后缀 + */ + String pathSuffix = paramsMap.get("pathSuffix"); + if (StringUtils.isBlank(pathSuffix)) { + if (fileName.lastIndexOf('.') != -1) { + pathSuffix = fileName.substring(fileName.lastIndexOf('.')); + } else { + pathSuffix = ""; + } + } + // 文件名前缀 + String name = fileName.substring(0, fileName.lastIndexOf(".")); + + // 生成文件名 + String result = null; + if ("generateFileNameById".equals(paramsMap.get("fileNameGenerator"))) { + // 对文件指定id进行Base64加密 + // todo 暂不使用,没有id + if (StringUtils.isBlank(paramsMap.get(fileName))) { + result = fileName; + } else { + result = Base64Util.encode(paramsMap.get(fileName)) + pathSuffix; + } + + } else if ("generateFileNameByTimeStamp".equals(paramsMap.get("fileNameGenerator"))) { + // 根据时间戳生成文件名 + + result = String.valueOf(System.currentTimeMillis()) + pathSuffix; + + } else if ("generateFileNameByOriginalName".equals(paramsMap.get("fileNameGenerator"))) { + // 按"原文件名"生成文件名 + + result = fileName; + + }else if ("generateFileNameAndTimeStamp".equals(paramsMap.get("fileNameGenerator"))) { + // 按"原文件名+时间戳"生成文件名 + + result = name + String.valueOf(System.currentTimeMillis()) + pathSuffix; + + } + + String childPath = paramsMap.get("childPath"); + if (StringUtils.isBlank(childPath)) { + childPath = ""; + } + return childPath + result; + } + +} diff --git a/service/src/main/resources/dev/commonConfig.properties b/service/src/main/resources/dev/commonConfig.properties new file mode 100644 index 0000000..e69de29 diff --git a/service/src/main/resources/pre/commonConfig.properties b/service/src/main/resources/pre/commonConfig.properties new file mode 100644 index 0000000..e69de29 diff --git a/service/src/main/resources/prod/commonConfig.properties b/service/src/main/resources/prod/commonConfig.properties new file mode 100644 index 0000000..e69de29 diff --git a/user/pom.xml b/user/pom.xml new file mode 100644 index 0000000..86a8a25 --- /dev/null +++ b/user/pom.xml @@ -0,0 +1,45 @@ + + + + com.hfkj + puhui-go-parent + 1.0-SNAPSHOT + + 4.0.0 + + com.hfkj + user + + + + com.hfkj + service + PACKT-SNAPSHOT + + + + + + + src/main/resources/${env} + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/user/src/main/java/com/UserApplication.java b/user/src/main/java/com/UserApplication.java new file mode 100644 index 0000000..1e41ac9 --- /dev/null +++ b/user/src/main/java/com/UserApplication.java @@ -0,0 +1,30 @@ +package com; + +import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation; +import com.alicp.jetcache.anno.config.EnableMethodCache; +import com.hfkj.common.utils.SpringContextUtil; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@SpringBootApplication +// @ComponentScan +@EnableTransactionManagement +@EnableScheduling +@EnableMethodCache(basePackages = "com.hfkj") +@EnableCreateCacheAnnotation +@ServletComponentScan +@MapperScan("com.hfkj.dao") +public class UserApplication +{ + public static void main( String[] args ) + { + ApplicationContext app = SpringApplication.run(UserApplication.class, args); + SpringContextUtil.setApplicationContext(app); + } + +} diff --git a/user/src/main/java/com/user/config/AuthConfig.java b/user/src/main/java/com/user/config/AuthConfig.java new file mode 100644 index 0000000..f83581e --- /dev/null +++ b/user/src/main/java/com/user/config/AuthConfig.java @@ -0,0 +1,169 @@ +package com.user.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.hfkj.common.security.UserCenter; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +@Configuration +public class AuthConfig implements WebMvcConfigurer { + + private static Logger log = LoggerFactory.getLogger(AuthConfig.class); + + @Resource + private UserCenter userCenter; + + /** + * 获取配置文件debug变量 + */ + @Value("${debug}") + private boolean debug = false; + + /** + * 解决18位long类型数据转json失去精度问题 + * @param converters + */ + @Override + public void configureMessageConverters(List> converters){ + MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); + + ObjectMapper objectMapper = jsonConverter.getObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + + converters.add(jsonConverter); + } + + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new HandlerInterceptorAdapter() { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, + Object handler) throws Exception { + if(debug){ + return true; + } + String token = request.getParameter("Authorization"); + if (StringUtils.isBlank(token)) { + token = request.getHeader("Authorization"); + } + if((StringUtils.isNotBlank(token) && userCenter.isTokenLogin(token)) || userCenter.isLogin(request)){//如果未登录,将无法使用任何接口 + userCenter.refreshCookie(request, response); + return true; + } else if(request instanceof StandardMultipartHttpServletRequest) { + StandardMultipartHttpServletRequest re = (StandardMultipartHttpServletRequest)request; + if(userCenter.isLogin(re.getRequest())){ + return true; + } else { + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } else{ + log.error("the user is not logged in,remoteAddr:"+getIpAddress(request)+",requestUrl:"+request.getRequestURL()); + response.setStatus(401); + return false; + } + } + }) + .addPathPatterns("/**") + .excludePathPatterns("/swagger-resources/**") + .excludePathPatterns("/**/api-docs") + .excludePathPatterns("/**/springfox-swagger-ui/**") + .excludePathPatterns("/**/swagger-ui.html") + .excludePathPatterns("/login/*") + .excludePathPatterns("/order/*") + .excludePathPatterns("/coupon/getCouponList") + .excludePathPatterns("/wechatpay/*") + .excludePathPatterns("/coupon/getCouponById") + .excludePathPatterns("/discount/getDiscountByQrCode") + .excludePathPatterns("/discount/getDiscountById") + .excludePathPatterns("/discount/getCouponByDiscount") + .excludePathPatterns("/discount/getDiscountByDiscountAgentId") + .excludePathPatterns("/highMerchantStore/getMerchantStoreById") + .excludePathPatterns("/highMerchantStore/getStoreListByCoupon") + .excludePathPatterns("/highMerchantStore/getStoreList") + .excludePathPatterns("/highMerchantStore/getMerchantList") + .excludePathPatterns("/highMerchantStore/getStoreListByMerchant") + .excludePathPatterns("/sms/sendSmsCode") + .excludePathPatterns("/sms/getSmsCode") + .excludePathPatterns("/activity/getWinLotteryList") + .excludePathPatterns("/user/login") + .excludePathPatterns("/user/unionPhoneLogin") + .excludePathPatterns("/user/getUnionId") + .excludePathPatterns("/highUser/setCacheParam") + .excludePathPatterns("/highUser/getCacheParam") + .excludePathPatterns("/highUser/delCacheParam") + .excludePathPatterns("/order/orderToH5Pay") + .excludePathPatterns("/order/orderToPay") + .excludePathPatterns("/test/*") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/outRechargeOrder/*") + .excludePathPatterns("/wechat/*") + .excludePathPatterns("/tuanyou/*") + .excludePathPatterns("/unionPay/*") + .excludePathPatterns("/highGas/*") + .excludePathPatterns("/common/*") + .excludePathPatterns("/order/qzOrderToPay") + .excludePathPatterns("/czOrder/orderRefundNotify") + .excludePathPatterns("/cmsContent/*") + .excludePathPatterns("/highBrand/*") + .excludePathPatterns("/highGoodsType/*") + .excludePathPatterns("/sendSms/*") + .excludePathPatterns("/test/*") + .excludePathPatterns("/sms/*") + ; + } + + public String getIpAddress(HttpServletRequest request) { + // 获取请求主机IP地址,如果通过代理进来,则透过防火墙获取真实IP地址 + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } else if (ip.length() > 15) { + String[] ips = ip.split(","); + for (int index = 0; index < ips.length; index++) { + String strIp = ips[index]; + if (!("unknown".equalsIgnoreCase(strIp))) { + ip = strIp; + break; + } + } + } + return ip; + } + +} diff --git a/user/src/main/java/com/user/config/ConfigListener.java b/user/src/main/java/com/user/config/ConfigListener.java new file mode 100644 index 0000000..29b3a77 --- /dev/null +++ b/user/src/main/java/com/user/config/ConfigListener.java @@ -0,0 +1,23 @@ +package com.user.config; + +import javax.annotation.Resource; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +@WebListener +public class ConfigListener implements ServletContextListener { + + @Resource + private SysConfig sysConfig; + + @Override + public void contextInitialized(ServletContextEvent sce) { + SysConst.setSysConfig(sysConfig); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/user/src/main/java/com/user/config/CorsConfig.java b/user/src/main/java/com/user/config/CorsConfig.java new file mode 100644 index 0000000..2912afe --- /dev/null +++ b/user/src/main/java/com/user/config/CorsConfig.java @@ -0,0 +1,49 @@ +package com.user.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName CorsConfig + * @Description: TODO () + * @Author 胡锐 + * @Date 2020/12/16 + **/ +@Configuration +public class CorsConfig extends WebMvcConfigurerAdapter { + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + List list = new ArrayList<>(); + list.add("*"); + corsConfiguration.setAllowedOrigins(list); + /* + // 请求常用的三种配置,*代表允许所有,当时你也可以自定义属性(比如header只能带什么,只能是post方式等等) + */ + corsConfiguration.addAllowedOrigin("*"); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedMethod("*"); + return corsConfiguration; + } + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); + return new CorsFilter(source); + } +} diff --git a/user/src/main/java/com/user/config/MultipartConfig.java b/user/src/main/java/com/user/config/MultipartConfig.java new file mode 100644 index 0000000..09e6ee1 --- /dev/null +++ b/user/src/main/java/com/user/config/MultipartConfig.java @@ -0,0 +1,26 @@ +package com.user.config; + +import org.springframework.boot.web.servlet.MultipartConfigFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.MultipartConfigElement; + +@Configuration +public class MultipartConfig { + + /** + * 文件上传配置 + * @return + */ + @Bean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + //文件最大 + factory.setMaxFileSize("300MB"); //KB,MB + //设置总上传数据总大小 + factory.setMaxRequestSize("350MB"); + return factory.createMultipartConfig(); + } + +} diff --git a/user/src/main/java/com/user/config/RedisConfig.java b/user/src/main/java/com/user/config/RedisConfig.java new file mode 100644 index 0000000..8261a4a --- /dev/null +++ b/user/src/main/java/com/user/config/RedisConfig.java @@ -0,0 +1,110 @@ +package com.user.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +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.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableCaching //开启注解 +public class RedisConfig extends CachingConfigurerSupport { + + /** + * retemplate相关配置 + * @param factory + * @return + */ + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + + RedisTemplate template = new RedisTemplate<>(); + // 配置连接工厂 + template.setConnectionFactory(factory); + + //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) + Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class); + + ObjectMapper om = new ObjectMapper(); + // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jacksonSeial.setObjectMapper(om); + + // 值采用json序列化 + template.setValueSerializer(jacksonSeial); + //使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + + // 设置hash key 和value序列化模式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(jacksonSeial); + template.afterPropertiesSet(); + + return template; + } + + /** + * 对hash类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + /** + * 对redis字符串类型数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + /** + * 对链表类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + /** + * 对无序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + /** + * 对有序集合类型的数据操作 + * + * @param redisTemplate + * @return + */ + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} diff --git a/user/src/main/java/com/user/config/SwaggerConfig.java b/user/src/main/java/com/user/config/SwaggerConfig.java new file mode 100644 index 0000000..6e58c21 --- /dev/null +++ b/user/src/main/java/com/user/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.user.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +/** +* SwaggerConfig.java +* 项目名称: +* 包: +* 类名称: SwaggerConfig.java +* 类描述: 构建restful api接口文档 +* 创建人: +* 创建时间: 2017 下午4:23:45 +*/ +@Configuration +@EnableSwagger2 +public class SwaggerConfig +{ + + /** + * 描述api的基本信息 + * 基本信息会展现在文档页面中 + * @return [api的基本信息] + */ + ApiInfo apiInfo() + { + return new ApiInfoBuilder().title("hgj-CWeb").description("提供给用户端的接口").termsOfServiceUrl("").version("1.0.0") + .contact(new Contact("", "", "")).build(); + } + + @Bean + public Docket customImplementation() + { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage("com")) + .build().directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class) + .directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class).apiInfo(apiInfo()); + } + +} diff --git a/user/src/main/java/com/user/config/SysConfig.java b/user/src/main/java/com/user/config/SysConfig.java new file mode 100644 index 0000000..cd854a4 --- /dev/null +++ b/user/src/main/java/com/user/config/SysConfig.java @@ -0,0 +1,31 @@ +package com.user.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +@Component("sysConfig") +@ConfigurationProperties +@PropertySource("classpath:/config.properties") +public class SysConfig { + + private String fileUrl; + + private String cmsPath; + + public String getFileUrl() { + return fileUrl; + } + + public void setFileUrl(String fileUrl) { + this.fileUrl = fileUrl; + } + + public String getCmsPath() { + return cmsPath; + } + + public void setCmsPath(String cmsPath) { + this.cmsPath = cmsPath; + } +} diff --git a/user/src/main/java/com/user/config/SysConst.java b/user/src/main/java/com/user/config/SysConst.java new file mode 100644 index 0000000..5bf96ed --- /dev/null +++ b/user/src/main/java/com/user/config/SysConst.java @@ -0,0 +1,19 @@ +package com.user.config; + +public class SysConst { + + private static SysConfig sysConfig; + + public static void setSysConfig(SysConfig arg){ + sysConfig = arg; + } + + public static SysConfig getSysConfig(){ + if (null == sysConfig) { + //防止空指针异常 + sysConfig = new SysConfig(); + return sysConfig; + } + return sysConfig; + } +} diff --git a/user/src/main/resources/dev/application.yml b/user/src/main/resources/dev/application.yml new file mode 100644 index 0000000..b312807 --- /dev/null +++ b/user/src/main/resources/dev/application.yml @@ -0,0 +1,89 @@ +server: + port: 9504 + servlet: + context-path: /user + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/puhui_go?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql + +rocketmq: + name-server: 139.9.154.68:9876 + producer: + access-key: huifukeji + secret-key: HF123456. + #必须指定group + group: default-group + consumer: + access-key: huifukeji + secret-key: HF123456. + +jetcache: + statIntervalMinutes: 15 + areaInCacheName: false + local: + default: + type: linkedhashmap + keyConvertor: fastjson + remote: + default: + type: redis + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + keyConvertor: fastjson + broadcastChannel: projectA + valueEncoder: java + valueDecoder: java + poolConfig: + minIdle: 5 + maxIdle: 20 + maxTotal: 50 diff --git a/user/src/main/resources/dev/config.properties b/user/src/main/resources/dev/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/user/src/main/resources/dev/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/user/src/main/resources/dev/logback.xml b/user/src/main/resources/dev/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/user/src/main/resources/dev/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/user/src/main/resources/pre/application.yml b/user/src/main/resources/pre/application.yml new file mode 100644 index 0000000..874093a --- /dev/null +++ b/user/src/main/resources/pre/application.yml @@ -0,0 +1,56 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://139.9.154.68:3306/hsg_pre?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + redis: + database: 1 + host: 139.9.154.68 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/user/src/main/resources/pre/config.properties b/user/src/main/resources/pre/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/user/src/main/resources/pre/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/user/src/main/resources/pre/logback.xml b/user/src/main/resources/pre/logback.xml new file mode 100644 index 0000000..9382585 --- /dev/null +++ b/user/src/main/resources/pre/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + + diff --git a/user/src/main/resources/prod/application.yml b/user/src/main/resources/prod/application.yml new file mode 100644 index 0000000..f3e38c7 --- /dev/null +++ b/user/src/main/resources/prod/application.yml @@ -0,0 +1,57 @@ +server: + port: 9301 + servlet: + context-path: /crest + +#配置是否为debug模式,debug模式下,不开启权限校验 +debug: false + +#datasource数据源设置 +spring: + datasource: + url: jdbc:mysql://127.0.0.1:3306/hsg?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8 + username: root + password: HF123456. + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.jdbc.Driver + filters: stat + maxActive: 10 + initialSize: 5 + maxWait: 60000 + minIdle: 5 + timeBetweenEvictionRunsMillis: 60000 + minEvictableIdleTimeMillis: 300000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + + redis: + database: 0 + host: 127.0.0.1 + port: 36379 + password: HF123456.Redis + timeout: 1000 + jedis: + pool: + max-active: 20 + max-wait: -1 + max-idle: 10 + min-idle: 0 + #配置日期返回至前台为时间戳 + jackson: + serialization: + write-dates-as-timestamps: true +mybatis: + mapperLocations: + - classpath*:sqlmap*/*.xml + type-aliases-package: + org.springboot.sample.entity + +pagehelper: + helperDialect: mysql + reasonable: true + supportMethodsArguments: true + params: count=countSql diff --git a/user/src/main/resources/prod/config.properties b/user/src/main/resources/prod/config.properties new file mode 100644 index 0000000..44ea8fc --- /dev/null +++ b/user/src/main/resources/prod/config.properties @@ -0,0 +1,2 @@ +fileUrl=/home/project/hsg/filesystem +cmsPath=/home/project/hsg/filesystem/cmsPath diff --git a/user/src/main/resources/prod/logback.xml b/user/src/main/resources/prod/logback.xml new file mode 100644 index 0000000..e509de0 --- /dev/null +++ b/user/src/main/resources/prod/logback.xml @@ -0,0 +1,72 @@ + + + + + %d %p (%file:%line\)- %m%n + UTF-8 + + + + log/base.log + + log/base.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/dao.log + + log/dao.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + log/error.log + + log/error.log.%d.%i + + + 64 MB + + + + + %d %p (%file:%line\)- %m%n + + UTF-8 + + + + + + + + + + + + + + +