diff --git a/neuray-pm-base-server/base-dfsfile-client/pom.xml b/neuray-pm-base-server/base-dfsfile-client/pom.xml index 4267c6adee309b95dfaab081002651d27ce6137b..63f3a312c690cd674264491032bb72b92d0d9f48 100644 --- a/neuray-pm-base-server/base-dfsfile-client/pom.xml +++ b/neuray-pm-base-server/base-dfsfile-client/pom.xml @@ -26,9 +26,15 @@ - + + + + org.springframework.cloud + spring-cloud-starter-alibaba-nacos-discovery + ${alibaba.nacos.version} com.gitee.neuray.security diff --git a/neuray-pm-base-server/base-dfsfile-client/src/main/java/com/gitee/neuray/security/file/rpc/FastDfsRpc.java b/neuray-pm-base-server/base-dfsfile-client/src/main/java/com/gitee/neuray/security/file/rpc/FastDfsRpc.java new file mode 100644 index 0000000000000000000000000000000000000000..ecd476aeffbf033291dcd7170fd2aeb9e9da4c9b --- /dev/null +++ b/neuray-pm-base-server/base-dfsfile-client/src/main/java/com/gitee/neuray/security/file/rpc/FastDfsRpc.java @@ -0,0 +1,384 @@ +package com.gitee.neuray.security.file.rpc; + +import com.gitee.neuray.security.auth.client.annotation.IgnoreUserToken; +import com.gitee.neuray.security.common.exception.BaseException; +import com.gitee.neuray.security.common.msg.ObjectRestResponse; +import com.gitee.neuray.security.common.msg.TableResultResponse; +import com.gitee.neuray.security.common.rest.BaseController; +import com.gitee.neuray.security.common.util.Query; +import com.gitee.neuray.security.common.util.UUIDUtils; +import com.gitee.neuray.security.file.biz.FileInfoBiz; +import com.gitee.neuray.security.file.contants.FileContants; +import com.gitee.neuray.security.file.entity.FileInfoEntity; +import com.gitee.neuray.security.file.jwt.FileJwtInfo; +import com.gitee.neuray.security.file.util.FastDFSClientWrapper; +import com.gitee.neuray.security.file.util.FileTypeEnum; +import com.gitee.neuray.security.file.vo.FileInfoVO; +import com.gitee.neuray.security.file.vo.JwtInfoVO; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; +import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Map; + +/** + * file文件接口 + * + * @author zhhongyu + * @since 2019-06-18 + */ +@Slf4j +@RestController +@RequestMapping("/fdfs/rpc") +public class FastDfsRpc extends BaseController { + @Autowired + private FastDFSClientWrapper dfsClient; + @Autowired + private FileJwtInfo fileJwtInfo; + + +// @PostMapping("/upload") +// @ResponseBody +// public ObjectRestResponse upload(@RequestParam("file") MultipartFile file) throws Exception { +// String imgUrl = dfsClient.uploadFile(file); +// return new ObjectRestResponse<>().data(imgUrl).rel(true); +// } + + /** + * todo:使用 + * 上传接口 + * + * @param file file文件 + * @return 文件访问路径 + * @throws Exception + */ + @PostMapping("/upload") + @ResponseBody + public ObjectRestResponse upload(@RequestParam("file") MultipartFile file) throws Exception { + com.gitee.neuray.security.common.vo.FileInfoVO fileInfoVO = baseBiz.uploadFile(file); + return new ObjectRestResponse<>().data(fileInfoVO).rel(true); + } + +// @PostMapping("/sensitiveUpload") +// @ResponseBody +// public ObjectRestResponse uploadSensitiveFile(@RequestParam("file") MultipartFile file) throws Exception { +// String imgUrl = dfsClient.uploadSensitiveFile(file); +// return new ObjectRestResponse<>().data(imgUrl).rel(true); +// } + + /** + * 上传加密文件接口(base64加密方式) + * + * @param file file文件 + * @return 文件访问路径 + * @throws Exception + */ + @PostMapping("/sensitiveUpload") + @ResponseBody + public ObjectRestResponse uploadChiperSensitiveFile(@RequestParam("file") MultipartFile file) throws Exception { + //使用base64进行加密 + com.gitee.neuray.security.common.vo.FileInfoVO fileInforVO = baseBiz.uploadSensitiveFile(file, FileContants.SENSITIVE_CIPHER_TYPE); + return new ObjectRestResponse<>().data(fileInforVO).rel(true); + } + + /** + * 采用位移加密方式上传文件接口 + * + * @param file + * @return + * @throws Exception + */ + @PostMapping("/sensitiveUpload2") + @ResponseBody + public ObjectRestResponse uploadByteMoveSensitiveFile(@RequestParam("file") MultipartFile file) throws Exception { + //使用base64进行加密 + com.gitee.neuray.security.common.vo.FileInfoVO fileInfoVO = baseBiz.uploadSensitiveFile(file, FileContants.SENSITIVE_BYTEMOVE_TYPE); + return new ObjectRestResponse<>().data(fileInfoVO).rel(true); + } + + /** + * 删除文件接口 + * + * @param fileId 文件id + * @return + * @throws Exception + */ + @RequestMapping(value = "delete", method = RequestMethod.DELETE) + @ResponseBody + public ObjectRestResponse removeFile(@RequestParam String fileId) throws Exception { + baseBiz.deleteFile(fileId); + return new ObjectRestResponse<>().rel(true); + } + + /** + * 文件下载(普通文件下载,没有加密) + * + * @param fileId 文件id + * @param response + * @throws Exception + */ + @GetMapping("/download") + public void download(@RequestParam String fileId, HttpServletResponse response) throws Exception { + Map stringObjectMap = baseBiz.downLoadFile(fileId, FileContants.NO_SENSITIVE_TYPE); + String fileName = (String) stringObjectMap.get("fileName"); + byte[] data = (byte[]) stringObjectMap.get("fileByte"); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); + ServletOutputStream outputStream = response.getOutputStream(); + IOUtils.write(data, outputStream); + } + + /** + * 下载加密文件(文件流加密) + * todo:使用 + * @param fileId + * @param response + * @throws Exception + */ + @GetMapping("/sensitiveDownload") + public void downloadChiperSensitiveFile(@RequestParam String fileId, HttpServletResponse response) throws Exception { + Map stringObjectMap = baseBiz.downLoadFile(fileId, FileContants.SENSITIVE_CIPHER_TYPE); + String fileName = (String) stringObjectMap.get("fileName"); + byte[] data = (byte[]) stringObjectMap.get("fileByte"); + response.setHeader("Content-Length",data.length+""); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); + ServletOutputStream outputStream = response.getOutputStream(); + IOUtils.write(data, outputStream); + } + + /** + * 下载加密文件(位移加密下载) + * + * @param fileId + * @param response + * @throws Exception + */ + @GetMapping("/sensitiveDownload2") + public void downloadByteMoveSensitiveFile(@RequestParam String fileId, HttpServletResponse response) throws Exception { + Map stringObjectMap = baseBiz.downLoadFile(fileId, FileContants.SENSITIVE_BYTEMOVE_TYPE); + String fileName = (String) stringObjectMap.get("fileName"); + byte[] data = (byte[]) stringObjectMap.get("fileByte"); + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); + ServletOutputStream outputStream = response.getOutputStream(); + IOUtils.write(data, outputStream); + } + + /** + * 图片展示接口(无加密图片) + * + * @param fileId + * @param response + * @throws IOException + */ + @RequestMapping("/getImage") + public void getFile(@RequestParam String fileId, HttpServletResponse response) throws IOException { + baseBiz.getImg(fileId, response, FileContants.NO_SENSITIVE_TYPE); + } + + /** + * todo:使用 + * 加密图片展示(文件流加密) + * + * @param fileId + * @param response + * @throws IOException + */ + @RequestMapping("/getSensitiveImage") + @IgnoreUserToken + public void getSensitiveImage(@RequestParam String fileId, HttpServletResponse response) throws IOException { + baseBiz.getImg(fileId, response, FileContants.SENSITIVE_CIPHER_TYPE); + } + + /** + * 加密图片展示(位移加密图片) + * + * @param fileId + * @param response + * @throws IOException + */ + @RequestMapping("/getSensitiveImage2") + public void getSensitiveImage2(@RequestParam String fileId, HttpServletResponse response) throws IOException { + baseBiz.getImg(fileId, response, FileContants.SENSITIVE_BYTEMOVE_TYPE); + } + + @PostMapping("/thumbImage") + @ResponseBody + public ObjectRestResponse crtThumbImage(@RequestParam("file") MultipartFile file) throws Exception { + String imgUrl = dfsClient.crtThumbImage(file); + return new ObjectRestResponse<>().data(imgUrl).rel(true); + } + + /** + * 分页获取文件列表,该接口包含path文件服务器路径,page接口不包含文件服务器路径 + * @param params + * @return + */ + @RequestMapping(value = "pageList",method = RequestMethod.GET) + @ResponseBody + public TableResultResponse pageList(@RequestParam Map params) { + //查询列表数据 + Query query = new Query(params); + return baseBiz.page(query); + } + + /** + * todo:使用 + * 文件分块上传接口(0到n-1块文件位数必须为8的倍数,最后一块文件可为任意) + * 下载这种文件时需要采用文件流加密下载接口,文件分块不能做秒传功能,因为不能确定唯一文件性 + * + * @param file 文件 + * @return 最后一块文件时返回文件基本信息实体,供前端使用 + * @throws Exception + */ + @ResponseBody + @RequestMapping(value = "/appendUploadFile",method = RequestMethod.POST) + @HystrixCommand( + fallbackMethod = "uploadAppendFileFallback", + threadPoolProperties = { + @HystrixProperty(name = "coreSize", value = "50"), + @HystrixProperty(name = "maxQueueSize", value = "500"), + @HystrixProperty(name = "queueSizeRejectionThreshold", value = "20")}, + commandProperties = { + @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "30000"), + @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "20") + }, + ignoreExceptions = BaseException.class + ) + public ObjectRestResponse uploadAppendFile(@RequestParam("file") MultipartFile file,HttpServletRequest request + ) throws Exception { + String currentNo = request.getHeader("currentNo"); + String totalSize = request.getHeader("totalSize"); + String key = request.getHeader("key"); + String fileName = request.getHeader("fileName"); + String fileSize = request.getHeader("fileSize"); + String levels = request.getHeader("levels"); + if (StringUtils.isEmpty(currentNo)) { + throw new BaseException("当前段数不能为空..."); + } + if (StringUtils.isEmpty(totalSize)) { + throw new BaseException("总段数不能为空..."); + } + if (StringUtils.isEmpty(key)) { + throw new BaseException("文件唯一性不能为空..."); + } + if (file == null || file.getBytes() == null) { + throw new BaseException("文件不能为空..."); + } + if (StringUtils.isEmpty(fileName)) { + throw new BaseException("文件名不能为空..."); + } + if (StringUtils.isEmpty(fileSize)) { + throw new BaseException("文件大小不能为空..."); + } + if(StringUtils.isEmpty(levels)){ + throw new BaseException("文件密级不能为空..."); + } + currentNo = URLDecoder.decode(currentNo, "UTF-8"); + totalSize = URLDecoder.decode(totalSize, "UTF-8"); + key = URLDecoder.decode(key, "UTF-8"); + fileName = URLDecoder.decode(fileName, "UTF-8"); + fileSize = URLDecoder.decode(fileSize, "UTF-8"); + log.info("接收到文件{}开始...", fileName); + FileInfoEntity fileInfoEntity = null; + JwtInfoVO jwtInfoVO = fileJwtInfo.getJwtInfoVO(request); + fileInfoEntity = this.transferFileInfo(fileName, Double.valueOf(fileSize),levels, jwtInfoVO); + //文件分块上传,加密方式采用文件流加密 + com.gitee.neuray.security.common.vo.FileInfoVO fileInfoVO = baseBiz.uploadAppendSensitiveFile(file, key, currentNo, totalSize, fileInfoEntity, jwtInfoVO); + fileInfoVO.setFileSize(Double.valueOf(fileSize)); + log.info("文件{}上传完成",fileName); + return new ObjectRestResponse().data(fileInfoVO).rel(true); + } + + public ObjectRestResponse uploadAppendFileFallback( MultipartFile file, + HttpServletRequest request, + Throwable throwable + ) throws Exception { + ObjectRestResponse result = new ObjectRestResponse(); + result.setStatus(503); + result.setMessage("服务忙...稍后重试"); + return result; + } + + /** + * 上传默认头像接口 + * @param file + * @return + * @throws Exception + */ + @PostMapping("/defaultAvator") + @ResponseBody + public ObjectRestResponse uploadDefaultAvator(@RequestParam("file") MultipartFile file) throws Exception { + com.gitee.neuray.security.common.vo.FileInfoVO fileInfoVO = baseBiz.uploadDefaultAvator(file); + return new ObjectRestResponse<>().data(fileInfoVO).rel(true); + } + + /** + * 分页获取默认头像接口 + * @param params + * @return + */ + @RequestMapping(value = "defaultAvatorPageList",method = RequestMethod.GET) + @ResponseBody + public TableResultResponse defaultAvatorPageList(@RequestParam Map params) { + //查询列表数据 + Query query = new Query(params); + return baseBiz.defaultAvatorPageList(query); + } + + private FileInfoEntity transferFileInfo(String fileName, Double fileSize,String levels, JwtInfoVO jwtInfoVO) throws Exception { + FileInfoEntity fileInfoEntity = new FileInfoEntity(); + fileInfoEntity.setId(UUIDUtils.generateShortUuid()); + if (jwtInfoVO != null) { + BeanUtils.copyProperties(jwtInfoVO, fileInfoEntity); + } + String suffix = ""; + String fileExt = ""; + String regixValue = FileContants.FILE_REGIX_VALUE; + if (fileName.indexOf(regixValue) != -1) { + suffix = fileName.substring(fileName.lastIndexOf(regixValue)); + fileName = fileName.substring(0, fileName.lastIndexOf(regixValue)); + } + if (!"".equals(suffix) && !regixValue.equals(suffix)) { + fileExt = suffix.substring(suffix.indexOf(regixValue) + 1); + } + fileInfoEntity.setFileExt(fileExt); + fileInfoEntity.setFileName(fileName); + String fileType = ""; + FileTypeEnum fileTypeEnum = FileTypeEnum.getEnumByValue(fileExt); + fileType = fileTypeEnum.getType(); + fileInfoEntity.setFileType(fileType.toLowerCase()); + fileInfoEntity.setFileSize(fileSize); + fileInfoEntity.setStatus(FileContants.EFECTIVE_FILE); + fileInfoEntity.setLevels(levels); + return fileInfoEntity; + } + + /** + * 文件模板下载(普通文件下载,没有加密) + * + * @param fileId 文件id + * @param response + * @throws Exception + */ + @GetMapping("/downloadModel") + public byte[] downloadModel(@RequestParam String fileId, HttpServletResponse response) throws Exception { + Map stringObjectMap = baseBiz.downLoadFile(fileId, FileContants.NO_SENSITIVE_TYPE); + String fileName = (String) stringObjectMap.get("fileName"); + byte[] data = (byte[]) stringObjectMap.get("fileByte"); + return data; + } +} diff --git a/neuray-pm-base-server/base-dfsfile-client/src/main/resources/application.yml b/neuray-pm-base-server/base-dfsfile-client/src/main/resources/application.yml index f9c2caa71788a7a4b36018e0ca0e9e0af79bbb69..551bdf001366241a1cdd4f89d1ab4015dec48d29 100644 --- a/neuray-pm-base-server/base-dfsfile-client/src/main/resources/application.yml +++ b/neuray-pm-base-server/base-dfsfile-client/src/main/resources/application.yml @@ -38,18 +38,18 @@ server: port: 8771 profiles: active: dev -#eruka注册中心 -eureka: - ###docker部署开启 - instance: - prefer-ip-address: true - client: - service-url: - defaultZone: http://${EUREKA_HOST:192.168.1.205}:${EUREKA_PORT:8070}/eureka/ - ###向注册中心上注册自己 - register-with-eureka: true - ###是否需要从eureka上获取注册信息 - fetch-registry: true +##eruka注册中心 +#eureka: +# ###docker部署开启 +# instance: +# prefer-ip-address: true +# client: +# service-url: +# defaultZone: http://${EUREKA_HOST:192.168.1.205}:${EUREKA_PORT:8070}/eureka/ +# ###向注册中心上注册自己 +# register-with-eureka: true +# ###是否需要从eureka上获取注册信息 +# fetch-registry: true ###fastdfs配置 diff --git a/neuray-pm-base-server/base-dfsfile-client/src/main/resources/bootstrap.yml b/neuray-pm-base-server/base-dfsfile-client/src/main/resources/bootstrap.yml new file mode 100644 index 0000000000000000000000000000000000000000..c0db3972799c61c5fe2c71d561b1e3342c9e94b0 --- /dev/null +++ b/neuray-pm-base-server/base-dfsfile-client/src/main/resources/bootstrap.yml @@ -0,0 +1,11 @@ +server: + port: 8771 +spring: + application: + name: base-dfsfile + cloud: + nacos: + discovery: + server-addr: 127.0.0.1:8848 + + diff --git a/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/StaffBiz.java b/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/StaffBiz.java index c0bedb01c91d640bddcb62f7cff7007308e687e8..d04af0ccbcdaf64fae11636843b8acbfce064e22 100644 --- a/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/StaffBiz.java +++ b/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/StaffBiz.java @@ -133,11 +133,13 @@ public class StaffBiz extends BaseBiz { String state = map.get("state").toString(); //微信企业号AccessToken - AccessToken accessToken = wechatBiz.getAccessToken(); + AccessToken accessToken = wechatBiz.getAccessToken(state); String token = accessToken.getAccessToken(); //微信企业号人员信息 UserInfo userInfo = wechatBiz.getUserInfo(code,token); + + //微信用户id String userId = userInfo.getUserId(); Map ret = new HashMap<>(); @@ -147,6 +149,27 @@ public class StaffBiz extends BaseBiz { return map; } + //微信userId即为电话号,通过其获取数据库中staff相关成员信息 + StaffVo staffParam = new StaffVo(); + staffParam.setPhone(userId); + //如果存在两个人公用同一手机号,只取一条。 + List staffVos = staffMapper.select(staffParam); + + StaffVo staffVo = staffVos.get(0); + + Map staffInfo = new HashMap<>(); + staffInfo.put("phone",userId); + staffInfo.put("name",staffVo.getName()); + staffInfo.put("deptCode",staffVo.getDeptCode()); + staffInfo.put("account",staffVo.getAccout()); + staffInfo.put("email",staffVo.getEmail()); + staffInfo.put("sfzdz",staffVo.getSfzdz()); + staffInfo.put("zzzt",staffVo.getZzzt()); + staffInfo.put("id",staffVo.getId()); + + map.put("staffInfo", staffInfo); + map.put("wxUserId",userId); + map.put("wxAccessToken",accessToken); map.put("msg","success"); return map; diff --git a/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/WechatBiz.java b/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/WechatBiz.java index 8ad5afde195acb1515e7811271ad8f3a69c337bb..1dd4550070be4b8ded047b31812c07795d18a70d 100644 --- a/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/WechatBiz.java +++ b/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/staff/biz/WechatBiz.java @@ -31,7 +31,7 @@ public class WechatBiz { * * @return */ - public AccessToken getAccessToken() { + public AccessToken getAccessToken(String state) { AccessToken accessToken = new AccessToken(); @@ -44,8 +44,15 @@ public class WechatBiz { //如果不存在调用微信企业号获取accesstoken接口,获取token CloseableHttpClient client = HttpUtil.getHttpClient(); + //todo 不同应用使用不同的应用密钥,根据自定义参数state获取 + String corpSecret = ""; + if("wb".equals(state)){ + corpSecret = Dictionary.WB_CORPSECRET; + }else{ + corpSecret = Dictionary.CORPSECRET; + } HttpGet request = new HttpGet(String.format(Dictionary.GET_ACCESS_TOKEN_URL, Dictionary.CORPID, - Dictionary.CORPSECRET)); + corpSecret)); try (CloseableHttpResponse response = client.execute(request)) { String responseContent = new BasicResponseHandler().handleResponse(response); WechatError error = JSONObject.parseObject(responseContent, WechatError.class); diff --git a/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/util/wechat/Dictionary.java b/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/util/wechat/Dictionary.java index 3949714638e6c8ed8886094f0f1259278d0d4328..d45de6246270d81073c3247112ae64fb4edff4ca 100644 --- a/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/util/wechat/Dictionary.java +++ b/neuray-pm-provider/neuray-pm-provider-admin/src/main/java/com/gitee/neuray/security/admin/util/wechat/Dictionary.java @@ -16,4 +16,9 @@ public class Dictionary { public static final String CORPID = "wwacc92a7b917bf282"; public static final String CORPSECRET = "eKGSa6CpPbKBm_aA-hYrmUsGoeCf8C8_cNIwJcinR8c"; + + /** 网报应用id */ + public static final String WB_AGENT_ID = "1000010"; + + public static final String WB_CORPSECRET = "LdDobcWFWN6pYxbUJZvc8ZAzj9otWkbfoLgKisQWd1g"; } diff --git a/neuray-pm-provider/neuray-pm-provider-wb/pom.xml b/neuray-pm-provider/neuray-pm-provider-wb/pom.xml index 3be06ac4b8bbd81013a92edb9496b094cea06e85..578cd9c149899e6f93b2a8a54ef0f4651572b9c9 100644 --- a/neuray-pm-provider/neuray-pm-provider-wb/pom.xml +++ b/neuray-pm-provider/neuray-pm-provider-wb/pom.xml @@ -12,7 +12,7 @@ neuray-pm-provider-wb - 1.8 + 1.8 @@ -67,6 +67,12 @@ org.springframework.cloud spring-cloud-starter-openfeign + + + httpclient + org.apache.httpcomponents + + org.springframework.cloud @@ -133,6 +139,12 @@ log4j 1.2.17 + + + org.apache.httpcomponents + httpmime + 4.5.5 + diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/NeurayPmWbApplication.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/NeurayPmWbApplication.java index ff30b200beae6926549e7d6aa5463cfc51ccf2e4..3c43faa52565c79d74dafc62cb16012b18860361 100644 --- a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/NeurayPmWbApplication.java +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/NeurayPmWbApplication.java @@ -7,6 +7,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -18,6 +19,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; @MapperScan("com.gitee.neuray.security.wb.*.mapper") @EnableSwagger2Doc @ServletComponentScan +@EnableFeignClients({"com.gitee.neuray.security.wb.ribs.feign"}) public class NeurayPmWbApplication { public static void main(String[] args) { diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/biz/WechatBiz.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/biz/WechatBiz.java new file mode 100644 index 0000000000000000000000000000000000000000..584ceb420bcc907eaf13aacf707e0f760e448b22 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/biz/WechatBiz.java @@ -0,0 +1,222 @@ +package com.gitee.neuray.security.wb.ribs.biz; + +import com.ace.cache.api.impl.CacheRedis; +import com.alibaba.fastjson.JSONObject; +import com.gitee.neuray.security.common.util.UUIDUtils; +import com.gitee.neuray.security.wb.ribs.constants.WbApiConstants; +import com.gitee.neuray.security.wb.ribs.feign.FileFeign; +import com.gitee.neuray.security.wb.ribs.util.wechat.Dictionary; +import com.gitee.neuray.security.wb.ribs.util.wechat.HttpUtil; +import com.gitee.neuray.security.wb.ribs.util.wechat.entity.*; +import org.apache.http.HttpEntity; +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.entity.StringEntity; +import org.apache.http.entity.mime.HttpMultipartMode; +import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.BasicResponseHandler; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.log4j.Logger; +import org.apache.poi.hssf.usermodel.HSSFRow; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.io.*; +import java.util.HashMap; +import java.util.Map; + +/** + * 微信企业号服务层 + */ +@Service +public class WechatBiz { + + private static Logger logger = Logger.getLogger(WechatBiz.class); + + @Autowired + private FileFeign fileFeign; + + /** + * 上传文件至微信服务,注意,文件仅保存3天 + * + * @return + */ + public MediaUploadInfo mediaUpload(String accessToken,String type,HttpServletRequest request,Map staff,XSSFWorkbook wb,String userId) throws IOException{ + + userId = "15040023164"; + + MediaUploadInfo mediaUploadInfo = new MediaUploadInfo(); + + + CloseableHttpClient clients = HttpUtil.getHttpClient(); + HttpPost requests = new HttpPost(String.format(Dictionary.MEDIA_UPLOAD_URL, accessToken, "file")); + + ByteArrayOutputStream boss=new ByteArrayOutputStream(); + wb.write(boss); + byte[] barray=boss.toByteArray(); + InputStream is=new ByteArrayInputStream(barray); + //todo 创建文件夹 临时文件 + String savePath = request.getServletContext().getRealPath("/temp"); + //String savePath = "D://temp"; + File tmpDir = new File(savePath); + String fileWriteTime = UUIDUtils.generateShortUuid(); + // 判断上传文件的保存目录是否存在 + if (!tmpDir.exists() && !tmpDir.isDirectory()) + { + //tmpDir.createNewFile(); + logger.debug(savePath + "目录不存在,需要创建。"); + + // 创建目录 + tmpDir.mkdir(); + } + File fileTemp = new File(savePath + File.separator + fileWriteTime + ".xlsx"); + FileOutputStream fileOutputStream = new FileOutputStream(fileTemp); + //将 下载wb的inputStream 通过FileOutputStream写入临时文件 + byte[] b = new byte[1024]; + int n; + while ((n = is.read(b)) != -1) + { + fileOutputStream.write(b, 0, n); + } + //================================================= + //设置请求参数,把文件上传给微信端 + FileBody bin = new FileBody(fileTemp); + HttpEntity reqEntity = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE) + .addPart("media",bin) + .build(); + + requests.setEntity(reqEntity); + + try (CloseableHttpResponse response = clients.execute(requests)) { + String responseContent = new BasicResponseHandler().handleResponse(response); + WechatError error = JSONObject.parseObject(responseContent, WechatError.class); + if (error.getErrCode() != 0) { + throw new Exception(error.toString()); + } + mediaUploadInfo = JSONObject.parseObject(responseContent, MediaUploadInfo.class); + //删除临时文件 + fileTemp.delete(); + logger.info(mediaUploadInfo.getMediaId()); + //调用发送文件 + SendMsgInfo sendMsgInfo = this.sendMsg(accessToken,userId,mediaUploadInfo.getMediaId()); + return mediaUploadInfo; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public SendMsgInfo sendMsg(String accessToken,String userId,String mediaId){ + SendMsgInfo sendMsgInfo = new SendMsgInfo(); + + //如果不存在调用微信企业号获取accesstoken接口,获取token + CloseableHttpClient clients = HttpUtil.getHttpClient(); + HttpPost requests = new HttpPost(String.format(Dictionary.SEND_MSG_URL, accessToken)); + + //发送微信消息必要参数 其中 touser、toparty、totag三者不能全为空 + JSONObject mapParam = new JSONObject(); + mapParam.put("touser",userId); //接收用户id 使用|分隔 + mapParam.put("toparty",""); //部门id 使用|分隔 + mapParam.put("totag",""); //标签id 使用|分隔 + mapParam.put("msgtype","file"); //固定为file 其他见官网api + mapParam.put("agentid",Dictionary.WB_AGENT_ID); //企业应用id,可在企业微信应用设置页面查看 + mapParam.put("safe",0); //是否为保密 0是 + mapParam.put("enable_duplicate_check",0); //是否开启重复消息检查 0是 + mapParam.put("duplicate_check_interval",1800); //重复消息检查间隔 1800s 最大不超过4小时 + JSONObject fileParam = new JSONObject(); + fileParam.put("media_id",mediaId); //微信服务文件id + mapParam.put("file",fileParam); + + requests.setEntity(new StringEntity(JSONObject.toJSONString(mapParam), "utf-8")); + + //requests.setHeader("Content-Type", contentType); + + try (CloseableHttpResponse response = clients.execute(requests)) { + String responseContent = new BasicResponseHandler().handleResponse(response); + WechatError error = JSONObject.parseObject(responseContent, WechatError.class); + if (error.getErrCode() != 0) { + throw new Exception(error.toString()); + } + sendMsgInfo = JSONObject.parseObject(responseContent, SendMsgInfo.class); + + logger.info(sendMsgInfo.getInvaliduser()); + return sendMsgInfo; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + //public void excelAndSend(String accessToken,String type,HttpServletRequest request,Map staff,String userId) throws IOException{ + public void excelAndSend(Map map,String type,HttpServletRequest request) throws IOException{ + String accessToken = map.get("accessToken").toString(); + String userId = map.get("wxUserId").toString(); + String staffMapStr = JSONObject.toJSONString(map.get("staffInfo")); + + String ids = map.get("ids").toString(); + //todo 根据id获取对应的报销类型 + String[] idsArr = ids.split(","); + + Map staff = JSONObject.parseObject(staffMapStr,Map.class); + byte[] res = fileFeign.downloadModel(WbApiConstants.FILE_ID); + InputStream sbs = new ByteArrayInputStream(res); + + //读取excel模板 + XSSFWorkbook wb = new XSSFWorkbook(sbs); + XSSFSheet fkdSheet = wb.getSheetAt(1); + XSSFSheet jtfSheet = wb.getSheetAt(2); + XSSFSheet cyfSheet = wb.getSheetAt(3); + XSSFSheet clfSheet = wb.getSheetAt(4); + + /*//交通费 + if("jtf".equals(type)){ + jtfSheet(jtfSheet); + }*/ + + + //处理市内交通费 + //jtfSheet.getRow(); + + //处理餐饮费 + + //处理差旅费 + + //处理付款单 + + + //将excel转为字节 + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + wb.write(bos); + } finally { + bos.close(); + } + byte[] bytes = bos.toByteArray(); + + //todo 处理完excel上传至微信服务端 + this.mediaUpload(accessToken,type,request,staff,wb,userId); + + } + + public XSSFSheet jtfSheet(XSSFSheet jtfSheet,Map map){ + + for (Row row : jtfSheet){ + for(Cell cell : row){ + + } + } + + return null; + + } + +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/constants/WbApiConstants.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/constants/WbApiConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..9fef82dd83c3afca57990192a11389be261fedc6 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/constants/WbApiConstants.java @@ -0,0 +1,11 @@ +package com.gitee.neuray.security.wb.ribs.constants; + +/** + * @auther: liwd + * @date: 2020/5/11 15:28 + * @description: 网报常量 + */ +public final class WbApiConstants { + public static final String DFSFILE_ADDRESS = "base-dfsfile"; + public static final String FILE_ID = "b00mzVxm"; +} \ No newline at end of file diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/controller/RibsController.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/controller/RibsController.java index 4a14350f6b4f93e15280f18d1473699e3a894a84..254eefc7943e0914cadae78b1656ec9bcc55043f 100644 --- a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/controller/RibsController.java +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/controller/RibsController.java @@ -6,17 +6,16 @@ import com.gitee.neuray.security.common.msg.ObjectRestResponse; import com.gitee.neuray.security.common.msg.TableResultResponse; import com.gitee.neuray.security.common.util.ExcelUtils; import com.gitee.neuray.security.common.util.Query; -import com.gitee.neuray.security.wb.ribs.biz.ClfBiz; -import com.gitee.neuray.security.wb.ribs.biz.CyfBiz; -import com.gitee.neuray.security.wb.ribs.biz.JtfBiz; -import com.gitee.neuray.security.wb.ribs.biz.RibsBiz; +import com.gitee.neuray.security.wb.ribs.biz.*; import com.gitee.neuray.security.wb.ribs.vo.ClfVo; import com.gitee.neuray.security.wb.ribs.vo.RibsPageExcelVo; import com.gitee.neuray.security.wb.ribs.vo.RibsVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -34,6 +33,7 @@ public class RibsController { @Autowired private ClfBiz clfBiz; @Autowired private CyfBiz cyfBiz; @Autowired private JtfBiz jtfBiz; + @Autowired private WechatBiz wechatBiz; /** * 分页获取列表 @@ -54,7 +54,12 @@ public class RibsController { * @return */ @RequestMapping(value = "commitClf", method = RequestMethod.POST) - public ObjectRestResponse commitClf(@RequestBody RibsVo ribsVo) { + public ObjectRestResponse commitClf(@RequestBody Map map, HttpServletRequest request) { + + RibsVo ribsVo = JSONObject.parseObject(JSONObject.toJSONString(map.get("ribsVo")),RibsVo.class); + Map wechatInfo = JSONObject.parseObject(JSONObject.toJSONString(map.get("staffInfo")),Map.class); + wechatInfo.put("ids",ribsVo.getIds()); + // 生成报销单号 String bxdh = createBxdh("CLY"); // 修改子表差旅费状态为提交,修改报销单号 @@ -69,6 +74,13 @@ public class RibsController { ribsVo.setIds(null); ribsVo.setBxdh(bxdh); ribsBiz.commitClf(ribsVo); + + try { + wechatBiz.excelAndSend(wechatInfo,"clf",request); + } catch (IOException e) { + e.printStackTrace(); + } + return new ObjectRestResponse().rel(true); } /** diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/feign/FileFeign.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/feign/FileFeign.java new file mode 100644 index 0000000000000000000000000000000000000000..d972a1790c1bd208e214436e55cc7fdce3ea37aa --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/feign/FileFeign.java @@ -0,0 +1,16 @@ +package com.gitee.neuray.security.wb.ribs.feign; +import com.gitee.neuray.security.common.msg.ObjectRestResponse; +import com.gitee.neuray.security.wb.ribs.constants.WbApiConstants; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import java.util.List; + +@FeignClient(value = WbApiConstants.DFSFILE_ADDRESS,configuration = {}) +public interface FileFeign { + @RequestMapping(value = "/fdfs/rpc/downloadModel",method = RequestMethod.GET) + byte[] downloadModel(@RequestParam("fileId") String fileId); + @RequestMapping(value = "/fdfs/rpc/download",method = RequestMethod.GET) + void download(@RequestParam("fileId") String fileId); +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/MoneyUtil.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/MoneyUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..1d994c09b767e84a82fd24a052758d81ecd09bce --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/MoneyUtil.java @@ -0,0 +1,134 @@ +package com.gitee.neuray.security.wb.ribs.util; + +public class MoneyUtil { + + /** 大写数字 */ + private static final String[] NUMBERS = { "零", "壹", "贰", "叁", "肆", "伍", + "陆", "柒", "捌", "玖" }; + + /** 整数部分的单位 */ + private static final String[] IUNIT = { "元", "拾", "佰", "仟", "万", "拾", "佰", + "仟", "亿", "拾", "佰", "仟", "万", "拾", "佰", "仟" }; + + /** 小数部分的单位 */ + private static final String[] DUNIT = { "角", "分", "厘" }; + + /** + * 得到大写金额。 + */ + public static String toChinese(String str) { + str = str.replaceAll(",", "");// 去掉"," + String integerStr;// 整数部分数字 + String decimalStr;// 小数部分数字 + // 初始化:分离整数部分和小数部分 + if (str.indexOf(".") > 0) { + integerStr = str.substring(0, str.indexOf(".")); + decimalStr = str.substring(str.indexOf(".") + 1); + } else if (str.indexOf(".") == 0) { + integerStr = ""; + decimalStr = str.substring(1); + } else { + integerStr = str; + decimalStr = ""; + } + // integerStr去掉首0,不必去掉decimalStr的尾0(超出部分舍去) + if (!integerStr.equals("")) { + integerStr = Long.toString(Long.parseLong(integerStr)); + if (integerStr.equals("0")) { + integerStr = ""; + } + } + // overflow超出处理能力,直接返回 + if (integerStr.length() > IUNIT.length) { + System.out.println(str + ":超出处理能力"); + return str; + } + + int[] integers = toArray(integerStr);// 整数部分数字 + boolean isMust5 = isMust5(integerStr);// 设置万单位 + int[] decimals = toArray(decimalStr);// 小数部分数字 + return getChineseInteger(integers, isMust5) + + getChineseDecimal(decimals); + } + + /** + * 整数部分和小数部分转换为数组,从高位至低位 + */ + private static int[] toArray(String number) { + int[] array = new int[number.length()]; + for (int i = 0; i < number.length(); i++) { + array[i] = Integer.parseInt(number.substring(i, i + 1)); + } + return array; + } + + /** + * 得到中文金额的整数部分。 + */ + private static String getChineseInteger(int[] integers, boolean isMust5) { + StringBuffer chineseInteger = new StringBuffer(""); + int length = integers.length; + for (int i = 0; i < length; i++) { + // 0出现在关键位置:1234(万)5678(亿)9012(万)3456(元) + // 特殊情况:10(拾元、壹拾元、壹拾万元、拾万元) + String key = ""; + if (integers[i] == 0) { + if ((length - i) == 13)// 万(亿)(必填) + key = IUNIT[4]; + else if ((length - i) == 9)// 亿(必填) + key = IUNIT[8]; + else if ((length - i) == 5 && isMust5)// 万(不必填) + key = IUNIT[4]; + else if ((length - i) == 1)// 元(必填) + key = IUNIT[0]; + // 0遇非0时补零,不包含最后一位 + if ((length - i) > 1 && integers[i + 1] != 0) + key += NUMBERS[0]; + } + chineseInteger.append(integers[i] == 0 ? key + : (NUMBERS[integers[i]] + IUNIT[length - i - 1])); + } + return chineseInteger.toString(); + } + + /** + * 得到中文金额的小数部分。 + */ + private static String getChineseDecimal(int[] decimals) { + StringBuffer chineseDecimal = new StringBuffer(""); + for (int i = 0; i < decimals.length; i++) { + // 舍去3位小数之后的 + if (i == 3) + break; + chineseDecimal.append(decimals[i] == 0 ? "" + : (NUMBERS[decimals[i]] + DUNIT[i])); + } + return chineseDecimal.toString(); + } + + /** + * 判断第5位数字的单位"万"是否应加。 + */ + private static boolean isMust5(String integerStr) { + int length = integerStr.length(); + if (length > 4) { + String subInteger = ""; + if (length > 8) { + // 取得从低位数,第5到第8位的字串 + subInteger = integerStr.substring(length - 8, length - 4); + } else { + subInteger = integerStr.substring(0, length - 4); + } + return Integer.parseInt(subInteger) > 0; + } else { + return false; + } + } + + public static void main(String[] args) { + MoneyUtil moneyUtil = new MoneyUtil(); + System.out.println(moneyUtil.toChinese("1234")); + } + + +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/PoiUtil.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/PoiUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..329c0dbfd0d64444c21a892399d4264c0f8fc97c --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/PoiUtil.java @@ -0,0 +1,119 @@ +package com.gitee.neuray.security.wb.ribs.util; + +import com.gitee.neuray.security.common.util.UUIDUtils; +import org.apache.poi.hssf.usermodel.*; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import java.io.*; +import java.util.Iterator; + +public class PoiUtil { + + /** + * 复制单元格 + * @param srcCell + * @param distCell + * @param copyValueFlag true则连同cell的内容一起复制 + */ + public static void copyCell(XSSFWorkbook wb, Cell srcCell, Cell distCell, boolean copyValueFlag) { + CellStyle newStyle = wb.createCellStyle(); + CellStyle srcStyle = srcCell.getCellStyle(); + + newStyle.cloneStyleFrom(srcStyle); + newStyle.setFont(wb.getFontAt(srcStyle.getFontIndex())); + + // 样式 + distCell.setCellStyle(newStyle); + + // 内容 + if (srcCell.getCellComment() != null) { + distCell.setCellComment(srcCell.getCellComment()); + } + + // 不同数据类型处理 + CellType srcCellType = srcCell.getCellTypeEnum(); + distCell.setCellType(srcCellType); + + if (copyValueFlag) { + if (srcCellType == CellType.NUMERIC) { + if (DateUtil.isCellDateFormatted(srcCell)) { + distCell.setCellValue(srcCell.getDateCellValue()); + } else { + distCell.setCellValue(srcCell.getNumericCellValue()); + } + } else if (srcCellType == CellType.STRING) { + distCell.setCellValue(srcCell.getRichStringCellValue()); + } else if (srcCellType == CellType.BLANK) { + + } else if (srcCellType == CellType.BOOLEAN) { + distCell.setCellValue(srcCell.getBooleanCellValue()); + } else if (srcCellType == CellType.ERROR) { + distCell.setCellErrorValue(srcCell.getErrorCellValue()); + } else if (srcCellType == CellType.FORMULA) { + distCell.setCellFormula(srcCell.getCellFormula()); + } + } + } + + /** + * 行复制功能 + * @param wb 工作簿 + * @param fromRow 从哪行开始 + * @param toRow 目标行 + * @param copyValueFlag true则连同cell的内容一起复制 + */ + public static void copyRow(XSSFWorkbook wb, Row fromRow, Row toRow, boolean copyValueFlag) { + toRow.setHeight(fromRow.getHeight()); + + for (Iterator cellIt = fromRow.cellIterator(); cellIt.hasNext();) { + Cell tmpCell = cellIt.next(); + Cell newCell = toRow.createCell(tmpCell.getColumnIndex()); + copyCell(wb, tmpCell, newCell, copyValueFlag); + } + + Sheet worksheet = fromRow.getSheet(); + + for (int i = 0; i < worksheet.getNumMergedRegions(); i++) { + CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i); + if (cellRangeAddress.getFirstRow() == fromRow.getRowNum()) { + CellRangeAddress newCellRangeAddress = new CellRangeAddress(toRow.getRowNum(), + (toRow.getRowNum() + (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow())), + cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastColumn()); + worksheet.addMergedRegionUnsafe(newCellRangeAddress); + } + } + } + + /** + * excel 插入行 在开始行号之上新增 + * @param sheet + * @param rows 插入几行 + * @param startRow 开始行号 + */ + private static void insertRow(Sheet sheet, int startRow, int rows) { + sheet.shiftRows(startRow, sheet.getLastRowNum(), rows, true, false); + for (int i = 0; i < rows; i++) { + Row sourceRow = null;//原始位置 + Row targetRow = null;//移动后位置 + Cell sourceCell = null; + Cell targetCell = null; + sourceRow = sheet.createRow(startRow); + targetRow = sheet.getRow(startRow + rows); + sourceRow.setHeight(targetRow.getHeight()); + + for (int m = targetRow.getFirstCellNum(); m < targetRow.getPhysicalNumberOfCells(); m++) { + sourceCell = sourceRow.createCell(m); + targetCell = targetRow.getCell(m); + sourceCell.setCellStyle(targetCell.getCellStyle()); + sourceCell.setCellType(targetCell.getCellTypeEnum()); + sourceCell.setCellFormula(targetCell.getCellFormula()); + } + startRow++; + } + + } + +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/WechatUtil.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/WechatUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..146244804cb137c1b94b68c44995cb74766c3863 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/WechatUtil.java @@ -0,0 +1,69 @@ +package com.gitee.neuray.security.wb.ribs.util; + +import sun.misc.BASE64Encoder; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; + +/** + * @auther: liwd + * @date: 2020/5/8 + * @description: + */ +public class WechatUtil { + //文件转换二进制流 + public static byte[] fileToBytes(File file){ + byte[] data = null; + try{ + FileInputStream fim = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int len; + byte[] buffer = new byte[1024]; + while ((len = fim.read(buffer))!=-1){ + bos.write(buffer,0,len); + } + data = bos.toByteArray(); + fim.close(); + bos.close(); + }catch (Exception e){ + System.out.println("转换报错"); + e.printStackTrace(); + } + return data; + } + //文件转换二进制流 + public static byte[] fileToBytes(InputStream im){ + byte[] data = null; + try{ + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + int len; + byte[] buffer = new byte[1024]; + while ((len = im.read(buffer))!=-1){ + bos.write(buffer,0,len); + } + data = bos.toByteArray(); + im.close(); + bos.close(); + }catch (Exception e){ + System.out.println("转换报错"); + e.printStackTrace(); + } + return data; + } + //二进制流base64转码 + public static String bytesEncodeBase64 (byte[] datas){ + BASE64Encoder encoder = new BASE64Encoder(); + return datas != null ? encoder.encode(datas) : ""; + } + //文件转二进制转base64 + public static String fileToBytesToBase64(File file){ + return bytesEncodeBase64(fileToBytes(file)); + } + //文件转二进制转base64 + public static String fileToBytesToBase64(InputStream im){ + return bytesEncodeBase64(fileToBytes(im)); + } + +} \ No newline at end of file diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/Dictionary.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/Dictionary.java new file mode 100644 index 0000000000000000000000000000000000000000..a24a7162a8b60a5500e05fff9b0b312f241646b2 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/Dictionary.java @@ -0,0 +1,37 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat; + +public class Dictionary { + + /** 获取ACCESS_TOKEN的接口地址 */ + public static final String GET_ACCESS_TOKEN_URL = + "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"; + + /** 获取用户的接口地址 */ + public static final String GET_USER_INFO_URL = + "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s"; + + /** 上传文件的接口地址 */ + public static final String MEDIA_UPLOAD_URL = + "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s"; + + /** 下载文件的接口地址 */ + public static final String MEDIA_DOWNLOAD_URL = + "https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s"; + + /** 推送应用消息的接口地址 */ + public static final String SEND_MSG_URL = + "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s"; + + /** 网报应用id */ + public static final String WB_AGENT_ID = "1000010"; + + public static final String WB_CORPSECRET = "LdDobcWFWN6pYxbUJZvc8ZAzj9otWkbfoLgKisQWd1g"; + + /** ACCESS_TOKEN超时时间(分) */ + public static final int ACCESS_TOKEN_TIMEOUT_MIN = 60; + + public static final String CORPID = "wwacc92a7b917bf282"; + + public static final String CORPSECRET = "eKGSa6CpPbKBm_aA-hYrmUsGoeCf8C8_cNIwJcinR8c"; + +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/HttpUtil.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/HttpUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..00a161c118bc5c6b459c514363dac3ec3ebd690c --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/HttpUtil.java @@ -0,0 +1,118 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat; + +import org.apache.http.client.config.RequestConfig; +import org.apache.http.config.SocketConfig; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy; +import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.File; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * @author LIWD + * @date 2020/3/3 + */ +public class HttpUtil { + + private static CloseableHttpClient httpClient; + + private static void createHttpClient() { + RequestConfig.Builder requestConfigBuilder = RequestConfig.custom(); + //客户端和服务器建立连接的timeout + requestConfigBuilder.setConnectTimeout(30000); + //从连接池获取连接的timeout + requestConfigBuilder.setConnectionRequestTimeout(30000); + //连接建立后,request没有回应的timeout + requestConfigBuilder.setSocketTimeout(30000); + HttpClientBuilder clientBuilder = HttpClientBuilder.create(); + clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build()); + clientBuilder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(30000).build()); + clientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()); + httpClient = clientBuilder.build(); + } + + public static CloseableHttpClient getHttpClient() { + if(httpClient == null) { + createHttpClient(); + } + return httpClient; + } + + /*public static String httpRequest(String requestUrl, File file) { + StringBuffer buffer = new StringBuffer(); + + try{ + //1.建立连接 + URL url = new URL(requestUrl); + HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); //打开链接 + + //1.1输入输出设置 + httpUrlConn.setDoInput(true); + httpUrlConn.setDoOutput(true); + httpUrlConn.setUseCaches(false); // post方式不能使用缓存 + //1.2设置请求头信息 + httpUrlConn.setRequestProperty("Connection", "Keep-Alive"); + httpUrlConn.setRequestProperty("Charset", "UTF-8"); + //1.3设置边界 + String BOUNDARY = "----------" + System.currentTimeMillis(); + httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY); + + // 请求正文信息 + // 第一部分: + //2.将文件头输出到微信服务器 + StringBuilder sb = new StringBuilder(); + sb.append("--"); // 必须多两道线 + sb.append(BOUNDARY); + sb.append("\r\n"); + sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length() + + "\";filename=\""+ file.getName() + "\"\r\n"); + sb.append("Content-Type:application/octet-stream\r\n\r\n"); + byte[] head = sb.toString().getBytes("utf-8"); + // 获得输出流 + OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream()); + // 将表头写入输出流中:输出表头 + outputStream.write(head); + + //3.将文件正文部分输出到微信服务器 + // 把文件以流文件的方式 写入到微信服务器中 + DataInputStream in = new DataInputStream(new FileInputStream(file)); + int bytes = 0; + byte[] bufferOut = new byte[1024]; + while ((bytes = in.read(bufferOut)) != -1) { + outputStream.write(bufferOut, 0, bytes); + } + in.close(); + //4.将结尾部分输出到微信服务器 + byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线 + outputStream.write(foot); + outputStream.flush(); + outputStream.close(); + + + //5.将微信服务器返回的输入流转换成字符串 + InputStream inputStream = httpUrlConn.getInputStream(); + InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + + String str = null; + while ((str = bufferedReader.readLine()) != null) { + buffer.append(str); + } + + bufferedReader.close(); + inputStreamReader.close(); + // 释放资源 + inputStream.close(); + inputStream = null; + httpUrlConn.disconnect(); + + + } catch (IOException e) { + System.out.println("发送POST请求出现异常!" + e); + e.printStackTrace(); + } + return buffer.toString(); + }*/ +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/RedirectURLTool.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/RedirectURLTool.java new file mode 100644 index 0000000000000000000000000000000000000000..e997af8b11f770e49e7883834e5d574785ecc8b9 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/RedirectURLTool.java @@ -0,0 +1,25 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +public class RedirectURLTool { + + private static final String CONNECT_OAUTH2_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s"; + + /** + * 生成应用路径工具 + * @param args + */ + public static void main(String[] args) { + String a = CONNECT_OAUTH2_AUTHORIZE_URL + + "&response_type=%s&scope=%s&state=%s#wechat_redirect"; + System.out.println(URLEncoder.encode("http://7dkyir.natappfree.cc/app/addressList")); + try { + System.out.println(String.format(a,"wwacc92a7b917bf282", + URLEncoder.encode("http://7dkyir.natappfree.cc/app/addresslist","UTF-8"),"code","snsapi_base","STATE")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/AccessToken.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/AccessToken.java new file mode 100644 index 0000000000000000000000000000000000000000..a825b4b7f67ba7bef2dd0f26ef52370db4c8cb57 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/AccessToken.java @@ -0,0 +1,61 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat.entity; + +import com.alibaba.fastjson.annotation.JSONField; + +import java.io.Serializable; + +public class AccessToken implements Serializable { + + private static final long serialVersionUID = 1L; + + private String accessToken; + + private int expiresIn; + + private long time; + + private String errmsg; + + private String errcode; + + @JSONField(name = "access_token") + public String getAccessToken() { + return accessToken; + } + @JSONField(name = "access_token") + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + @JSONField(name = "expires_in") + public int getExpiresIn() { + return expiresIn; + } + @JSONField(name = "expires_in") + public void setExpiresIn(int expiresIn) { + this.expiresIn = expiresIn; + } + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + + public String getErrcode() { + return errcode; + } + + public void setErrcode(String errcode) { + this.errcode = errcode; + } +} \ No newline at end of file diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/MediaUploadInfo.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/MediaUploadInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..819f0b60fb7e322ca7c9ce0576c797852db93c09 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/MediaUploadInfo.java @@ -0,0 +1,58 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat.entity; + +import com.alibaba.fastjson.annotation.JSONField; + +public class MediaUploadInfo { + + private String errorcode; + + private String errmsg; + + private String type; + + private String mediaId; + + private String createdAt; + + public String getErrorcode() { + return errorcode; + } + + public void setErrorcode(String errorcode) { + this.errorcode = errorcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @JSONField(name = "media_id") + public String getMediaId() { + return mediaId; + } + @JSONField(name = "media_id") + public void setMediaId(String mediaId) { + this.mediaId = mediaId; + } + @JSONField(name = "created_at") + public String getCreatedAt() { + return createdAt; + } + + @JSONField(name = "created_at") + public void setCreatedAt(String createdAt) { + this.createdAt = createdAt; + } +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/SendMsgInfo.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/SendMsgInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..413760806c9d85fe9ff6df9a79bea7a590d7bc24 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/SendMsgInfo.java @@ -0,0 +1,34 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat.entity; + +public class SendMsgInfo { + + private String invaliduser; + + private String invalidparty; + + private String invalidtag; + + public String getInvaliduser() { + return invaliduser; + } + + public void setInvaliduser(String invaliduser) { + this.invaliduser = invaliduser; + } + + public String getInvalidparty() { + return invalidparty; + } + + public void setInvalidparty(String invalidparty) { + this.invalidparty = invalidparty; + } + + public String getInvalidtag() { + return invalidtag; + } + + public void setInvalidtag(String invalidtag) { + this.invalidtag = invalidtag; + } +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/UserInfo.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/UserInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..160ff962398b4d9ff105e19ad06d874168bdfc35 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/UserInfo.java @@ -0,0 +1,61 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat.entity; + +import com.alibaba.fastjson.annotation.JSONField; + +import java.io.Serializable; + +public class UserInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String errcode; + + private String errmsg; + + private String userId; + + private String deviceId; + + private long time; + + public long getTime() { + return time; + } + + public void setTime(long time) { + this.time = time; + } + + public String getErrcode() { + return errcode; + } + + public void setErrcode(String errcode) { + this.errcode = errcode; + } + + public String getErrmsg() { + return errmsg; + } + + public void setErrmsg(String errmsg) { + this.errmsg = errmsg; + } + + @JSONField(name = "UserId") + public String getUserId() { + return userId; + } + @JSONField(name = "UserId") + public void setUserId(String userId) { + this.userId = userId; + } + @JSONField(name = "DeviceId") + public String getDeviceId() { + return deviceId; + } + @JSONField(name = "DeviceId") + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } +} diff --git a/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/WechatError.java b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/WechatError.java new file mode 100644 index 0000000000000000000000000000000000000000..3ec57d3c3f4179e831c4008e20f911d619832fb7 --- /dev/null +++ b/neuray-pm-provider/neuray-pm-provider-wb/src/main/java/com/gitee/neuray/security/wb/ribs/util/wechat/entity/WechatError.java @@ -0,0 +1,32 @@ +package com.gitee.neuray.security.wb.ribs.util.wechat.entity; + +import com.alibaba.fastjson.annotation.JSONField; + +public class WechatError { + + private int errCode; + + private String errMsg; + + @JSONField(name = "errcode") + public int getErrCode() { + return errCode; + } + @JSONField(name = "errcode") + public void setErrCode(int errCode) { + this.errCode = errCode; + } + @JSONField(name = "errmsg") + public String getErrmsg() { + return errMsg; + } + @JSONField(name = "errmsg") + public void setErrmsg(String errMsg) { + this.errMsg = errMsg; + } + + @Override + public String toString() { + return "错误: Code=" + this.errCode + ", Msg=" + this.errMsg; + } +} \ No newline at end of file