WaterElectricComponent.java 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package com.chuanghai.ihotel.component;
  2. import com.chuanghai.ihotel.common.exception.BizCodeEnume;
  3. import com.chuanghai.ihotel.common.exception.RRException;
  4. import com.chuanghai.ihotel.config.WaterElectricConfig;
  5. import com.chuanghai.ihotel.constant.RedisKey;
  6. import com.chuanghai.ihotel.util.WaterElectricDataEncAndDecUtil;
  7. import com.chuanghai.ihotel.util.WaterElectricSignUtil;
  8. import com.fasterxml.jackson.databind.JsonNode;
  9. import com.fasterxml.jackson.databind.ObjectMapper;
  10. import lombok.extern.slf4j.Slf4j;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.data.redis.core.StringRedisTemplate;
  13. import org.springframework.http.HttpEntity;
  14. import org.springframework.http.HttpHeaders;
  15. import org.springframework.http.ResponseEntity;
  16. import org.springframework.stereotype.Component;
  17. import org.springframework.util.LinkedMultiValueMap;
  18. import org.springframework.util.MultiValueMap;
  19. import org.springframework.util.StringUtils;
  20. import org.springframework.web.client.RestTemplate;
  21. import java.time.LocalDateTime;
  22. import java.time.format.DateTimeFormatter;
  23. import java.util.HashMap;
  24. import java.util.Map;
  25. import java.util.concurrent.TimeUnit;
  26. /**
  27. * 水电服务
  28. */
  29. @Slf4j
  30. @Component
  31. public class WaterElectricComponent {
  32. private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
  33. @Autowired
  34. private StringRedisTemplate stringRedisTemplate;
  35. @Autowired
  36. private WaterElectricConfig waterElectricConfig;
  37. /**
  38. * 获取token
  39. * @return
  40. */
  41. public String getToken() {
  42. String token = stringRedisTemplate.opsForValue().get(RedisKey.WATER_AND_ELECTRIC_SERVICE_TOKEN);
  43. if (StringUtils.hasText(token)) {
  44. return token;
  45. } else {
  46. HashMap<String, String> map = new HashMap<>();
  47. map.put("operatorSecret", waterElectricConfig.getOperatorSecret());
  48. try {
  49. JsonNode jsonNode = queryData("queryToken", map, null);
  50. String accessToken = jsonNode.get("accessToken").asText();
  51. long ttl = jsonNode.get("tokenAvailableTime").asLong();
  52. stringRedisTemplate.opsForValue().set(RedisKey.WATER_AND_ELECTRIC_SERVICE_TOKEN, accessToken, ttl, TimeUnit.SECONDS);
  53. return accessToken;
  54. } catch (Exception e) {
  55. throw new RRException(BizCodeEnume.THIRD_PARTY_SERVICE_CALL_FAILED, "请求水电接口token异常");
  56. }
  57. }
  58. }
  59. /**
  60. * 请求数据
  61. *
  62. * @param path 请求接口url
  63. * @param paramMap 请求参数
  64. * @param token 请求token 获取token时该字段可以为空
  65. */
  66. private JsonNode queryData(String path, Map<String, String> paramMap, String token) throws Exception {
  67. ObjectMapper mapper = new ObjectMapper();
  68. // 加密data部分
  69. String encode = WaterElectricDataEncAndDecUtil.dataEncode(mapper.writeValueAsString(paramMap), waterElectricConfig.getDataSecret(), waterElectricConfig.getDataSecretIv());
  70. String seq = "0001";
  71. String timeStamp = DTF.format(LocalDateTime.now());
  72. MultiValueMap<String, String> requestMap = new LinkedMultiValueMap<>();
  73. requestMap.add("operatorId", waterElectricConfig.getOperatorId());
  74. requestMap.add("data", encode);
  75. requestMap.add("timeStamp", timeStamp);
  76. requestMap.add("seq", seq);
  77. // 为防止 + 在收发过程中被变成空格,将加密后的密文中的所有空格替换一下,需要签名的参数: operatorId + 加密后的data + 时间戳 + 自增序列
  78. String signSrc = waterElectricConfig.getOperatorId() + encode.replaceAll(" ", "+") + timeStamp + seq;
  79. String sig = WaterElectricSignUtil.sign(signSrc, waterElectricConfig.getSignKey());
  80. requestMap.add("sig", sig);
  81. RestTemplate restTemplate = new RestTemplate();
  82. HttpHeaders headers = new HttpHeaders();
  83. if (StringUtils.hasText(token)) {
  84. headers.add("token", token);
  85. }
  86. HttpEntity<MultiValueMap<String, String>> formEntity = new HttpEntity<>(requestMap, headers);
  87. ResponseEntity<String> responseEntity = restTemplate.postForEntity(waterElectricConfig.getServiceHost() + path, formEntity, String.class);
  88. String body = responseEntity.getBody();
  89. JsonNode jsonNode = mapper.readTree(body);
  90. if (!"0".equals(jsonNode.get("ret").asText())) {
  91. log.error("接口请求失败,【{}】", body);
  92. }
  93. // 验签
  94. String dataS = jsonNode.get("data").asText().replaceAll(" ", "+");
  95. String resultSigStr = jsonNode.get("operatorId").asText()
  96. + dataS
  97. + jsonNode.get("msg").asText()
  98. + jsonNode.get("ret").asText();
  99. // 本地签名
  100. String localSign = WaterElectricSignUtil.sign(resultSigStr, waterElectricConfig.getSignKey());
  101. String remoteSign = jsonNode.get("sig").asText();
  102. if (!(StringUtils.hasText(remoteSign) && remoteSign.equals(localSign))) {
  103. log.error("接口验签失败,本地签名【{}】,远程签名【{}】", localSign, remoteSign);
  104. }
  105. String data = WaterElectricDataEncAndDecUtil.dataDecode(dataS, waterElectricConfig.getDataSecret(), waterElectricConfig.getDataSecretIv());
  106. if (!StringUtils.hasText(data)) {
  107. log.error("水电服务接口data解密失败");
  108. }
  109. JsonNode dataJson = mapper.readTree(data);
  110. return dataJson;
  111. }
  112. }