f
This commit is contained in:
@@ -781,28 +781,26 @@ func buildRiskWarning(apiData map[string]interface{}, log *zap.Logger) map[strin
|
||||
if yysy9e4aData != nil && yysyData != nil {
|
||||
if yysy9e4aMap, ok := yysy9e4aData.(map[string]interface{}); ok {
|
||||
if yysyMap, ok := yysyData.(map[string]interface{}); ok {
|
||||
// 从身份证号获取省份(前2位)
|
||||
var idCardProvince string
|
||||
// 从身份证号获取地址
|
||||
var idCardAddress string
|
||||
if address, ok := yysyMap["address"].(string); ok && address != "" {
|
||||
// 从地址中提取省份(简化处理,取前2-3个字符)
|
||||
if len(address) >= 2 {
|
||||
idCardProvince = address[:2]
|
||||
// 处理"省"字
|
||||
idCardProvince = strings.TrimSuffix(idCardProvince, "省")
|
||||
}
|
||||
idCardAddress = address
|
||||
}
|
||||
|
||||
// 从手机号归属地获取省份
|
||||
var phoneProvince string
|
||||
// 从手机号归属地获取省份和城市
|
||||
var phoneProvince, phoneCity string
|
||||
if provinceName, ok := yysy9e4aMap["provinceName"].(string); ok {
|
||||
phoneProvince = provinceName
|
||||
// 处理"省"字
|
||||
phoneProvince = strings.TrimSuffix(phoneProvince, "省")
|
||||
}
|
||||
if cityName, ok := yysy9e4aMap["cityName"].(string); ok {
|
||||
phoneCity = cityName
|
||||
}
|
||||
|
||||
// 判断省份是否一致
|
||||
if idCardProvince != "" && phoneProvince != "" && idCardProvince != phoneProvince {
|
||||
riskWarning["idCardPhoneProvinceMismatch"] = 1
|
||||
// 使用智能比较函数判断是否一致
|
||||
if idCardAddress != "" && phoneProvince != "" {
|
||||
if !compareLocation(idCardAddress, phoneProvince, phoneCity) {
|
||||
riskWarning["idCardPhoneProvinceMismatch"] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1483,33 +1481,11 @@ func buildElementVerificationDetail(apiData map[string]interface{}, log *zap.Log
|
||||
if yysyMapForBelong, ok := yysyDataForBelong.(map[string]interface{}); ok {
|
||||
// 从身份证号地址获取省份和城市
|
||||
var personProvince, personCity string
|
||||
var idCardAddress string
|
||||
if address, ok := yysyMapForBelong["address"].(string); ok && address != "" {
|
||||
// 解析地址,提取省份和城市
|
||||
// 格式通常是:省份+市+县/区
|
||||
parts := strings.Split(address, "省")
|
||||
if len(parts) > 1 {
|
||||
personProvince = parts[0] + "省"
|
||||
cityPart := parts[1]
|
||||
if strings.Contains(cityPart, "市") {
|
||||
cityParts := strings.Split(cityPart, "市")
|
||||
if len(cityParts) > 0 {
|
||||
personCity = cityParts[0] + "市"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 尝试其他格式
|
||||
if strings.Contains(address, "省") {
|
||||
provinceEnd := strings.Index(address, "省")
|
||||
personProvince = address[:provinceEnd+1]
|
||||
if provinceEnd+1 < len(address) {
|
||||
cityPart := address[provinceEnd+1:]
|
||||
if strings.Contains(cityPart, "市") {
|
||||
cityEnd := strings.Index(cityPart, "市")
|
||||
personCity = cityPart[:cityEnd+1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
idCardAddress = address
|
||||
personProvince = extractProvinceFromAddress(address)
|
||||
personCity = extractCityFromAddress(address)
|
||||
}
|
||||
|
||||
// 从手机号归属地获取省份和城市
|
||||
@@ -1533,15 +1509,12 @@ func buildElementVerificationDetail(apiData map[string]interface{}, log *zap.Log
|
||||
belongRisks["phoneCardType"] = convertChannel(channel)
|
||||
}
|
||||
|
||||
// 判断归属地是否一致
|
||||
if personProvince != "" && phoneProvince != "" {
|
||||
// 标准化省份名称(去除"省"字后比较)
|
||||
personProvinceNorm := strings.TrimSuffix(personProvince, "省")
|
||||
phoneProvinceNorm := strings.TrimSuffix(phoneProvince, "省")
|
||||
if personProvinceNorm != phoneProvinceNorm {
|
||||
detail["belongRiskFlag"] = 1 // 高风险
|
||||
// 判断归属地是否一致(使用智能比较函数)
|
||||
if idCardAddress != "" && phoneProvince != "" {
|
||||
if compareLocation(idCardAddress, phoneProvince, phoneCity) {
|
||||
detail["belongRiskFlag"] = 2 // 低风险(一致)
|
||||
} else {
|
||||
detail["belongRiskFlag"] = 2 // 低风险
|
||||
detail["belongRiskFlag"] = 1 // 高风险(不一致)
|
||||
}
|
||||
} else {
|
||||
detail["belongRiskFlag"] = 0 // 未查得
|
||||
@@ -3162,19 +3135,19 @@ func buildTimeLoanPerformances(variableValue map[string]interface{}) []interface
|
||||
|
||||
// checkLoanRisk 检查借贷风险
|
||||
func checkLoanRisk(variableValue map[string]interface{}) bool {
|
||||
// 检查近期申请频率是否过高
|
||||
// 检查近期申请频率是否过高(调高风险阈值:从>=5提高到>=10)
|
||||
periods := []string{"d7", "d15", "m1", "m3"}
|
||||
for _, period := range periods {
|
||||
bankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_bank_allnum", period))
|
||||
nbankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_nbank_allnum", period))
|
||||
|
||||
if bankAllnum != "" && bankAllnum != "0" {
|
||||
if count, err := strconv.Atoi(bankAllnum); err == nil && count >= 5 {
|
||||
if count, err := strconv.Atoi(bankAllnum); err == nil && count >= 10 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if nbankAllnum != "" && nbankAllnum != "0" {
|
||||
if count, err := strconv.Atoi(nbankAllnum); err == nil && count >= 5 {
|
||||
if count, err := strconv.Atoi(nbankAllnum); err == nil && count >= 10 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -3610,15 +3583,15 @@ func checkRecentApplicationFrequency(variableValue map[string]interface{}, riskW
|
||||
bankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_bank_allnum", period.apiPeriod))
|
||||
nbankAllnum := getStringValue(variableValue, fmt.Sprintf("als_%s_id_nbank_allnum", period.apiPeriod))
|
||||
|
||||
// 如果近7天申请次数>=5,认为是极为频繁
|
||||
// 如果近7天申请次数>=10,认为是极为频繁(调高风险阈值,进一步提高阈值)
|
||||
if bankAllnum != "" && bankAllnum != "0" {
|
||||
if count, err := strconv.Atoi(bankAllnum); err == nil && count >= 5 {
|
||||
if count, err := strconv.Atoi(bankAllnum); err == nil && count >= 10 {
|
||||
(*riskWarning)[period.field] = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if nbankAllnum != "" && nbankAllnum != "0" {
|
||||
if count, err := strconv.Atoi(nbankAllnum); err == nil && count >= 5 {
|
||||
if count, err := strconv.Atoi(nbankAllnum); err == nil && count >= 10 {
|
||||
(*riskWarning)[period.field] = 1
|
||||
break
|
||||
}
|
||||
@@ -3655,17 +3628,17 @@ func checkBankApplicationFrequency(variableValue map[string]interface{}, riskWar
|
||||
}
|
||||
}
|
||||
|
||||
// 银行申请次数极多(>=10)
|
||||
if bankTotal >= 10 {
|
||||
// 银行申请次数极多(>=20,调高风险阈值,进一步提高阈值)
|
||||
if bankTotal >= 20 {
|
||||
(*riskWarning)["frequentBankApplications"] = 1
|
||||
} else if bankTotal >= 5 {
|
||||
} else if bankTotal >= 15 {
|
||||
(*riskWarning)["moreFrequentBankApplications"] = 1
|
||||
}
|
||||
|
||||
// 非银申请次数极多(>=10)
|
||||
if nbankTotal >= 10 {
|
||||
// 非银申请次数极多(>=20,调高风险阈值,进一步提高阈值)
|
||||
if nbankTotal >= 20 {
|
||||
(*riskWarning)["frequentNonBankApplications"] = 1
|
||||
} else if nbankTotal >= 5 {
|
||||
} else if nbankTotal >= 15 {
|
||||
(*riskWarning)["moreFrequentNonBankApplications"] = 1
|
||||
}
|
||||
}
|
||||
@@ -3756,11 +3729,11 @@ func checkRentalApplicationFrequency(jrzq1d09Map map[string]interface{}, riskWar
|
||||
}
|
||||
}
|
||||
|
||||
// 租赁申请次数极多(>=10)
|
||||
if totalCount >= 10 {
|
||||
// 租赁申请次数极多(>=20,调高风险阈值,进一步提高阈值)
|
||||
if totalCount >= 20 {
|
||||
(*riskWarning)["veryFrequentRentalApplications"] = 1
|
||||
(*riskWarning)["frequentRentalApplications"] = 1
|
||||
} else if totalCount >= 5 {
|
||||
} else if totalCount >= 15 {
|
||||
(*riskWarning)["frequentRentalApplications"] = 1
|
||||
}
|
||||
}
|
||||
@@ -4011,6 +3984,208 @@ func getPhoneArea(mobile string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// normalizeProvinceName 标准化省份名称,用于比较
|
||||
// 处理各种格式:广西壮族自治区 -> 广西,北京市 -> 北京,内蒙古自治区 -> 内蒙古等
|
||||
func normalizeProvinceName(province string) string {
|
||||
if province == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 去除前后空格
|
||||
province = strings.TrimSpace(province)
|
||||
|
||||
// 特殊处理:内蒙古(必须在最前面)
|
||||
if strings.Contains(province, "内蒙古") {
|
||||
return "内蒙古"
|
||||
}
|
||||
|
||||
// 处理自治区、特别行政区、直辖市等后缀
|
||||
suffixes := []string{
|
||||
"壮族自治区", "回族自治区", "维吾尔自治区", "自治区",
|
||||
"特别行政区", "省", "市",
|
||||
}
|
||||
|
||||
normalized := province
|
||||
for _, suffix := range suffixes {
|
||||
if strings.HasSuffix(normalized, suffix) {
|
||||
normalized = strings.TrimSuffix(normalized, suffix)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
// normalizeCityName 标准化城市名称,用于比较
|
||||
// 处理各种格式:南宁地区 -> 南宁,南宁市 -> 南宁等
|
||||
func normalizeCityName(city string) string {
|
||||
if city == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 去除前后空格
|
||||
city = strings.TrimSpace(city)
|
||||
|
||||
// 处理各种后缀
|
||||
suffixes := []string{
|
||||
"地区", "市", "自治州", "盟", "县", "区",
|
||||
}
|
||||
|
||||
normalized := city
|
||||
for _, suffix := range suffixes {
|
||||
if strings.HasSuffix(normalized, suffix) {
|
||||
normalized = strings.TrimSuffix(normalized, suffix)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return normalized
|
||||
}
|
||||
|
||||
// extractProvinceFromAddress 从完整地址中提取省份名称
|
||||
func extractProvinceFromAddress(address string) string {
|
||||
if address == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 特殊处理:内蒙古(必须在最前面,因为"内蒙古"可能被其他模式误匹配)
|
||||
if strings.HasPrefix(address, "内蒙古") {
|
||||
return "内蒙古自治区"
|
||||
}
|
||||
|
||||
// 处理直辖市(必须在自治区之前)
|
||||
if strings.HasPrefix(address, "北京") {
|
||||
return "北京市"
|
||||
}
|
||||
if strings.HasPrefix(address, "上海") {
|
||||
return "上海市"
|
||||
}
|
||||
if strings.HasPrefix(address, "天津") {
|
||||
return "天津市"
|
||||
}
|
||||
if strings.HasPrefix(address, "重庆") {
|
||||
return "重庆市"
|
||||
}
|
||||
|
||||
// 处理各种省份格式(按长度从长到短,避免误匹配)
|
||||
patterns := []struct {
|
||||
pattern string
|
||||
extract func(string) string
|
||||
}{
|
||||
// 处理"XX壮族自治区"格式(最长,优先匹配)
|
||||
{"壮族自治区", func(addr string) string {
|
||||
if idx := strings.Index(addr, "壮族自治区"); idx > 0 {
|
||||
return addr[:idx+len("壮族自治区")]
|
||||
}
|
||||
return ""
|
||||
}},
|
||||
// 处理"XX回族自治区"格式
|
||||
{"回族自治区", func(addr string) string {
|
||||
if idx := strings.Index(addr, "回族自治区"); idx > 0 {
|
||||
return addr[:idx+len("回族自治区")]
|
||||
}
|
||||
return ""
|
||||
}},
|
||||
// 处理"XX维吾尔自治区"格式
|
||||
{"维吾尔自治区", func(addr string) string {
|
||||
if idx := strings.Index(addr, "维吾尔自治区"); idx > 0 {
|
||||
return addr[:idx+len("维吾尔自治区")]
|
||||
}
|
||||
return ""
|
||||
}},
|
||||
// 处理"XX特别行政区"格式
|
||||
{"特别行政区", func(addr string) string {
|
||||
if idx := strings.Index(addr, "特别行政区"); idx > 0 {
|
||||
return addr[:idx+len("特别行政区")]
|
||||
}
|
||||
return ""
|
||||
}},
|
||||
// 处理"XX自治区"格式(如西藏、宁夏,必须在其他自治区之后)
|
||||
{"自治区", func(addr string) string {
|
||||
if idx := strings.Index(addr, "自治区"); idx > 0 {
|
||||
return addr[:idx+len("自治区")]
|
||||
}
|
||||
return ""
|
||||
}},
|
||||
// 处理"XX省"格式(最后处理,因为可能与其他模式冲突)
|
||||
{"省", func(addr string) string {
|
||||
if idx := strings.Index(addr, "省"); idx > 0 {
|
||||
return addr[:idx+1]
|
||||
}
|
||||
return ""
|
||||
}},
|
||||
}
|
||||
|
||||
for _, p := range patterns {
|
||||
if strings.Contains(address, p.pattern) {
|
||||
if result := p.extract(address); result != "" {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// extractCityFromAddress 从完整地址中提取城市名称
|
||||
func extractCityFromAddress(address string) string {
|
||||
if address == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 先提取省份,然后从剩余部分提取城市
|
||||
province := extractProvinceFromAddress(address)
|
||||
if province == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 去除省份部分
|
||||
cityPart := address[len(province):]
|
||||
|
||||
// 处理各种城市格式
|
||||
patterns := []string{"地区", "市", "自治州", "盟"}
|
||||
for _, pattern := range patterns {
|
||||
if idx := strings.Index(cityPart, pattern); idx > 0 {
|
||||
return cityPart[:idx+len(pattern)]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// compareLocation 比较两个地址是否一致(省份和城市)
|
||||
// 使用号码归属地(格式:省份-城市)去匹配户籍所在地
|
||||
// 如果号码归属地中的省份和城市都出现在户籍所在地中,则认为一致
|
||||
// 返回true表示一致,false表示不一致
|
||||
func compareLocation(address1, province2, city2 string) bool {
|
||||
if address1 == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 如果号码归属地只有省份,检查省份是否出现在户籍所在地中
|
||||
if province2 != "" && city2 == "" {
|
||||
// 标准化省份名称,去除后缀
|
||||
province2Norm := normalizeProvinceName(province2)
|
||||
// 检查标准化后的省份名称是否出现在户籍所在地中
|
||||
return strings.Contains(address1, province2Norm)
|
||||
}
|
||||
|
||||
// 如果号码归属地有省份和城市,检查两者是否都出现在户籍所在地中
|
||||
if province2 != "" && city2 != "" {
|
||||
// 标准化省份和城市名称,去除后缀
|
||||
province2Norm := normalizeProvinceName(province2)
|
||||
city2Norm := normalizeCityName(city2)
|
||||
|
||||
// 检查省份和城市是否都出现在户籍所在地中
|
||||
provinceMatch := strings.Contains(address1, province2Norm)
|
||||
cityMatch := strings.Contains(address1, city2Norm)
|
||||
|
||||
return provinceMatch && cityMatch
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func convertChannel(channel string) string {
|
||||
channelMap := map[string]string{
|
||||
"cmcc": "中国移动",
|
||||
|
||||
Reference in New Issue
Block a user