2024-05-10 15:30:20 +08:00
|
|
|
|
package com.jsowell.api.thirdparty;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
|
|
|
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
2024-05-08 18:40:45 +08:00
|
|
|
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
2024-04-19 17:10:51 +08:00
|
|
|
|
import com.google.common.collect.Maps;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
import com.jsowell.common.annotation.Anonymous;
|
|
|
|
|
|
import com.jsowell.common.core.controller.BaseController;
|
|
|
|
|
|
import com.jsowell.common.exception.BusinessException;
|
2024-05-08 19:02:54 +08:00
|
|
|
|
import com.jsowell.common.util.JWTUtils;
|
2024-04-19 14:06:01 +08:00
|
|
|
|
import com.jsowell.common.util.StringUtils;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
import com.jsowell.pile.thirdparty.CommonParamsDTO;
|
2024-04-18 18:24:19 +08:00
|
|
|
|
import com.jsowell.pile.vo.ThirdPartySecretInfoVO;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
import com.jsowell.thirdparty.platform.util.Cryptos;
|
2024-04-19 17:10:51 +08:00
|
|
|
|
import com.jsowell.thirdparty.platform.util.GBSignUtils;
|
2024-04-18 18:24:19 +08:00
|
|
|
|
import com.jsowell.thirdparty.service.ThirdpartySecretInfoService;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
|
|
|
2024-05-08 18:40:45 +08:00
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
|
|
import java.lang.reflect.Method;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 内蒙古接口
|
|
|
|
|
|
*/
|
|
|
|
|
|
@Anonymous
|
|
|
|
|
|
@RestController
|
|
|
|
|
|
public class ThirdPartyBaseController extends BaseController {
|
2024-04-18 18:24:19 +08:00
|
|
|
|
|
2024-04-18 14:15:44 +08:00
|
|
|
|
@Autowired
|
2024-04-18 18:24:19 +08:00
|
|
|
|
private ThirdpartySecretInfoService thirdpartySecretInfoService;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
|
2024-05-08 19:02:54 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 验证token
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected boolean verifyToken(String token) {
|
|
|
|
|
|
if (StringUtils.equals(token, "jsowellTest")) {
|
|
|
|
|
|
// 为了方便测试,token为jsowellTest校验通过
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
boolean result;
|
|
|
|
|
|
try {
|
|
|
|
|
|
result = JWTUtils.checkThirdPartyToken(token);
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
result = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-19 16:05:58 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 解析DTO
|
|
|
|
|
|
* @param dto
|
|
|
|
|
|
* @param targetClass
|
|
|
|
|
|
* @return
|
|
|
|
|
|
* @param <T>
|
|
|
|
|
|
*/
|
2024-05-08 18:40:45 +08:00
|
|
|
|
protected <T> T parseParamsDTO(CommonParamsDTO dto, Class<T> targetClass) throws NoSuchFieldException, IllegalAccessException {
|
2024-04-18 14:15:44 +08:00
|
|
|
|
// 解密
|
2024-04-19 14:06:01 +08:00
|
|
|
|
String operatorId = StringUtils.isNotBlank(dto.getOperatorID()) ? dto.getOperatorID() : dto.getPlatformID();
|
2024-04-18 14:15:44 +08:00
|
|
|
|
// 通过operatorId 查出 operatorSecret
|
2024-04-18 18:24:19 +08:00
|
|
|
|
ThirdPartySecretInfoVO secretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId);
|
|
|
|
|
|
if (secretInfoVO == null) {
|
2024-04-18 14:15:44 +08:00
|
|
|
|
throw new BusinessException("1", "无此对接平台");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-19 14:06:01 +08:00
|
|
|
|
String dataSecret = secretInfoVO.getOurDataSecret();
|
|
|
|
|
|
String dataSecretIv = secretInfoVO.getOurDataSecretIv();
|
2024-04-18 14:15:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 解密data 获取参数中的OperatorSecret
|
|
|
|
|
|
String decrypt = Cryptos.decrypt(dto.getData(), dataSecret, dataSecretIv);
|
2024-05-08 18:40:45 +08:00
|
|
|
|
T t = JSONObject.parseObject(decrypt, targetClass);
|
|
|
|
|
|
|
|
|
|
|
|
// 校验是否有operatorId, 没有就set
|
|
|
|
|
|
verifyOperatorId(dto, t);
|
|
|
|
|
|
return t;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取OperatorId的值 verify
|
|
|
|
|
|
* @param t
|
|
|
|
|
|
* @return
|
|
|
|
|
|
* @throws NoSuchFieldException
|
|
|
|
|
|
* @throws IllegalAccessException
|
|
|
|
|
|
*/
|
|
|
|
|
|
private <T> void verifyOperatorId(CommonParamsDTO dto, T t) throws NoSuchFieldException, IllegalAccessException {
|
|
|
|
|
|
String targetFieldName = "operatorId";
|
|
|
|
|
|
String operatorId = (String) getFieldValueByObject(t, targetFieldName);
|
|
|
|
|
|
if (StringUtils.isBlank(operatorId)) {
|
|
|
|
|
|
setFieldValueByFieldName(t, targetFieldName, dto.getOperatorID());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private <T> void setFieldValueByFieldName(T t, String targetFieldName, Object value) {
|
|
|
|
|
|
// 获取该对象的class
|
|
|
|
|
|
Class<? extends Object> tClass = t.getClass();
|
|
|
|
|
|
// 获取所有的属性数组
|
|
|
|
|
|
Field[] fields = tClass.getDeclaredFields();
|
|
|
|
|
|
|
|
|
|
|
|
for (Field field : fields) {
|
|
|
|
|
|
// 属性名称
|
|
|
|
|
|
String currentFieldName = "";
|
|
|
|
|
|
try {
|
|
|
|
|
|
boolean has_JsonProperty = field.isAnnotationPresent(JsonProperty.class);
|
|
|
|
|
|
if (has_JsonProperty) {
|
|
|
|
|
|
currentFieldName = field.getAnnotation(JsonProperty.class).value();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
currentFieldName = field.getName();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 忽略大小写对比
|
|
|
|
|
|
if (currentFieldName.equalsIgnoreCase(targetFieldName)) {
|
|
|
|
|
|
// 取消语言访问检查
|
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
|
// 给变量赋值
|
|
|
|
|
|
field.set(t, value);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 使用反射获取字段值
|
|
|
|
|
|
*/
|
2024-08-08 10:56:02 +08:00
|
|
|
|
private <T> Object getFieldValueByObject(T t, String targetFieldName) {
|
2024-05-08 18:40:45 +08:00
|
|
|
|
// 获取该对象的class
|
|
|
|
|
|
Class<? extends Object> tClass = t.getClass();
|
|
|
|
|
|
// 获取所有的属性数组
|
|
|
|
|
|
Field[] fields = tClass.getDeclaredFields();
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 这里只需要 id 这个属性,所以直接取 fields[0] 这
|
|
|
|
|
|
* 一个,如果id不是排在第一位,自己取相应的位置,
|
|
|
|
|
|
* 如果有需要,可以写成for循环,遍历全部属性
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
for (Field field : fields) {
|
|
|
|
|
|
// 属性名称
|
|
|
|
|
|
String currentFieldName = "";
|
|
|
|
|
|
// 获取属性上面的注解 import com.fasterxml.jackson.annotation.JsonProperty;
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 举例: @JsonProperty("roleIds")
|
|
|
|
|
|
* private String roleIds;
|
|
|
|
|
|
*/
|
|
|
|
|
|
try {
|
|
|
|
|
|
boolean has_JsonProperty = field.isAnnotationPresent(JsonProperty.class);
|
|
|
|
|
|
if (has_JsonProperty) {
|
|
|
|
|
|
currentFieldName = field.getAnnotation(JsonProperty.class).value();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
currentFieldName = field.getName();
|
|
|
|
|
|
}
|
|
|
|
|
|
// 忽略大小写对比
|
|
|
|
|
|
if (currentFieldName.equalsIgnoreCase(targetFieldName)) {
|
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
|
currentFieldName = currentFieldName.replaceFirst(currentFieldName.substring(0, 1), currentFieldName.substring(0, 1).toUpperCase());
|
|
|
|
|
|
//整合出 getId() 属性这个方法
|
|
|
|
|
|
Method m = tClass.getMethod("get" + currentFieldName);
|
|
|
|
|
|
return m.invoke(t);
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (SecurityException e) {
|
|
|
|
|
|
// 安全性异常
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
|
|
// 非法参数
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
} catch (IllegalAccessException | NoSuchMethodException e) {
|
|
|
|
|
|
// 无访问权限
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
} catch (InvocationTargetException e) {
|
|
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
2024-04-18 14:15:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-19 17:10:51 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 校验签名
|
|
|
|
|
|
*
|
|
|
|
|
|
* verifySignature
|
|
|
|
|
|
*/
|
|
|
|
|
|
protected boolean verifySignature(CommonParamsDTO dto) {
|
2024-09-25 11:49:14 +08:00
|
|
|
|
return this.verifySignature(dto, null);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected boolean verifySignature(CommonParamsDTO dto, String signSecret) {
|
2024-04-19 17:10:51 +08:00
|
|
|
|
// 查询密钥
|
|
|
|
|
|
String operatorId = StringUtils.isNotBlank(dto.getOperatorID()) ? dto.getOperatorID() : dto.getPlatformID();
|
2024-11-26 13:32:04 +08:00
|
|
|
|
ThirdPartySecretInfoVO secretInfoVO;
|
|
|
|
|
|
if (StringUtils.isNotBlank(dto.getPlatformType())) {
|
|
|
|
|
|
// type不为空,按照type查
|
|
|
|
|
|
secretInfoVO = thirdpartySecretInfoService.queryByThirdPlatformType(dto.getPlatformType());
|
|
|
|
|
|
}else {
|
|
|
|
|
|
secretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId);
|
|
|
|
|
|
}
|
2024-04-19 17:10:51 +08:00
|
|
|
|
if (secretInfoVO == null) {
|
|
|
|
|
|
throw new BusinessException("1", "无此对接平台");
|
|
|
|
|
|
}
|
|
|
|
|
|
// 校验签名,使用响应方的密钥
|
2024-09-25 11:49:14 +08:00
|
|
|
|
if (StringUtils.isBlank(signSecret)) {
|
2024-09-25 11:53:45 +08:00
|
|
|
|
signSecret = secretInfoVO.getOurSigSecret();
|
2024-09-25 11:49:14 +08:00
|
|
|
|
}
|
2024-04-19 17:10:51 +08:00
|
|
|
|
Map<String, String> map = Maps.newLinkedHashMap();
|
|
|
|
|
|
String operatorID = dto.getOperatorID();
|
|
|
|
|
|
if (StringUtils.isNotBlank(operatorID)) {
|
|
|
|
|
|
map.put("OperatorID", operatorID);
|
|
|
|
|
|
}
|
|
|
|
|
|
String platformID = dto.getPlatformID();
|
|
|
|
|
|
if (StringUtils.isNotBlank(platformID)) {
|
|
|
|
|
|
map.put("PlatformID", platformID);
|
|
|
|
|
|
}
|
|
|
|
|
|
String data = dto.getData();
|
|
|
|
|
|
if (StringUtils.isNotBlank(data)) {
|
|
|
|
|
|
map.put("Data", data);
|
|
|
|
|
|
}
|
|
|
|
|
|
String timeStamp = dto.getTimeStamp();
|
|
|
|
|
|
if (StringUtils.isNotBlank(timeStamp)) {
|
|
|
|
|
|
map.put("TimeStamp", timeStamp);
|
|
|
|
|
|
}
|
|
|
|
|
|
String seq = dto.getSeq();
|
|
|
|
|
|
if (StringUtils.isNotBlank(seq)) {
|
|
|
|
|
|
map.put("Seq", seq);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 计算sign
|
|
|
|
|
|
String sign = GBSignUtils.sign(map, signSecret);
|
|
|
|
|
|
return StringUtils.equals(dto.getSig(), sign);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-18 14:15:44 +08:00
|
|
|
|
}
|