Commit 8e4bb7aa authored by liwenbin's avatar liwenbin

新城活体判断和量子分3缺失不推

parent 045a95b9
......@@ -40,4 +40,9 @@ public class RedisKeyConstants {
* 助贷资方审核订单缓存KEY
*/
public static final String AID_FUND_AUDIT_ORDER_KEY = "ASSET.DISTRIBUTE:AID_FUND_AUDIT_ORDER:BY_BIZ_NO_AND_FUND_ID:AKVVS3:";
/**
* 助贷资方每日渠道限制
*/
public static final String AID_FUND_PUSH_ORDER_DAY_LIMIT_KEY = "ASSET.DISTRIBUTE:AID_FUND_PUSH_ORDER_DAY_LIMIT:KAM91A:";
}
......@@ -98,14 +98,14 @@ public class AidUserInfo implements Serializable {
private String livePhotoContent;
/**
* 活体类型,0-腾讯
* 活体类型,0-腾讯, 1-face
*/
private Integer liveType;
/**
* 活体分值
*/
private TencentLiveEntity liveResult;
private Object liveResult;
private String companyName;
......
package com.quantgroup.asset.distribution.model.entity.live;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : FaceLiveEntity
* @date : 2020/7/23 2:30 下午
*/
@Data
public class FaceLiveEntity implements Serializable {
private static final long serialVersionUID = 1L;
private Double confidence; //(人脸比对分数)比对结果的置信度,取值[0,100], 数字越大表示两张照片越可能是同一个人。
private ThresholdsEntity thresholds;
}
package com.quantgroup.asset.distribution.model.entity.live;
import com.alibaba.fastjson.annotation.JSONField;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import java.io.Serializable;
/**
* @author : Hyuk
* @description : ThresholdsEntity
* @date : 2020/7/23 2:31 下午
*/
@Data
public class ThresholdsEntity implements Serializable {
private static final long serialVersionUID = 1L;
@JSONField(name = "1e-3")
@SerializedName("1e-3")
private Double _1e3; //(置信度阈值)误识率为千分之一的置信度阈值
@JSONField(name = "1e-5")
@SerializedName("1e-5")
private Double _1e5; //(置信度阈值)误识率为万分之一的置信度阈值
@JSONField(name = "1e-4")
@SerializedName("1e-4")
private Double _1e4; //(置信度阈值)误识率为十万分之一的置信度阈值
@JSONField(name = "1e-6")
@SerializedName("1e-6")
private Double _1e6; //(置信度阈值)误识率为百万分之一的置信度阈值
}
......@@ -20,6 +20,7 @@ import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.entity.OcrIdCardEntity;
import com.quantgroup.asset.distribution.model.entity.aid.*;
import com.quantgroup.asset.distribution.model.entity.live.FaceLiveEntity;
import com.quantgroup.asset.distribution.model.entity.live.TencentLiveEntity;
import com.quantgroup.asset.distribution.model.entity.user.SDKUserInfo;
import com.quantgroup.asset.distribution.model.entity.user.UserAddressInfo;
......@@ -234,12 +235,21 @@ public class AidAssetCommonServiceImpl implements IAidAssetCommonService {
aidUserInfo.setIdCardBaseContentA(ocrIdCardEntity.getIdCardBaseContentA());
aidUserInfo.setIdCardBaseContentB(ocrIdCardEntity.getIdCardBaseContentB());
aidUserInfo.setLivePhotoContent(ocrIdCardEntity.getLivePhotoContent());
aidUserInfo.setEmail(sdkUserInfo.getEmail());
// 0-腾讯, 增加了就去写个枚举
aidUserInfo.setLiveType(0);
// 0-腾讯 1-商汤 2-face++ 3-linkface
int liveType = 0;
TencentLiveEntity tencentLiveEntity = getTencentLiveEntity(uuid);
if (tencentLiveEntity != null) {
aidUserInfo.setLiveResult(tencentLiveEntity);
aidUserInfo.setEmail(sdkUserInfo.getEmail());
} else {
FaceLiveEntity faceLiveEntity = getFaceLiveEntity(uuid);
if (faceLiveEntity != null) {
liveType = 2;
aidUserInfo.setLiveResult(faceLiveEntity);
}
}
aidUserInfo.setLiveType(liveType);
return aidUserInfo;
}
......@@ -280,8 +290,10 @@ public class AidAssetCommonServiceImpl implements IAidAssetCommonService {
* @return
*/
private AidRiskInfo createdAidRiskInfo(AssetForm assetForm, Map<String, Object> data) {
String[] riskInfoKeys = {AidRiskInfoConstants.QG_SCORE3, AidRiskInfoConstants.QG_SCORE5, AidRiskInfoConstants.QG_DEBT_PAYING_SCORE,
AidRiskInfoConstants.QG_RISK_LEVEL_PHONE, AidRiskInfoConstants.QG_RISK_LEVEL_IDNO};
String[] riskInfoKeys = {AidRiskInfoConstants.QG_SCORE3,
// AidRiskInfoConstants.QG_SCORE5, AidRiskInfoConstants.QG_DEBT_PAYING_SCORE,
// AidRiskInfoConstants.QG_RISK_LEVEL_PHONE, AidRiskInfoConstants.QG_RISK_LEVEL_IDNO
};
Set<String> keys = new HashSet<>();
for (String riskInfoKey : riskInfoKeys) {
......@@ -295,10 +307,10 @@ public class AidAssetCommonServiceImpl implements IAidAssetCommonService {
return AidRiskInfo.builder()
.label(1)
.qgScore3(data.get(AidRiskInfoConstants.QG_SCORE3))
.qgScore5(data.get(AidRiskInfoConstants.QG_SCORE5))
.qgDebtPayingScore(transformZhiShuConsumeLevel(data.get(AidRiskInfoConstants.QG_DEBT_PAYING_SCORE)))
.qgRiskLevelPhone(data.get(AidRiskInfoConstants.QG_RISK_LEVEL_PHONE))
.qgRiskLevelIdNo(data.get(AidRiskInfoConstants.QG_RISK_LEVEL_IDNO))
// .qgScore5(data.get(AidRiskInfoConstants.QG_SCORE5))
// .qgDebtPayingScore(transformZhiShuConsumeLevel(data.get(AidRiskInfoConstants.QG_DEBT_PAYING_SCORE)))
// .qgRiskLevelPhone(data.get(AidRiskInfoConstants.QG_RISK_LEVEL_PHONE))
// .qgRiskLevelIdNo(data.get(AidRiskInfoConstants.QG_RISK_LEVEL_IDNO))
.build();
}
......@@ -321,10 +333,34 @@ public class AidAssetCommonServiceImpl implements IAidAssetCommonService {
if ("0".equals(data.getString("code")) && "0".equals(data.getString("business_code"))) {
return JSON.parseObject(data.getString("data"), TencentLiveEntity.class);
}
return null;
// 这里为空抛一下异常, 理论上来说是不正常的, 因为都是自己的渠道, 之后增加其他活体类型, 再放到前筛里面去
throw new QGException(QGExceptionType.LIVE_DATA_ERROR, uuid);
// throw new QGException(QGExceptionType.LIVE_DATA_ERROR, uuid);
}
/**
* 获取Face活体
* @param uuid
* @return
*/
private FaceLiveEntity getFaceLiveEntity(String uuid) {
String url = operatorDomain + "/auth-center/ex/face/getOcrData.json";
Map<String, String> params = new HashMap<>();
params.put("uuid", uuid);
// 以后增加活体类型记得增加枚举
params.put("liveType", "face");
String result = httpService.post(url, params);
JSONObject data = JSON.parseObject(result);
QGPreconditions.checkArgument(data != null , QGExceptionType.LIVE_DATA_ERROR, uuid);
if ("0".equals(data.getString("code")) && "0".equals(data.getString("business_code"))) {
return JSON.parseObject(data.getString("data"), FaceLiveEntity.class);
}
return null;
}
/**
* 创建包装助贷资方对象
* @param fundId
......
......@@ -3,11 +3,13 @@ package com.quantgroup.asset.distribution.service.funding.impl;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Stopwatch;
import com.quantgroup.asset.distribution.constant.AidFundStatus;
import com.quantgroup.asset.distribution.constant.aid.AidRiskInfoConstants;
import com.quantgroup.asset.distribution.enums.UserLoanType;
import com.quantgroup.asset.distribution.exception.QGExceptionType;
import com.quantgroup.asset.distribution.exception.QGPreconditions;
import com.quantgroup.asset.distribution.model.form.AssetForm;
import com.quantgroup.asset.distribution.model.response.GlobalResponse;
import com.quantgroup.asset.distribution.service.feature.IFeatureService;
import com.quantgroup.asset.distribution.service.funding.*;
import com.quantgroup.asset.distribution.service.jpa.entity.AidLoanFundAuditOrder;
import com.quantgroup.asset.distribution.service.jpa.entity.AidLoanFundConfig;
......@@ -25,10 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
......@@ -58,6 +57,8 @@ public class AidFundRouteServiceImpl implements IAidFundRouteService {
private IAidFundAssetService aidFundAssetService;
@Autowired
private IAidFundAuditOrderService aidFundAuditOrderService;
@Autowired
private IFeatureService featureService;
/**
* 助贷资金路由
......@@ -79,13 +80,13 @@ public class AidFundRouteServiceImpl implements IAidFundRouteService {
//第二步 开关筛选
if(CollectionUtils.isNotEmpty(aidLoanFundConfigList))
aidLoanFundConfigList = aidLoanFundConfigList.parallelStream().filter(aidLoanFundConfig->aidLoanFundConfig.getFundSwitchState()==1).collect(Collectors.toList());
//第三步 限制次数筛选
if(CollectionUtils.isNotEmpty(aidLoanFundConfigList)){
// AID_LOAN_COUNT_LIMIT_KEY + DateUtil.getDay() //TODO 放redis
aidLoanFundConfigList = aidLoanFundConfigList.parallelStream()
.filter(aidLoanFundConfig->aidLoanFundConfig.getFundCountLimit() >=redisService.setIncr(AID_LOAN_COUNT_LIMIT_KEY + DateUtil.getDay(), 1, 3, TimeUnit.DAYS))
.collect(Collectors.toList());
}
// //第三步 限制次数筛选, 改成按资方筛选
// if(CollectionUtils.isNotEmpty(aidLoanFundConfigList)){
// // AID_LOAN_COUNT_LIMIT_KEY + DateUtil.getDay() //TODO 放redis
// aidLoanFundConfigList = aidLoanFundConfigList.parallelStream()
// .filter(aidLoanFundConfig->aidLoanFundConfig.getFundCountLimit() >=redisService.setIncr(AID_LOAN_COUNT_LIMIT_KEY + DateUtil.getDay(), 1, 3, TimeUnit.DAYS))
// .collect(Collectors.toList());
// }
//第四步 限制总额度筛选 额度筛选暂时没有用到
// if(CollectionUtils.isNotEmpty(aidLoanFundConfigList)){
// // 获取已放款总金额 AID_LOAN_ALL_AMOUNT_LIMIT_KEY + DateUtil.getDay() //TODO 放redis
......@@ -103,7 +104,6 @@ public class AidFundRouteServiceImpl implements IAidFundRouteService {
aidLoanFundConfigSet.addAll(aidLoanFundConfigList);
for(AidLoanFundConfig aidLoanFundConfig : aidLoanFundConfigSet){
//此助贷资方如果已经被这笔订单路由过 就跳过
AidLoanFundRouteRecord aidLoanFundRouteRecord = iAidFundRouteRecordService.findByBizNoAndFundId(assetForm.getBizNo(), aidLoanFundConfig.getFundId());
int status = aidLoanFundRouteRecord == null ? -1 : aidLoanFundRouteRecord.getAidFundRouteStatus().intValue();
......@@ -114,12 +114,19 @@ public class AidFundRouteServiceImpl implements IAidFundRouteService {
//助贷资金分配规则校验
if(ruleService.valid(aidLoanFundConfig.getFundRuleEl(), data)){
// 分配规则二次校验, md主要是风控的需求无法用表达式去满足, 特征值为null的居然让结果为true
if (!secondValid(data, aidLoanFundConfig, asset)) { continue; }
if (!secondValid(data, aidLoanFundConfig, asset, assetForm)) { continue; }
// 助贷资金准入接口调用
boolean accessResult = false;
if (status == AidFundStatus.Route.PRE_PASS) {
accessResult = true;
} else {
// 调用次数限制
long increment = redisService.setIncr(AID_FUND_PUSH_ORDER_DAY_LIMIT_KEY + aidLoanFundConfig.getFundId() + ":" + DateUtil.getDay(), 1, 2, TimeUnit.DAYS);
if (increment > aidLoanFundConfig.getFundCountLimit()) {
redisService.setIncr(AID_FUND_PUSH_ORDER_DAY_LIMIT_KEY + aidLoanFundConfig.getFundId() + ":" + DateUtil.getDay(), -1, 2, TimeUnit.DAYS);
continue;
}
accessResult = aidFundAssetService.preAudit(assetForm, aidLoanFundConfig.getFundId(), aidLoanFundConfig.getFundProductId(), data);
// 保存主贷资金路由记录
aidLoanFundRouteRecord = new AidLoanFundRouteRecord();
......@@ -206,9 +213,10 @@ public class AidFundRouteServiceImpl implements IAidFundRouteService {
* @param data
* @param aidLoanFundConfig
* @param asset
* @param assetForm
* @return
*/
private boolean secondValid(Map<String, Object> data, AidLoanFundConfig aidLoanFundConfig, Asset asset) {
private boolean secondValid(Map<String, Object> data, AidLoanFundConfig aidLoanFundConfig, Asset asset, AssetForm assetForm) {
boolean valid = true;
if ("970".equals(aidLoanFundConfig.getFundId()) && "1052".equals(aidLoanFundConfig.getFundProductId())) {
// 你我贷助贷资方
......@@ -237,10 +245,29 @@ public class AidFundRouteServiceImpl implements IAidFundRouteService {
valid = false;
}
// 这里针对每个助贷资方单独打印一下为啥不导的日志
// 这里提前走, 节省数据费用
if (!valid) {
log.info("助贷资方导流, 用户命中二次校验规则, 不进行导流, uuid : {}, fundId : {}, fundProductId : {}, userAge : {}, province : {}",
asset.getUuid(), aidLoanFundConfig.getFundId(), aidLoanFundConfig.getFundProductId(), age, province);
return valid;
}
// 3、量子分3缺失的不导
if (data.get(AidRiskInfoConstants.QG_SCORE3) == null) {
Set<String> keys = new HashSet<>();
keys.add(AidRiskInfoConstants.QG_SCORE3);
Map<String, Object> features = featureService.getFeatureData(keys, assetForm, 1);
data.putAll(features);
}
String qgScore3 = String.valueOf(data.get(AidRiskInfoConstants.QG_SCORE3));
if (qgScore3 == null || qgScore3.startsWith("-999999")) {
valid = false;
}
if (!valid) {
log.info("助贷资方导流, 用户命中二次校验规则, 不进行导流, uuid : {}, fundId : {}, fundProductId : {}, userAge : {}, province : {}, qgScore3 : {}",
asset.getUuid(), aidLoanFundConfig.getFundId(), aidLoanFundConfig.getFundProductId(), age, province, qgScore3);
}
}
return valid;
......
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