diff --git a/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java b/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java index df4dd76..412eb6c 100644 --- a/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java +++ b/src/main/java/com/newyetai/alitaforward/verification/constants/FactorVerificationSourceTypeEnum.java @@ -8,7 +8,9 @@ public enum FactorVerificationSourceTypeEnum { FXQ("放心签", 1), CL("创蓝", 2), - SYS("系统", 3); + SYS("系统", 3), + ALI("阿里", 4), + ; private final String desc; diff --git a/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java b/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java index a2db1aa..c6e5d57 100644 --- a/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java +++ b/src/main/java/com/newyetai/alitaforward/verification/factor/AbstractVerify.java @@ -40,8 +40,6 @@ import lombok.extern.slf4j.Slf4j; @SuppressWarnings("rawtypes,unchecked") public abstract class AbstractVerify implements IVerify, ITopicMqHandler{ - private static final Integer DEFAULT_TYPE = FactorVerificationSourceTypeEnum.CL.getType(); - static final Map SOURCE_SERVICE_MAP = Maps.newConcurrentMap(); /** @@ -97,14 +95,9 @@ public abstract class AbstractVerify implements protected T syncBeforeVerify(T t) { // 认证源根据配置文件不同调用不同SDK 1放心签、2创蓝 String source = EnvironmentUtils.getProperty("alita.authenticationSource"); - int authenticationSource = DEFAULT_TYPE; + int authenticationSource = FactorVerificationSourceTypeEnum.CL.getType(); try { authenticationSource = Integer.parseInt(source); - //如果不是这两种认证源,用默认的源 - if (!(FactorVerificationSourceTypeEnum.CL.getType().equals(authenticationSource) - || FactorVerificationSourceTypeEnum.FXQ.getType().equals(authenticationSource))) { - authenticationSource = DEFAULT_TYPE; - } } catch (NumberFormatException e) { //doNothing } diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/ali/ALiVerifySourceServiceImpl.java b/src/main/java/com/newyetai/alitaforward/verification/source/ali/ALiVerifySourceServiceImpl.java new file mode 100644 index 0000000..29794e4 --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/ali/ALiVerifySourceServiceImpl.java @@ -0,0 +1,67 @@ +package com.newyetai.alitaforward.verification.source.ali; + +import cn.hutool.json.JSONUtil; +import com.newyetai.alitaforward.verification.constants.FactorVerificationSourceTypeEnum; +import com.newyetai.alitaforward.verification.dto.FactorVerificationDTO; +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.alitaforward.verification.source.FactorVerificationSourceService; +import com.newyetai.alitaforward.verification.source.ali.mapstruct.AliVerifyMapMapper; +import com.newyetai.common.AlitaResult; +import com.newyetai.common.constant.AuthStatusEnum; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.ali.dto.IdCardReq; +import com.newyetai.sdk.ali.dto.IdCardRes; +import com.newyetai.sdk.ali.service.AliVerifyService; +import com.newyetai.sdk.common.constant.SdkConstants; +import java.util.Objects; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + + +@Slf4j +@Service +@SuppressWarnings("unchecked") +public class ALiVerifySourceServiceImpl implements FactorVerificationSourceService { + + @Resource(name = AliVerifyService.BEAN_ID) + private AliVerifyService aliVerifyService; + + @Override + public RealNameTwoFactorVerificationDTO twoVerify(RealNameTwoFactorVerificationDTO verificationDTO) { + IdCardReq requestDTO = AliVerifyMapMapper.INSTANCE.toDTO(verificationDTO); + log.info("二要素认证:{}", JSONUtil.toJsonStr(requestDTO)); + AlitaResult result = aliVerifyService.verify(requestDTO); + handlerResult(result, verificationDTO); + return verificationDTO; + } + + + + private void handlerResult(AlitaResult result, FactorVerificationDTO verificationDTO) { + verificationDTO.setInvokeData(JsonUtils.toJsonString(result)); + AuthStatusEnum targetStatus = null; + if (SdkConstants.SDK_INVOKE_NOT_REACH_CODE.equals(result.getCode())) { + // 接口调起失败,未拿到返回结果,视为未调起 + verificationDTO.setFailReason("调用异常,未调起第三方"); + } else { + if (Boolean.TRUE.equals(result.getSuccess())) { + targetStatus = AuthStatusEnum.AUTH_SUCCESS; + } else { + targetStatus = AuthStatusEnum.AUTH_FAIL; + verificationDTO.setFailReason(result.getMsg()); + } + } + if (Objects.nonNull(targetStatus)) { + verificationDTO.setStatus(targetStatus.getType()); + } + } + + + + + @Override + public FactorVerificationSourceTypeEnum getSourceType() { + return FactorVerificationSourceTypeEnum.ALI; + } +} diff --git a/src/main/java/com/newyetai/alitaforward/verification/source/ali/mapstruct/AliVerifyMapMapper.java b/src/main/java/com/newyetai/alitaforward/verification/source/ali/mapstruct/AliVerifyMapMapper.java new file mode 100644 index 0000000..d7331ff --- /dev/null +++ b/src/main/java/com/newyetai/alitaforward/verification/source/ali/mapstruct/AliVerifyMapMapper.java @@ -0,0 +1,24 @@ +package com.newyetai.alitaforward.verification.source.ali.mapstruct; + +import com.newyetai.alitaforward.verification.dto.RealNameTwoFactorVerificationDTO; +import com.newyetai.sdk.ali.dto.IdCardReq; +import com.newyetai.sdk.chuanglan.dto.RealNameTwoBaseRequestDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + + +@Mapper +public interface AliVerifyMapMapper { + + AliVerifyMapMapper INSTANCE = Mappers.getMapper(AliVerifyMapMapper.class); + + @Mappings(value = { + @Mapping(target = "name", source = "dto.realName"), + @Mapping(target = "idcard", source = "dto.cardNo") + }) + IdCardReq toDTO(RealNameTwoFactorVerificationDTO dto); + + +} diff --git a/src/main/java/com/newyetai/common/util/StrUtils.java b/src/main/java/com/newyetai/common/util/StrUtils.java index 5026a47..673b1cf 100644 --- a/src/main/java/com/newyetai/common/util/StrUtils.java +++ b/src/main/java/com/newyetai/common/util/StrUtils.java @@ -17,7 +17,7 @@ public class StrUtils { /** * 大驼峰转小驼峰(AaBb -> aaBb) - * + * * @param upperCamel * @return * @author sr on 2021-02-03 @@ -30,7 +30,7 @@ public class StrUtils { /** * 驼峰转蛇形(AaBb -> aa_bb) - * + * * @param upperCamel * @return * @author sr on 2021-02-03 @@ -57,6 +57,17 @@ public class StrUtils { * @author sr on 2022-02-10 */ public static String buildAscQueryValue(Object paramData) { + return buildAscQueryValue(paramData, true, null); + } + + /** + * @param paramData 参数 + * @param normal 是否正常(p1=v1&p2=v2) + * @param split 特殊分隔符(v1分隔符v2) + * @return + * @author sr on 2024-11-18 + */ + public static String buildAscQueryValue(Object paramData, boolean normal, String split) { Map paramDataMap = null; if (paramData instanceof Map) { paramDataMap = paramDataMap; @@ -82,12 +93,52 @@ public class StrUtils { } StringBuilder paramstr = new StringBuilder(); for (Entry entry : parameters.entrySet()) { - paramstr.append(entry.getKey()).append(CommonConstants.EQUAL) - .append(entry.getValue()).append(CommonConstants.AND); + if (normal) { + paramstr.append(entry.getKey()).append(CommonConstants.EQUAL) + .append(entry.getValue()).append(CommonConstants.AND); + } else { + paramstr.append(entry.getValue()).append(split); + } + } + + return paramstr.substring(0, paramstr.length() - 1); + } + + + /** + * 构建参数字符串(xx=**&xx=**) + * @param paramData + * @return + * @author sr on 2024-11-18 + */ + public static String buildQueryValue(Object paramData) { + Map paramDataMap = null; + if (paramData instanceof Map) { + paramDataMap = paramDataMap; + } else { + try { + paramDataMap = JsonUtils.objToClassObj(paramData, Map.class); + } catch (Exception e) { + throw new BusinessException("参数对象格式错误"); + } + } + if (paramDataMap == null || paramDataMap.isEmpty()) { + return null; + } + StringBuilder paramstr = new StringBuilder(); + for (Entry entry : paramDataMap.entrySet()) { + Object value = entry.getValue(); + if (value != null) { + paramstr.append(entry.getKey()).append(CommonConstants.EQUAL) + .append(entry.getValue()).append(CommonConstants.AND); + } + } + if (paramstr.length() == 0) { + return null; } return paramstr.substring(0, paramstr.length() - 1); } - + /** * 不为空/空字符串/"null"字符串 * @param str @@ -97,5 +148,5 @@ public class StrUtils { public static boolean isNotNull(String str) { return StringUtils.isNotBlank(str) && !"null".equals(str); } - + } diff --git a/src/main/java/com/newyetai/sdk/ali/config/AliProperties.java b/src/main/java/com/newyetai/sdk/ali/config/AliProperties.java new file mode 100644 index 0000000..3a96b40 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/config/AliProperties.java @@ -0,0 +1,45 @@ +package com.newyetai.sdk.ali.config; + +import com.newyetai.sdk.chuanglan.config.ChuangLanCommonProperties; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Builder.Default; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + + +@ConfigurationProperties(prefix = AliProperties.PREFIX) +@Data +@Component +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class AliProperties { + + /** 配置前缀 */ + public static final String PREFIX = "ali"; + public static final String IDCARD_PREFIX = PREFIX + ".idcard"; + + /** 二要素配置 */ + private IdcardProperties idcard; + + @Data + @NoArgsConstructor + @AllArgsConstructor + @Builder + public static class IdcardProperties { + + /** 是否启用 **/ + @Default + private Boolean enable = Boolean.FALSE; + /** 次数限制 **/ + private Long numLimit; + private String url; + /** */ + private String appcode; + + } + +} diff --git a/src/main/java/com/newyetai/sdk/ali/dto/IdCardReq.java b/src/main/java/com/newyetai/sdk/ali/dto/IdCardReq.java new file mode 100644 index 0000000..149fa6c --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/dto/IdCardReq.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.ali.dto; + +import com.newyetai.sdk.common.dto.ISdkRequest; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.core.ParameterizedTypeReference; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IdCardReq implements ISdkRequest> { + + private static ParameterizedTypeReference> type = new ParameterizedTypeReference>() { + }; + + private String name; + private String idcard; + + @Override + public ParameterizedTypeReference> getResponseType() { + return type; + } + +} diff --git a/src/main/java/com/newyetai/sdk/ali/dto/IdCardRes.java b/src/main/java/com/newyetai/sdk/ali/dto/IdCardRes.java new file mode 100644 index 0000000..2a56c40 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/dto/IdCardRes.java @@ -0,0 +1,27 @@ +package com.newyetai.sdk.ali.dto; + +import java.io.Serializable; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class IdCardRes implements Serializable { + + /** code为200 data才会有值,400参数格式错误 */ + public static final Integer SUC_CODE = 200; + /** 1.不一致 0.一致 */ + public static final Integer SUC_RESULT = 0; + + private String birthday; + private Integer result; + private String address; + private String orderNo; + private String sex; + private String desc; + +} diff --git a/src/main/java/com/newyetai/sdk/ali/dto/VerifyRes.java b/src/main/java/com/newyetai/sdk/ali/dto/VerifyRes.java new file mode 100644 index 0000000..10f7c7a --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/dto/VerifyRes.java @@ -0,0 +1,17 @@ +package com.newyetai.sdk.ali.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class VerifyRes { + + private String msg; + private String success; + private Integer code; + private T data; + +} diff --git a/src/main/java/com/newyetai/sdk/ali/service/AliVerifyService.java b/src/main/java/com/newyetai/sdk/ali/service/AliVerifyService.java new file mode 100644 index 0000000..5124cd1 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/service/AliVerifyService.java @@ -0,0 +1,14 @@ +package com.newyetai.sdk.ali.service; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.ali.dto.IdCardReq; +import com.newyetai.sdk.ali.dto.IdCardRes; + +public interface AliVerifyService { + + String BEAN_ID = "sdk.aliVerifyService"; + String MOCK_BEAN_ID = "mock.aliVerifyService"; + + AlitaResult verify(IdCardReq req); + +} diff --git a/src/main/java/com/newyetai/sdk/ali/service/impl/AliVerifyServiceImpl.java b/src/main/java/com/newyetai/sdk/ali/service/impl/AliVerifyServiceImpl.java new file mode 100644 index 0000000..1ea9fb0 --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/service/impl/AliVerifyServiceImpl.java @@ -0,0 +1,78 @@ +package com.newyetai.sdk.ali.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.annotation.CheckAndMock; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.common.util.StrUtils; +import com.newyetai.sdk.ali.config.AliProperties; +import com.newyetai.sdk.ali.config.AliProperties.IdcardProperties; +import com.newyetai.sdk.ali.dto.IdCardReq; +import com.newyetai.sdk.ali.dto.IdCardRes; +import com.newyetai.sdk.ali.dto.VerifyRes; +import com.newyetai.sdk.ali.service.AliVerifyService; +import com.newyetai.sdk.common.constant.SdkConstants; +import com.newyetai.sdk.common.dto.DefaultSdkInvokeLogDTO; +import com.newyetai.sdk.common.util.HttpUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +@Slf4j +@Service(AliVerifyService.BEAN_ID) +public class AliVerifyServiceImpl implements AliVerifyService { + + private static RestTemplate restTemplate = HttpUtils.restTemplate; + @Autowired + private AliProperties aliProperties; + + @Override + @CheckAndMock(mockClass = MockAliVerifyServiceImpl.class, + propertyPrefix = AliProperties.IDCARD_PREFIX) + public AlitaResult verify(IdCardReq req){ + return this.verify(req, aliProperties.getIdcard()); + } + + public static AlitaResult verify(IdCardReq req, IdcardProperties idcardProperties){ + VerifyRes res = null; + + try { + try { + // 构建请求头 + HttpHeaders header = new HttpHeaders(); + header.add("Authorization", "APPCODE " + idcardProperties.getAppcode()); + header.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + // 发送请求 + HttpEntity requestEntity = new HttpEntity(StrUtils.buildQueryValue(req), header); + + ResponseEntity> result = restTemplate.exchange(idcardProperties.getUrl(), + HttpMethod.POST, requestEntity, req.getResponseType()); + res = result.getBody(); + } catch (Exception e) { + log.info("invoke error :{}", e); + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_ERROR_CODE, e.getMessage()); + } + try { + if (IdCardRes.SUC_CODE.equals(res.getCode()) && IdCardRes.SUC_RESULT.equals(res.getData().getResult())) { + return AlitaResult.success(res.getData()); + } + return AlitaResult.error(SdkConstants.SDK_HTTP_INVOKE_RESPONSE_FAIL_CODE, + res.getCode() + res.getData().getDesc()); + } catch (Exception e) { + return AlitaResult.error(SdkConstants.SDK_RESPONSE_CONVERT_ERROR_CODE, + e.getMessage()); + } + } finally { + log.info("invoke:{}", + JsonUtils + .toJsonString( + DefaultSdkInvokeLogDTO.builder().requestData(req).responseData(res) + .build())); + } + } + +} diff --git a/src/main/java/com/newyetai/sdk/ali/service/impl/MockAliVerifyServiceImpl.java b/src/main/java/com/newyetai/sdk/ali/service/impl/MockAliVerifyServiceImpl.java new file mode 100644 index 0000000..f5297ee --- /dev/null +++ b/src/main/java/com/newyetai/sdk/ali/service/impl/MockAliVerifyServiceImpl.java @@ -0,0 +1,19 @@ +package com.newyetai.sdk.ali.service.impl; + +import com.newyetai.common.AlitaResult; +import com.newyetai.sdk.ali.dto.IdCardReq; +import com.newyetai.sdk.ali.dto.IdCardRes; +import com.newyetai.sdk.ali.service.AliVerifyService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service(AliVerifyService.MOCK_BEAN_ID) +public class MockAliVerifyServiceImpl implements AliVerifyService { + + @Override + public AlitaResult verify(IdCardReq req) { + log.info("ali idcard mock..."); + return AlitaResult.success(IdCardRes.builder().result(IdCardRes.SUC_RESULT).build()); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4a958c0..c89e838 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -52,7 +52,7 @@ file.storage.ali.bucketName=newyetai #发号器 #机器id:根据ip自己定义 -code.snowflake.workid.192.168.31.234=23 +code.snowflake.workid.192.168.31.135=23 code.snowflake.workid.121.37.2.171=1 code.snowflake.workid.139.159.237.199=2 code.snowflake.workid.192.168.3.2=4 @@ -144,16 +144,13 @@ sms.numLimit=300000 #短信验证码模板配置 sms.phoneSms=SMS_478425358 -## 创蓝账号配置 -chuanglan.enable=true -chuanglan.phone=13816929046 -chuanglan.domain=https://api.253.com -chuanglan.appId=BkDWu80l -chuanglan.appSecret=Lvy1s1hu -## 创蓝实名认证(基础二要素)开关、次数配置 -chuanglan.realName2Base.enable=false -chuanglan.realName2Base.url=/open/idcard/id-card-auth -chuanglan.realName2Base.numLimit=1 +#默认认证源:1fxq,2cl,4ali +alita.authenticationSource=4 +#阿里二要素认证 +ali.idcard.enable=true +ali.idcard.url=https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check +ali.idcard.appcode=728e8c05167a482093418707ca22822b + #讯飞配置 xf.httpAPIPassword=EiORVeNtBjFOcUSKXanT:oIVlTRNhWcEDpksviZaG diff --git a/src/test/java/com/newyetai/AliVerifyTest.java b/src/test/java/com/newyetai/AliVerifyTest.java new file mode 100644 index 0000000..23392e1 --- /dev/null +++ b/src/test/java/com/newyetai/AliVerifyTest.java @@ -0,0 +1,26 @@ +package com.newyetai; + +import com.newyetai.common.AlitaResult; +import com.newyetai.common.util.JsonUtils; +import com.newyetai.sdk.ali.config.AliProperties.IdcardProperties; +import com.newyetai.sdk.ali.dto.IdCardReq; +import com.newyetai.sdk.ali.dto.IdCardRes; +import com.newyetai.sdk.ali.service.impl.AliVerifyServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; + +@Slf4j +public class AliVerifyTest { + + public static IdcardProperties idcardProperties = IdcardProperties.builder() + .url("https://kzidcardv1.market.alicloudapi.com/api-mall/api/id_card/check") + .appcode("728e8c05167a482093418707ca22822b").build(); + + @Test + public void idcard() { + IdCardReq req = IdCardReq.builder().name("吴国东").idcard("210221197907106318").build(); + AlitaResult result = AliVerifyServiceImpl.verify(req, idcardProperties); + log.info("{}", JsonUtils.toJsonString(result)); + } + +}