tianyuan-api-server/apps/api/internal/logic/COMB/comb86pmlogic.go
2025-07-25 15:57:48 +08:00

296 lines
9.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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: "MOB032", ServiceId: "FLXG54F5", Mapping: westmodel.FLXG54F5FieldMapping, Wrap: "", Service: "yushan"}, // 手机号码风险
{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,
}
}
if apiRequests[i].SourceId == "MOB032" {
apiRequests[i].Request = map[string]interface{}{
"mobile": data.MobileNo,
}
}
}
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 {
if req.SourceId == "G22SC01" {
resultResp, parseErr := common.ParseJsonResponse(respData)
if parseErr != nil {
westResp = "{}"
} else {
westResp = string(resultResp) // 用于后续的 JSON 验证和处理
}
} 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
}