package com.jsowell.api.thirdparty; import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.collect.Maps; import com.jsowell.common.annotation.Anonymous; import com.jsowell.common.core.controller.BaseController; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.JWTUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.pile.thirdparty.CommonParamsDTO; import com.jsowell.pile.vo.ThirdPartySecretInfoVO; import com.jsowell.thirdparty.platform.util.Cryptos; import com.jsowell.thirdparty.platform.util.GBSignUtils; import com.jsowell.thirdparty.service.ThirdpartySecretInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RestController; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; /** * 内蒙古接口 */ @Anonymous @RestController public class ThirdPartyBaseController extends BaseController { @Autowired private ThirdpartySecretInfoService thirdpartySecretInfoService; /** * 验证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; } /** * 解析DTO * @param dto * @param targetClass * @return * @param */ protected T parseParamsDTO(CommonParamsDTO dto, Class targetClass) throws NoSuchFieldException, IllegalAccessException { // 解密 String operatorId = StringUtils.isNotBlank(dto.getOperatorID()) ? dto.getOperatorID() : dto.getPlatformID(); // 通过operatorId 查出 operatorSecret ThirdPartySecretInfoVO secretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId); if (secretInfoVO == null) { throw new BusinessException("1", "无此对接平台"); } String dataSecret = secretInfoVO.getOurDataSecret(); String dataSecretIv = secretInfoVO.getOurDataSecretIv(); // 解密data 获取参数中的OperatorSecret String decrypt = Cryptos.decrypt(dto.getData(), dataSecret, dataSecretIv); T t = JSONObject.parseObject(decrypt, targetClass); // 校验是否有operatorId, 没有就set verifyOperatorId(dto, t); return t; } /** * 获取OperatorId的值 verify * @param t * @return * @throws NoSuchFieldException * @throws IllegalAccessException */ private 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 void setFieldValueByFieldName(T t, String targetFieldName, Object value) { // 获取该对象的class Class 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); } } } /** * 使用反射获取字段值 */ private Object getFieldValueByObject(T t, String targetFieldName) { // 获取该对象的class Class 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; } /** * 校验签名 * * verifySignature */ protected boolean verifySignature(CommonParamsDTO dto) { return this.verifySignature(dto, null); } protected boolean verifySignature(CommonParamsDTO dto, String signSecret) { // 查询密钥 String operatorId = StringUtils.isNotBlank(dto.getOperatorID()) ? dto.getOperatorID() : dto.getPlatformID(); ThirdPartySecretInfoVO secretInfoVO = thirdpartySecretInfoService.queryByOperatorId(operatorId); if (secretInfoVO == null) { throw new BusinessException("1", "无此对接平台"); } // 校验签名,使用响应方的密钥 if (StringUtils.isBlank(signSecret)) { signSecret = secretInfoVO.getOurSigSecret(); } Map 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); } }