Commit bd499f3d authored by matianhao's avatar matianhao

[招必得接口] <add> 接入招必得接口;修改配置文件

parent 14c01606
...@@ -46,6 +46,12 @@ ...@@ -46,6 +46,12 @@
<version>1.18.12</version> <version>1.18.12</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
......
package com.mth.requestsecret.controller;
import com.alibaba.fastjson.JSONObject;
import com.mth.requestsecret.service.RestTemlateService;
import com.mth.requestsecret.util.AESUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 招必得接口
*
* @author MaTianHao
* @date 2020/8/20
*/
@RestController
@Slf4j
public class ZbdController {
@Autowired
RestTemlateService restTemlateService;
/**
* 2.2 获取标段信息接口
*
* @param beginDate
* @param endDate
* @return
* @throws Exception
*/
@PostMapping("/getTenderInfo")
public ResponseEntity getTenderInfo(String beginDate, String endDate) throws Exception {
String apiMethod = "/la/supervise/getTenderInfo.do";
// 1. 设置参数
JSONObject requestParam = new JSONObject();
requestParam.put("BeginDate", beginDate);
requestParam.put("EndDate", endDate);
// 2. 加密参数并发送请求
return encryptRequestParam(requestParam, apiMethod);
}
/**
* 2.3 获取报名信息接口
*
* @param tenderNo
* @return
* @throws Exception
*/
@PostMapping("/getTenderBidInfo")
public ResponseEntity getTenderBidInfo(String tenderNo) throws Exception {
String apiMethod = "/la/supervise/getTenderBidInfo.do";
// 1. 设置参数
JSONObject requestParam = new JSONObject();
requestParam.put("TenderNo", tenderNo);
// 2. 加密参数并发送请求
return encryptRequestParam(requestParam, apiMethod);
}
/**
* 2.4 获取开标信息接口
*
* @param tenderNo
* @return
* @throws Exception
*/
@PostMapping("/getTenderOpenBidInfo")
public ResponseEntity getTenderOpenBidInfo(String tenderNo) throws Exception {
String apiMethod = "/la/supervise/getTenderOpenBidInfo.do";
// 1. 设置参数
JSONObject requestParam = new JSONObject();
requestParam.put("TenderNo", tenderNo);
// 2. 加密参数并发送请求
return encryptRequestParam(requestParam, apiMethod);
}
/**
* 2.5 获取中标信息接口
*
* @param tenderNo
* @return
* @throws Exception
*/
@PostMapping("/getTenderWinInfo")
public ResponseEntity getTenderWinInfo(String tenderNo) throws Exception {
String apiMethod = "/la/supervise/getTenderWinInfo.do";
// 1. 设置参数
JSONObject requestParam = new JSONObject();
requestParam.put("TenderNo", tenderNo);
// 2. 加密参数并发送请求
return encryptRequestParam(requestParam, apiMethod);
}
/**
* 2.6 获取评标信息接口
*
* @param tenderNo
* @return
* @throws Exception
*/
@PostMapping("/getTenderEvalInfo")
public ResponseEntity getTenderEvalInfo(String tenderNo) throws Exception {
String apiMethod = "/la/supervise/getTenderEvalInfo.do";
// 1. 设置参数
JSONObject requestParam = new JSONObject();
requestParam.put("TenderNo", tenderNo);
// 2. 加密参数并发送请求
return encryptRequestParam(requestParam, apiMethod);
}
/**
* 异常响应体
*/
private ResponseEntity exceptionResponseEntity() {
JSONObject resultBody = new JSONObject();
resultBody.put("success", false);
resultBody.put("error", "时间戳接口返回异常");
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(resultBody);
}
/**
* 根据 key 和 iv 加密参数
*/
private ResponseEntity encryptRequestParam(JSONObject requestParam, String apiMethod) throws Exception {
String encrypt = AESUtils.encrypt(requestParam.toJSONString());
JSONObject param = new JSONObject();
param.put("_args", encrypt);
log.info("{} - 参数:{}", apiMethod, requestParam.toJSONString());
try {
return restTemlateService.zbdSendRequest(param, apiMethod);
} catch (Exception e) {
return exceptionResponseEntity();
}
}
}
...@@ -38,13 +38,13 @@ public class RequestSecretSchedulerTask implements SchedulingConfigurer { ...@@ -38,13 +38,13 @@ public class RequestSecretSchedulerTask implements SchedulingConfigurer {
@Autowired @Autowired
RedisUtils redisUtil; RedisUtils redisUtil;
@Value("${DATA_API_ADDRESS}") @Value("${ruicheng.address}")
private String pathUrl; private String pathUrl;
@Value("${app.key}") @Value("${ruicheng.key}")
private String appKey; private String appKey;
@Value("${app.secret}") @Value("${ruicheng.secret}")
private String appSecret; private String appSecret;
/** /**
......
...@@ -2,6 +2,7 @@ package com.mth.requestsecret.service; ...@@ -2,6 +2,7 @@ package com.mth.requestsecret.service;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.mth.requestsecret.scheduler.RequestSecretSchedulerTask; import com.mth.requestsecret.scheduler.RequestSecretSchedulerTask;
import com.mth.requestsecret.util.AESUtils;
import com.mth.requestsecret.util.DSLUtils; import com.mth.requestsecret.util.DSLUtils;
import com.mth.requestsecret.util.MD5Utils; import com.mth.requestsecret.util.MD5Utils;
import com.mth.requestsecret.util.RedisUtils; import com.mth.requestsecret.util.RedisUtils;
...@@ -14,6 +15,7 @@ import org.springframework.util.MultiValueMap; ...@@ -14,6 +15,7 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.Date; import java.util.Date;
import java.util.Objects;
import static com.mth.requestsecret.constant.Constants.RESPONSE_CODE_14; import static com.mth.requestsecret.constant.Constants.RESPONSE_CODE_14;
import static com.mth.requestsecret.constant.Constants.SJJ_REQUEST_SECRET_PREFIX; import static com.mth.requestsecret.constant.Constants.SJJ_REQUEST_SECRET_PREFIX;
...@@ -40,12 +42,28 @@ public class RestTemlateService { ...@@ -40,12 +42,28 @@ public class RestTemlateService {
private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0); private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
@Value("${DATA_API_ADDRESS}") @Value("${ruicheng.address}")
private String pathUrl; private String pathUrl;
@Value("${app.key}") @Value("${ruicheng.key}")
private String appKey; private String appKey;
@Value("${zbd.appid}")
private String zbdAppid;
@Value("${zbd.appSecret}")
private String zbdAppSecret;
@Value("${zbd.address}")
private String zbdAddress;
/**
* 瑞成平台接口发送请求
*
* @param paramMap
* @param apiMethod
* @return
*/
public ResponseEntity<String> commonSendRequest(MultiValueMap<String, Object> paramMap, final String apiMethod) { public ResponseEntity<String> commonSendRequest(MultiValueMap<String, Object> paramMap, final String apiMethod) {
// 请求url拼接api签名和公共参数 // 请求url拼接api签名和公共参数
StringBuilder url = new StringBuilder() StringBuilder url = new StringBuilder()
...@@ -97,4 +115,57 @@ public class RestTemlateService { ...@@ -97,4 +115,57 @@ public class RestTemlateService {
} }
return responseEntity; return responseEntity;
} }
/**
* 招必得平台接口发送请求
*/
public ResponseEntity<String> zbdSendRequest(JSONObject paramMap, final String apiMethod) {
// 1. 获取请求时间戳并解密
String timeStamp = getZbdTimeStampAndDecrypt();
// 2. 拼接header验证签名
String signStr = zbdAppid + zbdAppSecret + timeStamp;
String sign = MD5Utils.encoderByMd5UpperCase(signStr);
// authorization : appid=xxx&sign=xxx
String authorization = "appid=" + zbdAppid + "&sign=" + sign;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("authorization", authorization);
// 3. 发送请求
HttpEntity<String> request = new HttpEntity<>(paramMap.toJSONString(), headers);
String url = zbdAddress + apiMethod;
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
// 4. 日志记录
log.info("招必得api:{}", apiMethod);
log.info("api url:{}", url);
log.info("api params:{}", paramMap);
log.info("api response:{}", responseEntity);
return responseEntity;
}
/**
* 获取请求时间戳并解密
*
* @return
*/
private String getZbdTimeStampAndDecrypt() {
String timeStampUrl = zbdAddress + "/gen/querytimestamp.do?appid=2020081001";
ResponseEntity<String> timeStampResponse = restTemplate.getForEntity(timeStampUrl, String.class);
JSONObject body = JSONObject.parseObject(timeStampResponse.getBody());
if (!(Objects.nonNull(body) && Objects.equals("true", body.getString("success")))) {
log.warn("招必得请求时间戳接口返回异常:{}", timeStampResponse);
throw new RuntimeException("时间戳接口异常");
}
// 解析返回值
String encryptTimestamp = body.getJSONObject("data").getString("encrypt_key");
// 解密
return AESUtils.decrypt(encryptTimestamp);
}
} }
\ No newline at end of file
package com.mth.requestsecret.util;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/**
* @author MaTianHao
* @date 2020/8/19
*/
@Slf4j
public class AESUtils {
/**
* AES/CBC协定密钥key(256位)
*/
private final static String KEY = "LaKEXJRbiocF1iYOssFgj5Tdq1m0kFVO";
/**
* AES/CBC协定向量iv(128位)
*/
private final static String IV = "LaKEXJRbiocF1iYO";
/**
* 加密
*/
public static String encrypt(String sstr) throws Exception {
byte[] keyByte = KEY.getBytes("utf-8");
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
// 算法/模式/补码方式
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] ivByte = IV.getBytes(StandardCharsets.UTF_8);
// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
IvParameterSpec iv = new IvParameterSpec(ivByte);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] encrype = cipher.doFinal(sstr.getBytes());
// 此处使用BASE64做转码功能,同时能起到2次加密的作用。
return Base64.getEncoder().encodeToString(encrype);
}
/**
* 解密
*/
public static String decrypt(String sstr) {
try {
byte[] keyByte = KEY.getBytes("utf-8");
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
// 算法/模式/补码方式
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 使用CBC模式,需要一个向量iv,可增加加密算法的强度
IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
byte[] encrype = Base64.getDecoder().decode(sstr);
byte[] origin = cipher.doFinal(encrype);
return new String(origin);
} catch (Exception e) {
return null;
}
}
}
package com.mth.requestsecret.util; package com.mth.requestsecret.util;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
public class MD5Utils { public class MD5Utils {
/**
* md5加密
*
* @param plainText
* @return
*/
public static String encoderByMd5(String plainText) { public static String encoderByMd5(String plainText) {
String re_md5 = new String(); String re_md5 = new String();
try { try {
...@@ -32,4 +39,15 @@ public class MD5Utils { ...@@ -32,4 +39,15 @@ public class MD5Utils {
return re_md5; return re_md5;
} }
/**
* md5加密(大写)
*
* @param plainText
* @return
*/
public static String encoderByMd5UpperCase(String plainText) {
String md5 = encoderByMd5(plainText);
return md5.toUpperCase();
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment