From b2c89a2c694a1a16c6583544cf1f78246471cc78 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Fri, 25 Jul 2025 12:28:27 +0800 Subject: [PATCH] add comb86pm --- apps/api/api.api | 3 + .../internal/handler/COMB/comb86pmhandler.go | 31 ++ apps/api/internal/handler/routes.go | 7 +- apps/api/internal/logic/COMB/comb298ylogic.go | 18 +- apps/api/internal/logic/COMB/comb86pmlogic.go | 281 ++++++++++++++++++ apps/api/internal/types/types.go | 2 +- apps/api/internal/validator/structs.go | 7 + apps/api/internal/westmodel/fieldMapping.go | 2 +- 8 files changed, 339 insertions(+), 12 deletions(-) create mode 100644 apps/api/internal/handler/COMB/comb86pmhandler.go create mode 100644 apps/api/internal/logic/COMB/comb86pmlogic.go diff --git a/apps/api/api.api b/apps/api/api.api index 3112d3b..5a60587 100644 --- a/apps/api/api.api +++ b/apps/api/api.api @@ -167,5 +167,8 @@ service api-api { service api-api { @handler COMB298Y post /COMB298Y (request) returns (string) + + @handler COMB86PM + post /COMB86P (request) returns (string) } diff --git a/apps/api/internal/handler/COMB/comb86pmhandler.go b/apps/api/internal/handler/COMB/comb86pmhandler.go new file mode 100644 index 0000000..1a2bd88 --- /dev/null +++ b/apps/api/internal/handler/COMB/comb86pmhandler.go @@ -0,0 +1,31 @@ +package COMB + +import ( + "net/http" + + "tianyuan-api/apps/api/internal/logic/COMB" + "tianyuan-api/apps/api/internal/svc" + "tianyuan-api/apps/api/internal/types" + "tianyuan-api/pkg/errs" + "tianyuan-api/pkg/response" + + "github.com/zeromicro/go-zero/rest/httpx" +) + +func COMB86PMHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.Request + if err := httpx.Parse(r, &req); err != nil { + response.Fail(r.Context(), w, errs.ErrParamValidation, nil) + return + } + + l := COMB.NewCOMB86PMLogic(r.Context(), svcCtx) + resp, err := l.COMB86PM(&req) + if err != nil { + response.Fail(r.Context(), w, err, resp) + } else { + response.Success(r.Context(), w, resp) + } + } +} diff --git a/apps/api/internal/handler/routes.go b/apps/api/internal/handler/routes.go index 54a2ca7..041bd18 100644 --- a/apps/api/internal/handler/routes.go +++ b/apps/api/internal/handler/routes.go @@ -1,5 +1,5 @@ // Code generated by goctl. DO NOT EDIT. -// goctl 1.7.3 +// goctl 1.8.4 package handler @@ -27,6 +27,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/COMB298Y", Handler: COMB.COMB298YHandler(serverCtx), }, + { + Method: http.MethodPost, + Path: "/COMB86P", + Handler: COMB.COMB86PMHandler(serverCtx), + }, }..., ), rest.WithPrefix("/api/v1"), diff --git a/apps/api/internal/logic/COMB/comb298ylogic.go b/apps/api/internal/logic/COMB/comb298ylogic.go index 9f8a066..397c7c4 100644 --- a/apps/api/internal/logic/COMB/comb298ylogic.go +++ b/apps/api/internal/logic/COMB/comb298ylogic.go @@ -109,15 +109,15 @@ func (l *COMB298YLogic) COMB298Y(req *types.Request) (resp string, err *errs.App // 准备并发请求 apiRequests := []APIRequest{ - {SourceId: "G16BJ02", ServiceId: "YYSY09CD", Mapping: westmodel.YYSY09CDFieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G27BJ05", ServiceId: "JRZQ0A03", Mapping: westmodel.JRZQ0A03FieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G28BJ05", ServiceId: "JRZQ8203", Mapping: westmodel.JRZQ8203FieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G26BJ05", ServiceId: "FLXG3D56", Mapping: westmodel.FLXG3D56FieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G22SC01", ServiceId: "FLXGCA3D", Mapping: westmodel.FLXGCA3DFieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G29BJ05", ServiceId: "JRZQ4AA8", Mapping: westmodel.JRZQ4AA8FieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G30BJ05", ServiceId: "FLXGC9D1", Mapping: westmodel.FLXGC9D1FieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "G32BJ05", ServiceId: "FLXG162A", Mapping: westmodel.FLXG162AFieldMapping, Wrap: "data", Service: "west"}, - {SourceId: "RIS031", ServiceId: "FLXG8UI0", Mapping: westmodel.FLXG8UI0FieldMapping, Wrap: "", Service: "yushan"}, + {SourceId: "G16BJ02", ServiceId: "YYSY09CD", Mapping: westmodel.YYSY09CDFieldMapping, Wrap: "data", Service: "west"}, // 运营商三要素简版 + {SourceId: "G27BJ05", ServiceId: "JRZQ0A03", Mapping: westmodel.JRZQ0A03FieldMapping, Wrap: "data", Service: "west"}, // 借贷意向 + {SourceId: "G28BJ05", ServiceId: "JRZQ8203", Mapping: westmodel.JRZQ8203FieldMapping, Wrap: "data", Service: "west"}, // 借贷行为 + {SourceId: "G26BJ05", ServiceId: "FLXG3D56", Mapping: westmodel.FLXG3D56FieldMapping, Wrap: "data", Service: "west"}, // 特殊名单 + {SourceId: "G22SC01", ServiceId: "FLXGCA3D", Mapping: westmodel.FLXGCA3DFieldMapping, Wrap: "data", Service: "west"}, // 综合涉诉 + {SourceId: "G29BJ05", ServiceId: "JRZQ4AA8", Mapping: westmodel.JRZQ4AA8FieldMapping, Wrap: "data", Service: "west"}, // 偿贷压力 + {SourceId: "G30BJ05", ServiceId: "FLXGC9D1", Mapping: westmodel.FLXGC9D1FieldMapping, Wrap: "data", Service: "west"}, // 黑灰产等级 + {SourceId: "G32BJ05", ServiceId: "FLXG162A", Mapping: westmodel.FLXG162AFieldMapping, Wrap: "data", Service: "west"}, // 团伙欺诈 + {SourceId: "RIS031", ServiceId: "FLXG0687", Mapping: westmodel.FLXG0687FieldMapping, Wrap: "", Service: "yushan"}, // 反赌反诈 {SourceId: "G09XM02", ServiceId: "IVYZ5733", Mapping: westmodel.IVYZ5733FieldMapping, Wrap: "data", Service: "west"}, {SourceId: "G11BJ06", ServiceId: "IVYZ9A2B", Mapping: westmodel.IVYZ9A2BFieldMapping, Wrap: "data", Service: "west"}, {SourceId: "G03HZ01", ServiceId: "FLXG54F5", Mapping: westmodel.FLXG54F5FieldMapping, Wrap: "data", Service: "west"}, diff --git a/apps/api/internal/logic/COMB/comb86pmlogic.go b/apps/api/internal/logic/COMB/comb86pmlogic.go new file mode 100644 index 0000000..7ff1046 --- /dev/null +++ b/apps/api/internal/logic/COMB/comb86pmlogic.go @@ -0,0 +1,281 @@ +package COMB + +import ( + "context" + "encoding/hex" + "encoding/json" + "sync" + + "tianyuan-api/apps/api/internal/common" + "tianyuan-api/apps/api/internal/svc" + "tianyuan-api/apps/api/internal/types" + "tianyuan-api/apps/api/internal/validator" + "tianyuan-api/apps/api/internal/westmodel" + "tianyuan-api/pkg/crypto" + "tianyuan-api/pkg/errs" + + "github.com/zeromicro/go-zero/core/logx" +) + +type COMB86PMLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewCOMB86PMLogic(ctx context.Context, svcCtx *svc.ServiceContext) *COMB86PMLogic { + return &COMB86PMLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *COMB86PMLogic) COMB86PM(req *types.Request) (resp string, err *errs.AppError) { + var status string + var charges bool + var remark = "" + secretKey, ok := l.ctx.Value("secretKey").(string) + if !ok { + return "", errs.ErrSystem + } + transactionID, ok := l.ctx.Value("transactionID").(string) + if !ok { + return "", errs.ErrSystem + } + userId, userIdOk := l.ctx.Value("userId").(int64) + if !userIdOk { + return "", errs.ErrSystem + } + productCode, productCodeOk := l.ctx.Value("productCode").(string) + if !productCodeOk || productCode == "" { + return "", errs.ErrSystem + } + + defer func() { + if err != nil { + status = "failed" + charges = false + } else { + status = "success" + charges = true + } + sendApiRequestMessageErr := l.svcCtx.ApiRequestMqsService.SendApiRequestMessage(l.ctx, transactionID, userId, productCode, status, charges, remark) + if sendApiRequestMessageErr != nil { + logx.Errorf("发送 API 请求消息失败: %v", err) + } + }() + // 1、解密 + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return "", errs.ErrSystem + } + decryptData, aesDecryptErr := crypto.AesDecrypt(req.Data, key) + if aesDecryptErr != nil || len(decryptData) == 0 { + return "", errs.ErrParamDecryption + } + + // 2、校验 + var data validator.COMB86PMRequest + if validatorErr := validator.ValidateAndParse(decryptData, &data); validatorErr != nil { + return "", errs.ErrParamValidation + } + + // 准备并发请求 + apiRequests := []APIRequest{ + {SourceId: "G31BJ05", ServiceId: "FLXG9687", Mapping: westmodel.FLXG9687FieldMapping, Wrap: "data", Service: "west"}, // 电诈风险预警 + {SourceId: "RIS031", ServiceId: "FLXG0687", Mapping: westmodel.FLXG0687FieldMapping, Wrap: "", Service: "yushan"}, // 反赌反诈 + {SourceId: "G03HZ01", ServiceId: "FLXG54F5", Mapping: westmodel.FLXG54F5FieldMapping, Wrap: "data", Service: "west"}, // 手机号码风险 + {SourceId: "G22SC01", ServiceId: "FLXG0V4B", Mapping: westmodel.FLXG0V4BFieldMapping, Wrap: "data", Service: "west"}, // 个人涉诉 + {SourceId: "G27BJ05", ServiceId: "JRZQ0A03", Mapping: westmodel.JRZQ0A03FieldMapping, Wrap: "data", Service: "west"}, // 借贷意向 + {SourceId: "G28BJ05", ServiceId: "JRZQ8203", Mapping: westmodel.JRZQ8203FieldMapping, Wrap: "data", Service: "west"}, // 借贷行为 + {SourceId: "G26BJ05", ServiceId: "FLXG3D56", Mapping: westmodel.FLXG3D56FieldMapping, Wrap: "data", Service: "west"}, // 特殊名单 + {SourceId: "G09XM02", ServiceId: "IVYZ5733", Mapping: westmodel.IVYZ5733FieldMapping, Wrap: "data", Service: "west"}, // 单人婚姻 + {SourceId: "G15BJ02", ServiceId: "YYSY6F2E", Mapping: westmodel.YYSY6F2EFieldMapping, Wrap: "data", Service: "west"}, // 运营商三要素详版 + } + + // 为每个请求构建对应的请求参数 + for i := range apiRequests { + if apiRequests[i].Service == "west" { + // 西部服务:先加密后mapping + westConfig := l.svcCtx.Config.WestConfig + if apiRequests[i].SourceId == "G05HZ01" { + // G05HZ01 不需要加密,直接使用原始数据 + dataMap, err := common.StructToMap(data) + if err != nil { + logx.Errorf("结构体转map失败:%v", err) + return "", errs.ErrSystem + } + logx.Infof("G05HZ01 原始数据: %+v", data) + logx.Infof("G05HZ01 转换后数据: %+v", dataMap) + apiRequests[i].Request = common.MapStructToAPIRequest(dataMap, apiRequests[i].Mapping, apiRequests[i].Wrap) + logx.Infof("G05HZ01 最终请求数据: %+v", apiRequests[i].Request) + } else { + // 其他西部服务需要加密 + encryptedRequest, encryptErr := common.EncryptStructFields(data, westConfig.Key) + if encryptErr != nil { + logx.Errorf("西部加密错误:%v", encryptErr) + return "", errs.ErrSystem + } + apiRequests[i].Request = common.MapStructToAPIRequest(encryptedRequest, apiRequests[i].Mapping, apiRequests[i].Wrap) + } + } else { + // 如果是 RIS031,添加 type: 3 + if apiRequests[i].SourceId == "RIS031" { + apiRequests[i].Request = map[string]interface{}{ + "keyWord": data.IDCard, + "type": 3, + } + } + } + logx.Infof("sourceId:%s,请求参数:%v", apiRequests[i].SourceId, apiRequests[i].Request) + } + + // 创建响应通道 + responseChan := make(chan APIResponse, len(apiRequests)) + var wg sync.WaitGroup + + // 并发处理请求 + for _, apiReq := range apiRequests { + wg.Add(1) + go func(req APIRequest) { + defer wg.Done() + success := true + var westResp string + var callAPIErr *errs.AppError + + // 根据服务类型选择不同的调用方式 + switch req.Service { + case "west": + // 4、发送请求到西部 + logx.Infof("交易号:%s", transactionID) + var respData []byte + if req.SourceId == "G05HZ01" { + respData, callAPIErr = l.svcCtx.WestDexService.CallAPISecond(req.SourceId, req.Request, l.svcCtx.Config.WestConfig.SecretSecondId) + } else { + respData, callAPIErr = l.svcCtx.WestDexService.CallAPI(req.SourceId, req.Request, l.svcCtx.Config.WestConfig.SecretId) + } + if callAPIErr != nil { + if callAPIErr.Code == errs.ErrDataSource.Code { + // 数据源错误(如查询无结果)是业务正常情况,记录为 info + logx.Infof("西部请求业务状态:sourceId:%s, resp:%v", req.SourceId, respData) + var jsonCheck interface{} + if json.Unmarshal(respData, &jsonCheck) != nil { + westResp = "{}" + } else { + westResp = string(respData) + } + } else { + // 其他业务错误 + logx.Errorf("西部请求业务错误:sourceId:%s,err:%v, resp:%v", req.SourceId, callAPIErr, respData) + westResp = "{}" + } + } else { + // 确保返回的是有效的 JSON + if len(respData) == 0 { + westResp = "{}" + } else { + // 验证 JSON 是否有效 + var jsonCheck interface{} + if json.Unmarshal(respData, &jsonCheck) != nil { + westResp = "{}" + } else { + westResp = string(respData) + } + } + } + case "yushan": + respData, err := l.svcCtx.YushanService.Request(req.SourceId, req.Request) + if err != nil { + logx.Errorf("羽山请求失败:sourceId:%s,err:%v", req.SourceId, err) + if appErr, ok := err.(*errs.AppError); ok { + callAPIErr = appErr + } else { + callAPIErr = errs.ErrSystem + } + westResp = "{}" // 发生错误时返回空对象 + } else { + // 确保返回的是有效的 JSON + if len(respData) == 0 { + westResp = "{}" + } else { + // 验证 JSON 是否有效 + var jsonCheck interface{} + if json.Unmarshal(respData, &jsonCheck) != nil { + westResp = "{}" + } else { + westResp = string(respData) + } + } + } + default: + success = false + westResp = "{}" + logx.Errorf("未知的服务类型:%s", req.Service) + } + + if callAPIErr != nil { + success = false + } + + // 确保响应是有效的 JSON + var jsonResp json.RawMessage + if err := json.Unmarshal([]byte(westResp), &jsonResp); err != nil { + jsonResp = json.RawMessage("{}") + } + + responseChan <- APIResponse{ + ServiceId: req.ServiceId, + Resp: jsonResp, + Success: success, + } + }(apiReq) + } + + // 等待所有请求完成 + go func() { + wg.Wait() + close(responseChan) + }() + + // 处理响应 + var responses []APIResponse + for resp := range responseChan { + responses = append(responses, resp) + } + + responseData := ResponseData{ + Responses: make([]struct { + ServiceId string `json:"api_code"` + Data json.RawMessage `json:"data"` + Success bool `json:"success"` + }, len(responses)), + } + + for i, resp := range responses { + responseData.Responses[i] = struct { + ServiceId string `json:"api_code"` + Data json.RawMessage `json:"data"` + Success bool `json:"success"` + }{ + ServiceId: resp.ServiceId, + Data: resp.Resp, + Success: resp.Success, + } + } + + // 将响应数据转换为JSON + jsonData, marshalErr := json.Marshal(responseData) + if marshalErr != nil { + logx.Errorf("JSON编码错误:%v", marshalErr) + return "", errs.ErrSystem + } + + // 加密JSON数据 + encryptData, aesEncrypt := crypto.AesEncrypt(jsonData, key) + if aesEncrypt != nil { + return "", errs.ErrSystem + } + + return string(encryptData), nil +} diff --git a/apps/api/internal/types/types.go b/apps/api/internal/types/types.go index 12de7fe..96f1db0 100644 --- a/apps/api/internal/types/types.go +++ b/apps/api/internal/types/types.go @@ -1,5 +1,5 @@ // Code generated by goctl. DO NOT EDIT. -// goctl 1.7.3 +// goctl 1.8.4 package types diff --git a/apps/api/internal/validator/structs.go b/apps/api/internal/validator/structs.go index e76c9e4..ee46762 100644 --- a/apps/api/internal/validator/structs.go +++ b/apps/api/internal/validator/structs.go @@ -171,3 +171,10 @@ type COMB298YRequest struct { MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` AuthDate string `json:"auth_date" validate:"required,validAuthDate" encrypt:"false"` } + +type COMB86PMRequest struct { + IDCard string `json:"id_card" validate:"required,validIDCard"` + Name string `json:"name" validate:"required,min=1,validName"` + MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"` + AuthDate string `json:"auth_date" validate:"required,validAuthDate" encrypt:"false"` +} diff --git a/apps/api/internal/westmodel/fieldMapping.go b/apps/api/internal/westmodel/fieldMapping.go index 48c8b2a..7fd4a69 100644 --- a/apps/api/internal/westmodel/fieldMapping.go +++ b/apps/api/internal/westmodel/fieldMapping.go @@ -51,7 +51,7 @@ var FLXGDEC7FieldMapping = map[string]string{ "IDCard": "id_card", "Name": "name", } -var FLXG8UI0FieldMapping = map[string]string{ +var FLXG0687FieldMapping = map[string]string{ "IDCard": "keyWord", } var IVYZ385EFieldMapping = map[string]string{