This commit is contained in:
2026-02-14 17:42:59 +08:00
parent 2c57ac0dab
commit fb495bc0ca

View File

@@ -781,32 +781,30 @@ 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 {
// 使用智能比较函数判断是否一致
if idCardAddress != "" && phoneProvince != "" {
if !compareLocation(idCardAddress, phoneProvince, phoneCity) {
riskWarning["idCardPhoneProvinceMismatch"] = 1
}
}
}
}
}
// ========== 公安重点人员核验风险 ==========
flxgdea9Data := getMapValue(apiData, "FLXGDEA9")
@@ -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": "中国移动",