This commit is contained in:
2026-05-28 12:23:05 +08:00
66 changed files with 4954 additions and 430 deletions

View File

@@ -249,7 +249,8 @@ type IVYZZQT3Req struct {
type IVYZZQ3BReq struct {
Name string `json:"name" validate:"required,min=1,validName"`
IDCard string `json:"id_card" validate:"required,validIDCard"`
ImageUrl string `json:"image_url" validate:"required,url"`
PhotoData string `json:"photo_data" validate:"omitempty,validBase64Image"`
ImageUrl string `json:"image_url" validate:"omitempty,url"`
Authorized string `json:"authorized" validate:"required,oneof=0 1"`
}
@@ -357,6 +358,11 @@ type QCXGGB2QReq struct {
Name string `json:"name" validate:"required,min=1,validName"`
CarPlateType string `json:"carplate_type" validate:"required"`
}
type QCXGM4CLReq struct {
IDCard string `json:"id_card" validate:"required,validIDCard"`
}
type QCXGJJ2AReq struct {
VinCode string `json:"vin_code" validate:"required"`
EngineNumber string `json:"engine_number" validate:"omitempty"`
@@ -487,6 +493,30 @@ type IVYZ2A8BReq struct {
Authorized string `json:"authorized" validate:"required,oneof=0 1"`
}
type QYGL4YABReq struct {
EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"`
LegalPerson string `json:"legal_person" validate:"required,min=1,validName"`
EntCode string `json:"ent_code" validate:"required,validUSCI"`
IDCard string `json:"id_card" validate:"required,validIDCard"`
}
type QYGL3YSBReq struct {
EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"`
LegalPerson string `json:"legal_person" validate:"required,min=1,validName"`
EntCode string `json:"ent_code" validate:"required,validUSCI"`
}
type QYGL2YSBReq struct {
LegalPerson string `json:"legal_person" validate:"required,min=1,validName"`
EntCode string `json:"ent_code" validate:"required,validUSCI"`
}
type QYGLDG77Req struct {
EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"`
AccountNo string `json:"account_no" validate:"required,min=1,"`
AccountBank string `json:"account_bank" validate:"required,min=1,"`
}
type IVYZ7C9DReq struct {
IDCard string `json:"id_card" validate:"required,validIDCard"`
Name string `json:"name" validate:"required,min=1,validName"`
@@ -533,6 +563,12 @@ type IVYZ4Y27Req struct {
IDCard string `json:"id_card" validate:"required,validIDCard"`
AuthAuthorizeFileBase64 string `json:"auth_authorize_file_base64" validate:"required,validBase64PDF"`
}
type FLXGHB4FReq struct {
Name string `json:"name" validate:"required,min=1,validName"`
IDCard string `json:"id_card" validate:"required,validIDCard"`
}
type IVYZP2Q6Req struct {
Name string `json:"name" validate:"required,min=1,validName"`
IDCard string `json:"id_card" validate:"required,validIDCard"`
@@ -571,6 +607,10 @@ type QYGL5A3CReq struct {
PageNum int64 `json:"page_num" validate:"omitempty,min=1"`
}
type QYGLBH7YReq struct {
EntName string `json:"ent_name" validate:"omitempty,min=1,validEnterpriseName"`
}
type QYGL2naoReq struct {
EntCode string `json:"ent_code" validate:"required,validUSCI"`
PageSize int64 `json:"page_size" validate:"omitempty,min=1,max=100"`

View File

@@ -24,6 +24,7 @@ import (
"tyapi-server/internal/infrastructure/external/huibo"
"tyapi-server/internal/infrastructure/external/jiguang"
"tyapi-server/internal/infrastructure/external/muzi"
"tyapi-server/internal/infrastructure/external/nuoer"
"tyapi-server/internal/infrastructure/external/shujubao"
"tyapi-server/internal/infrastructure/external/shumai"
"tyapi-server/internal/infrastructure/external/tianyancha"
@@ -68,6 +69,7 @@ func NewApiRequestService(
jiguangService *jiguang.JiguangService,
shumaiService *shumai.ShumaiService,
huiboService *huibo.HuiboService,
nuoerService *nuoer.NuoerService,
validator interfaces.RequestValidator,
productManagementService *services.ProductManagementService,
cfg *appconfig.Config,
@@ -84,6 +86,7 @@ func NewApiRequestService(
jiguangService,
shumaiService,
huiboService,
nuoerService,
validator,
productManagementService,
cfg,
@@ -105,6 +108,7 @@ func NewApiRequestServiceWithRepos(
jiguangService *jiguang.JiguangService,
shumaiService *shumai.ShumaiService,
huiboService *huibo.HuiboService,
nuoerService *nuoer.NuoerService,
validator interfaces.RequestValidator,
productManagementService *services.ProductManagementService,
cfg *appconfig.Config,
@@ -132,6 +136,7 @@ func NewApiRequestServiceWithRepos(
jiguangService,
shumaiService,
huiboService,
nuoerService,
validator,
combService,
reportRepo,
@@ -186,6 +191,7 @@ func registerAllProcessors(combService *comb.CombService) {
"FLXG3A9B": flxg.ProcessFLXG3A9BRequest,
"FLXGK5D2": flxg.ProcessFLXGK5D2Request,
"FLXGDJG3": flxg.ProcessFLXGDJG3Request, //董监高司法综合信息核验
"FLXGHB4F": flxg.ProcessFLXGHB4FRequest, //个人涉诉案件查询汇博
// JRZQ系列处理器
"JRZQ8203": jrzq.ProcessJRZQ8203Request,
"JRZQ0A03": jrzq.ProcessJRZQ0A03Request,
@@ -254,7 +260,11 @@ func registerAllProcessors(combService *comb.CombService) {
"QYGLDJ12": qygl.ProcessQYGLDJ12Request, //企业年报信息核验
"QYGL8848": qygl.ProcessQYGL8848Request, //企业税收违法核查
"QYGLDJ33": qygl.ProcessQYGLDJ33Request, //企业年报信息核验
"QYGLBH7Y": qygl.ProcessQYGLBH7YRequest, //企业涉诉案件查询汇博
"QYGL4YAB": qygl.ProcessQYGL4YABRequest, //企业四要素认证shumai
"QYGL3YSB": qygl.ProcessQYGL3YSBRequest, //企业三要素认证shumai
"QYGL2YSB": qygl.ProcessQYGL2YSBRequest, //企业二要素认证shumai
"QYGLDG77": qygl.ProcessQYGLDG77Request, //企业对公打款认证shumai
// YYSY系列处理器
"YYSY35TA": yysy.ProcessYYSY35TARequest, //运营商归属地数卖
"YYSYD50F": yysy.ProcessYYSYD50FRequest,
@@ -373,7 +383,7 @@ func registerAllProcessors(combService *comb.CombService) {
"QCXG5U0Z": qcxg.ProcessQCXG5U0ZRequest, // 车辆静态信息查询 10479
"QCXGY7F2": qcxg.ProcessQCXGY7F2Request, // 二手车VIN估值 10443
"QCXG3M7Z": qcxg.ProcessQCXG3M7ZRequest, //人车关系核验ETC10093 月更
"QCXGM4CL": qcxg.ProcessQCXGM4CLRequest, //名下车辆诺尔
// DWBG系列处理器 - 多维报告
"DWBG6A2C": dwbg.ProcessDWBG6A2CRequest,
"DWBG8B4D": dwbg.ProcessDWBG8B4DRequest,

View File

@@ -281,6 +281,13 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string
"IVYZRAX1": &dto.IVYZRAX1Req{}, //融安信用分
"IVYZRAX2": &dto.IVYZRAX1Req{}, //融御反欺诈
"IVYZ2MN7": &dto.IVYZ2MN6Req{}, //学历Bzhicha
"FLXGHB4F": &dto.FLXGHB4FReq{}, //个人涉诉案件查询汇博
"QYGLBH7Y": &dto.QYGLBH7YReq{}, //企业涉诉案件查询汇博
"QYGL4YAB": &dto.QYGL4YABReq{}, //企业四要素认证shumai
"QYGL3YSB": &dto.QYGL3YSBReq{}, //企业三要素认证shumai
"QYGL2YSB": &dto.QYGL2YSBReq{}, //企业二要素认证shumai
"QYGLDG77": &dto.QYGLDG77Req{}, //企业对公打款认证shumai
"QCXGM4CL": &dto.QCXGM4CLReq{}, //名下车辆诺尔
}
// 优先返回已配置的DTO
@@ -513,6 +520,8 @@ func (s *FormConfigServiceImpl) generateFieldLabel(jsonTag string) string {
"plate_color": "车牌颜色",
"marital_type": "婚姻状况类型",
"auth_authorize_file_base64": "PDF授权文件Base64编码≤500KB仅PDF",
"account_no": "企业账户",
"account_bank": "开户行",
}
if label, exists := labelMap[jsonTag]; exists {
@@ -579,6 +588,8 @@ func (s *FormConfigServiceImpl) generateExampleValue(fieldType reflect.Type, jso
"plate_color": "0",
"marital_type": "10",
"auth_authorize_file_base64": "JVBERi0xLjQKJcTl8uXr...示例PDF的Base64编码",
"account_no": "6222021234567890123",
"account_bank": "中国工商银行",
}
if example, exists := exampleMap[jsonTag]; exists {
@@ -654,6 +665,8 @@ func (s *FormConfigServiceImpl) generatePlaceholder(jsonTag string, fieldType st
"plate_color": "请输入车牌颜色",
"marital_type": "请选择婚姻状况类型",
"auth_authorize_file_base64": "请输入PDF文件的Base64编码字符串",
"account_no": "请输入企业账户",
"account_bank": "请输入开户行",
}
if placeholder, exists := placeholderMap[jsonTag]; exists {
@@ -731,6 +744,8 @@ func (s *FormConfigServiceImpl) generateDescription(jsonTag string, validation s
"plate_color": "车牌颜色",
"marital_type": "婚姻状况类型10-未登记无登记记录20-已婚30-丧偶40-离异",
"auth_authorize_file_base64": "请输入PDF文件的Base64编码字符串",
"account_no": "请输入企业账户",
"account_bank": "请输入开户行",
}
if desc, exists := descMap[jsonTag]; exists {

View File

@@ -9,6 +9,7 @@ import (
"tyapi-server/internal/infrastructure/external/huibo"
"tyapi-server/internal/infrastructure/external/jiguang"
"tyapi-server/internal/infrastructure/external/muzi"
"tyapi-server/internal/infrastructure/external/nuoer"
"tyapi-server/internal/infrastructure/external/shujubao"
"tyapi-server/internal/infrastructure/external/shumai"
"tyapi-server/internal/infrastructure/external/tianyancha"
@@ -42,6 +43,7 @@ type ProcessorDependencies struct {
JiguangService *jiguang.JiguangService
ShumaiService *shumai.ShumaiService
HuiboService *huibo.HuiboService
NuoerService *nuoer.NuoerService
Validator interfaces.RequestValidator
CombService CombServiceInterface // Changed to interface to break import cycle
Options *commands.ApiCallOptions // 添加Options支持
@@ -70,6 +72,7 @@ func NewProcessorDependencies(
jiguangService *jiguang.JiguangService,
shumaiService *shumai.ShumaiService,
huiboService *huibo.HuiboService,
nuoerService *nuoer.NuoerService,
validator interfaces.RequestValidator,
combService CombServiceInterface, // Changed to interface
reportRepo repositories.ReportRepository,
@@ -88,6 +91,7 @@ func NewProcessorDependencies(
JiguangService: jiguangService,
ShumaiService: shumaiService,
HuiboService: huiboService,
NuoerService: nuoerService,
Validator: validator,
CombService: combService,
Options: nil, // 初始化为nil在调用时设置

View File

@@ -25,7 +25,7 @@ func ProcessFLXG0V4BRequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 去掉司法案件案件去掉身份证号码
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" {
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
}
encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name)

View File

@@ -20,9 +20,10 @@ func ProcessFLXG5A3BRequest(ctx context.Context, params []byte, deps *processors
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" {
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
}
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)

View File

@@ -20,7 +20,7 @@ func ProcessFLXG7E8FRequest(ctx context.Context, params []byte, deps *processors
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" {
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
}

View File

@@ -20,7 +20,7 @@ func ProcessFLXGCA3DRequest(ctx context.Context, params []byte, deps *processors
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" {
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
}
encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name)

View File

@@ -20,6 +20,10 @@ func ProcessFLXGDEA8Request(ctx context.Context, params []byte, deps *processors
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 去掉司法案件案件去掉身份证号码
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
}
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
if err != nil {

View File

@@ -25,7 +25,7 @@ func ProcessFLXGDEA9Request(ctx context.Context, params []byte, deps *processors
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" {
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
}
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)

View File

@@ -0,0 +1,60 @@
package flxg
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/huibo"
)
// ProcessFLXGHB4FRequest FLXGHB4F API处理方法 - 个人涉诉案件查询汇博
func ProcessFLXGHB4FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.FLXGHB4FReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if deps.HuiboService == nil {
return nil, errors.Join(processors.ErrSystem, errors.New("汇博服务未初始化"))
}
// 使用 MD5 加密 name 和 idCard
// encryptedName := "MD5:" + huibo.MD5Encrypt(paramsDto.Name, deps.HuiboService.GetConfig().AppKey)
// encryptedIDCard := "MD5:" + huibo.MD5Encrypt(paramsDto.IDCard, deps.HuiboService.GetConfig().AppKey)
reqdata := map[string]interface{}{
"name": paramsDto.Name,
"idCard": paramsDto.IDCard,
}
respBytes, err := deps.HuiboService.CallAPI2(ctx, "P_004_0271", reqdata)
if err != nil {
return nil, errors.Join(processors.ErrDatasource, err)
}
// 解析响应
var response huibo.CallAPI2Response
if err := json.Unmarshal(respBytes, &response); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
// 处理状态码
switch response.Code {
case huibo.CallAPI2StatusSuccess:
// 查询成功
if response.Data == nil {
return []byte("{}"), nil
}
return respBytes, nil
case huibo.CallAPI2StatusNoData:
// 查询成功,无数据 - 按产品约定按调用成功计费
return []byte("{}"), nil
default:
// 其他错误状态码
message := huibo.GetCallAPI2StatusMessage(response.Code)
return nil, errors.Join(processors.ErrDatasource, errors.New(message))
}
}

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"strconv"
"time"
@@ -30,19 +31,20 @@ func ProcessIVYZZQ3BRequest(ctx context.Context, params []byte, deps *processors
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
encryptedImageUrl, err := deps.ZhichaService.Encrypt(paramsDto.ImageUrl)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
reqData := map[string]interface{}{
"idCard": encryptedIDCard,
"name": encryptedName,
"imageId": encryptedImageUrl,
"authorized": paramsDto.Authorized,
}
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI062", reqData)
if paramsDto.ImageUrl != "" {
reqData["url"] = paramsDto.ImageUrl
} else {
reqData["image"] = paramsDto.PhotoData
}
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI1001", reqData)
if err != nil {
if errors.Is(err, zhicha.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
@@ -56,7 +58,7 @@ func ProcessIVYZZQ3BRequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrSystem, err)
}
outBytes, err := mapZCI062RespToIVYZZQ3B(respBytes)
outBytes, err := mapZCI1001RespToIVYZZQ3B(respBytes)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
@@ -69,44 +71,118 @@ type IVYZZQ3BOut struct {
}
type IVYZZQ3BOutResultData struct {
// VerificationResult 审核校验结果valid 身份审核通过invalid 身份审核不通过(与 similarity 区间联动,见 mapVerificationResultFromSimilarity
// VerificationCode 审核校验编码,透传上游 incorrect
VerificationCode string `json:"verification_code"`
// VerificationResult 审核校验结果valid 身份审核通过invalid 身份审核不通过score >= 0.45 为 valid
VerificationResult string `json:"verification_result"`
// Similarity 照片相似度分数字符串01000。区间说明0600不同人600700不能确定是否同人7001000同人。数值为上游 score(0~1)×1000。
// VerificationMessage 审核校验信息,透传上游 msg
VerificationMessage string `json:"verification_message"`
// Similarity 照片相似度分数字符串01000。区间说明0600不同人600700不能确定是否同人7001000同人。
Similarity string `json:"similarity"`
}
// zci062UpstreamResp 智查 ZCI062 成功返回体中的分数字段(分值越大相似度越高)
type zci062UpstreamResp struct {
Score interface{} `json:"score"`
// zci1001UpstreamResp 智查 ZCI1001 成功返回体中的字段
type zci1001UpstreamResp struct {
Score interface{} `json:"score"`
Msg string `json:"msg"`
Incorrect interface{} `json:"incorrect"`
}
func mapZCI062RespToIVYZZQ3B(respBytes []byte) ([]byte, error) {
var r zci062UpstreamResp
func mapZCI1001RespToIVYZZQ3B(respBytes []byte) ([]byte, error) {
var r zci1001UpstreamResp
if err := json.Unmarshal(respBytes, &r); err != nil {
return nil, err
}
score := parseScoreToFloat64(r.Score)
similarityVal := score * 1000
score := parseScoreZCI1001ToFloat64(r.Score)
similarityVal := mapScoreToZCI001Similarity(score)
similarity := strconv.FormatFloat(similarityVal, 'f', 2, 64)
verificationResult := mapVerificationResultFromSimilarity(similarityVal)
verificationResult := buildToStringmapZCI1001RespToIVYZZQ3B(score)
out := IVYZZQ3BOut{
HandleTime: time.Now().Format("2006-01-02 15:04:05"),
ResultData: IVYZZQ3BOutResultData{
VerificationResult: verificationResult,
Similarity: similarity,
VerificationCode: valueZCI001ToString(r.Incorrect),
VerificationResult: verificationResult,
VerificationMessage: r.Msg,
Similarity: similarity,
},
}
return json.Marshal(out)
}
// mapVerificationResultFromSimilarity 与 similarity01000区间说明对齐
// 7001000】系统判断为同一人 → 身份审核通过 valid其余 → invalid。
func mapVerificationResultFromSimilarity(similarity float64) string {
if similarity >= 700 {
// buildToStringmapZCI1001RespToIVYZZQ3B 审核判定逻辑score >= 0.45 为 valid否则为 invalid
func buildToStringmapZCI1001RespToIVYZZQ3B(score float64) string {
if score >= 0.45 {
return "valid"
}
return "invalid"
}
// mapScoreToZCI001Similarity 将 score(0~1) 分段映射到 similarity(0~1000)
// 0.40 -> 6000.45 -> 700
func mapScoreToZCI001Similarity(score float64) float64 {
if score <= 0 {
return 0
}
if score >= 1 {
return 1000
}
if score < 0.40 {
// [0, 0.40) -> [0, 600)
return (score / 0.40) * 600
}
if score < 0.45 {
// [0.40, 0.45) -> [600, 700)
return 600 + ((score-0.40)/0.05)*100
}
// [0.45, 1] -> [700, 1000]
return 700 + ((score-0.45)/0.55)*300
}
func parseScoreZCI1001ToFloat64(v interface{}) float64 {
switch t := v.(type) {
case float64:
return t
case float32:
return float64(t)
case int:
return float64(t)
case int32:
return float64(t)
case int64:
return float64(t)
case json.Number:
if f, err := t.Float64(); err == nil {
return f
}
case string:
if f, err := strconv.ParseFloat(t, 64); err == nil {
return f
}
}
return 0
}
func valueZCI001ToString(v interface{}) string {
if v == nil {
return ""
}
switch t := v.(type) {
case string:
return t
case int:
return strconv.Itoa(t)
case int32:
return strconv.FormatInt(int64(t), 10)
case int64:
return strconv.FormatInt(t, 10)
case float64:
return strconv.FormatFloat(t, 'f', -1, 64)
case float32:
return strconv.FormatFloat(float64(t), 'f', -1, 64)
default:
return fmt.Sprintf("%v", v)
}
}

View File

@@ -37,9 +37,9 @@ func ProcessJRZQ1E7BRequest(ctx context.Context, params []byte, deps *processors
}
reqData := map[string]interface{}{
"name": encryptedName,
"idCard": encryptedIDCard,
"phone": encryptedMobileNo,
"name": encryptedName,
"idCard": encryptedIDCard,
"phone": encryptedMobileNo,
"authorized": paramsDto.Authorized,
}
@@ -55,9 +55,9 @@ func ProcessJRZQ1E7BRequest(ctx context.Context, params []byte, deps *processors
// 将响应数据转换为 JSON 字节
respBytes, err := json.Marshal(respData)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
// return nil, errors.Join(processors.ErrSystem, err)
return json.Marshal(map[string]interface{}{})
}
return respBytes, nil
}

View File

@@ -37,9 +37,9 @@ func ProcessJRZQ2F8ARequest(ctx context.Context, params []byte, deps *processors
}
reqData := map[string]interface{}{
"name": encryptedName,
"idCard": encryptedIDCard,
"phone": encryptedMobileNo,
"name": encryptedName,
"idCard": encryptedIDCard,
"phone": encryptedMobileNo,
"authorized": paramsDto.Authorized,
}
@@ -60,4 +60,3 @@ func ProcessJRZQ2F8ARequest(ctx context.Context, params []byte, deps *processors
return respBytes, nil
}

View File

@@ -40,6 +40,7 @@ func ProcessJRZQ3P01Request(ctx context.Context, params []byte, deps *processors
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI109", reqData)
if err != nil {
if errors.Is(err, zhicha.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
} else {
return nil, errors.Join(processors.ErrSystem, err)

View File

@@ -7,10 +7,9 @@ import (
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/jiguang"
)
// ProcessQCXG4D2ERequest QCXG4D2E API处理方法 - 极光名下车辆数量查询
// ProcessQCXG4D2ERequest QCXG4D2E API处理方法 - 名下车辆数量(委托诺尔 QCXGM4CL
func ProcessQCXG4D2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QCXG4D2EReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
@@ -21,27 +20,15 @@ func ProcessQCXG4D2ERequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 构建请求参数
reqData := map[string]interface{}{
"idNum": paramsDto.IDCard,
"userType": paramsDto.UserType,
}
// 调用极光API
// apiCode: vehicle-inquiry-under-name (用于请求头)
// apiPath: vehicle/inquiry-under-name (用于URL路径)
respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-inquiry-under-name", "vehicle/inquiry-under-name", reqData)
m4clParams, err := json.Marshal(dto.QCXGM4CLReq{IDCard: paramsDto.IDCard})
if err != nil {
// 根据错误类型返回相应的错误
if errors.Is(err, jiguang.ErrNotFound) {
return nil, errors.Join(processors.ErrNotFound, err)
} else if errors.Is(err, jiguang.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
return nil, errors.Join(processors.ErrSystem, err)
}
// 极光服务已经返回了 data 字段的 JSON直接返回即可
return respBytes, nil
raw, err := ProcessQCXGM4CLRequest(ctx, m4clParams, deps)
if err != nil {
return nil, err
}
return transformQCXG5F3AResponse(raw)
}

View File

@@ -4,13 +4,15 @@ import (
"context"
"encoding/json"
"errors"
"strconv"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/jiguang"
"github.com/tidwall/gjson"
)
// ProcessQCXG5F3ARequest QCXG5F3A API处理方法 - 极光名下车辆车牌查询
// ProcessQCXG5F3ARequest QCXG5F3A API处理方法 - 名下车辆(委托诺尔 QCXGM4CL响应格式兼容极光
func ProcessQCXG5F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QCXG5F3AReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
@@ -21,32 +23,53 @@ func ProcessQCXG5F3ARequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
null := ""
// 构建请求参数
reqData := map[string]interface{}{
"id_card": paramsDto.IDCard,
"name": paramsDto.Name,
"userType": null,
"vehicleType": null,
"encryptionType": null,
"encryptionContent": null,
}
// 调用极光API
// apiCode: vehicle-person-vehicles (用于请求头)
// apiPath: vehicle/person-vehicles (用于URL路径)
respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-person-vehicles", "vehicle/person-vehicles", reqData)
m4clParams, err := json.Marshal(dto.QCXGM4CLReq{IDCard: paramsDto.IDCard})
if err != nil {
// 根据错误类型返回相应的错误
if errors.Is(err, jiguang.ErrNotFound) {
return nil, errors.Join(processors.ErrNotFound, err)
} else if errors.Is(err, jiguang.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
return nil, errors.Join(processors.ErrSystem, err)
}
// 极光服务已经返回了 data 字段的 JSON直接返回即可
return respBytes, nil
raw, err := ProcessQCXGM4CLRequest(ctx, m4clParams, deps)
if err != nil {
return nil, err
}
return transformQCXG5F3AResponse(raw)
}
// transformQCXG5F3AResponse 将诺尔响应转为 QCXG5F3A 对外格式:去掉 busiCode/busiMsg展开 resultvehicleCount 为字符串
func transformQCXG5F3AResponse(raw []byte) ([]byte, error) {
base := gjson.GetBytes(raw, "result")
if !base.Exists() {
base = gjson.ParseBytes(raw)
}
list := base.Get("list").Value()
if list == nil {
list = []interface{}{}
}
countStr, err := formatVehicleCountAsString(base.Get("vehicleCount"))
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
out := map[string]interface{}{
"vehicleCount": countStr,
"list": list,
}
return json.Marshal(out)
}
func formatVehicleCountAsString(v gjson.Result) (string, error) {
if !v.Exists() {
return "0", nil
}
switch v.Type {
case gjson.String:
return v.String(), nil
case gjson.Number:
return strconv.FormatInt(v.Int(), 10), nil
default:
return "", errors.New("vehicleCount 类型无效")
}
}

View File

@@ -8,12 +8,11 @@ import (
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/jiguang"
"github.com/tidwall/gjson"
)
// ProcessQCXG9P1CRequest QCXG9P1C API处理方法 兼容旧版 极光名下车牌查询数量
// ProcessQCXG9P1CRequest QCXG9P1C API处理方法 - 名下车辆详版(委托诺尔 QCXGM4CL
func ProcessQCXG9P1CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QCXG9P1CReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
@@ -24,54 +23,53 @@ func ProcessQCXG9P1CRequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
null := ""
// 构建请求参数
reqData := map[string]interface{}{
"id_card": paramsDto.IDCard,
"name": null,
"userType": null,
"vehicleType": null,
"encryptionType": null,
"encryptionContent": null,
}
// 调用极光API
// apiCode: vehicle-person-vehicles (用于请求头)
// apiPath: vehicle/person-vehicles (用于URL路径)
respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-person-vehicles", "vehicle/person-vehicles", reqData)
m4clParams, err := json.Marshal(dto.QCXGM4CLReq{IDCard: paramsDto.IDCard})
if err != nil {
// 根据错误类型返回相应的错误
if errors.Is(err, jiguang.ErrNotFound) {
return nil, errors.Join(processors.ErrNotFound, err)
} else if errors.Is(err, jiguang.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
return nil, errors.Join(processors.ErrSystem, err)
}
// 使用 gjson 检查并转换 vehicleCount 字段
vehicleCountResult := gjson.GetBytes(respBytes, "vehicleCount")
if vehicleCountResult.Exists() && vehicleCountResult.Type == gjson.String {
// 如果是字符串类型,转换为整数
vehicleCountInt, err := strconv.Atoi(vehicleCountResult.String())
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
// 解析 JSON 并修改 vehicleCount 字段
var respData map[string]interface{}
if err := json.Unmarshal(respBytes, &respData); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
respData["vehicleCount"] = vehicleCountInt
// 重新序列化为JSON并返回
resultBytes, err := json.Marshal(respData)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
return resultBytes, nil
raw, err := ProcessQCXGM4CLRequest(ctx, m4clParams, deps)
if err != nil {
return nil, err
}
// 如果 vehicleCount 不存在或不是字符串,直接返回原始响应
return respBytes, nil
return transformQCXG9P1CResponse(raw)
}
// transformQCXG9P1CResponse 将诺尔响应转为 QCXG9P1C 对外格式:去掉 busiCode/busiMsg展开 resultvehicleCount 为整数
func transformQCXG9P1CResponse(raw []byte) ([]byte, error) {
base := gjson.GetBytes(raw, "result")
if !base.Exists() {
base = gjson.ParseBytes(raw)
}
list := base.Get("list").Value()
if list == nil {
list = []interface{}{}
}
countInt, err := formatVehicleCountAsInt(base.Get("vehicleCount"))
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
out := map[string]interface{}{
"vehicleCount": countInt,
"list": list,
}
return json.Marshal(out)
}
func formatVehicleCountAsInt(v gjson.Result) (int, error) {
if !v.Exists() {
return 0, nil
}
switch v.Type {
case gjson.String:
return strconv.Atoi(v.String())
case gjson.Number:
return int(v.Int()), nil
default:
return 0, errors.New("vehicleCount 类型无效")
}
}

View File

@@ -0,0 +1,48 @@
package qcxg
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/nuoer"
)
// ProcessQCXGM4CLRequest QCXGM4CL API处理方法 - 名下车辆诺尔
func ProcessQCXGM4CLRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QCXGM4CLReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
body := map[string]string{
"idCard": paramsDto.IDCard,
}
nuoerDoCheckAPIKey := "id_vehicle_query_102"
ApiPath := "/v1/doCheck"
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
if err != nil {
if errors.Is(err, nuoer.ErrNotFound) {
return nil, errors.Join(processors.ErrNotFound, err)
}
if errors.Is(err, nuoer.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
}
return nil, errors.Join(processors.ErrSystem, err)
}
respBytes, err := json.Marshal(resp.Data)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
return respBytes, nil
}

View File

@@ -0,0 +1,47 @@
package qygl
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shumai"
)
// ProcessQYGL2YSBRequest QYGL2YSB API处理方法 - 企业二要素认证
func ProcessQYGL2YSBRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGL2YSBReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
reqFormData := map[string]interface{}{
"legalPerson": paramsDto.LegalPerson,
"creditNo": paramsDto.EntCode,
}
apiPath := "/v4/company/two/check" // 接口路径,根据数脉文档填写(如 v4/xxx
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
if err != nil {
if errors.Is(err, shumai.ErrDatasource) {
// 数据源错误
return nil, errors.Join(processors.ErrDatasource, err)
} else if errors.Is(err, shumai.ErrSystem) {
// 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else if errors.Is(err, shumai.ErrNotFound) {
// 查无记录
return nil, errors.Join(processors.ErrNotFound, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
}
return respBytes, nil
}

View File

@@ -0,0 +1,48 @@
package qygl
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shumai"
)
// ProcessQYGL3YSBRequest QYGL3YSB API处理方法 - 企业三要素认证
func ProcessQYGL3YSBRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGL3YSBReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
reqFormData := map[string]interface{}{
"legalPerson": paramsDto.LegalPerson,
"companyName": paramsDto.EntName,
"creditNo": paramsDto.EntCode,
}
apiPath := "/v4/company-three/check" // 接口路径,根据数脉文档填写(如 v4/xxx
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
if err != nil {
if errors.Is(err, shumai.ErrDatasource) {
// 数据源错误
return nil, errors.Join(processors.ErrDatasource, err)
} else if errors.Is(err, shumai.ErrSystem) {
// 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else if errors.Is(err, shumai.ErrNotFound) {
// 查无记录
return nil, errors.Join(processors.ErrNotFound, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
}
return respBytes, nil
}

View File

@@ -8,10 +8,31 @@ import (
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shujubao"
)
// QYGL4B2EItem 返回列表项
type QYGL4B2EItem struct {
PublishTime string `json:"publish_time"`
CaseType string `json:"case_type"`
ID int64 `json:"id"`
Department string `json:"department"`
TaxpayerName string `json:"taxpayer_name"`
}
// QYGL4B2EResponse 最终返回结构
type QYGL4B2EResponse struct {
Total int64 `json:"total"`
Items []QYGL4B2EItem `json:"items"`
}
// ProcessQYGL4B2ERequest QYGL4B2E API处理方法 - 税收违法
func ProcessQYGL4B2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
func ProcessQYGL4B2ERequest(
ctx context.Context,
params []byte,
deps *processors.ProcessorDependencies,
) ([]byte, error) {
var paramsDto dto.QYGL5A3CReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
@@ -21,39 +42,90 @@ func ProcessQYGL4B2ERequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 设置默认值
// 默认值
pageSize := paramsDto.PageSize
if pageSize == 0 {
pageSize = int64(20)
pageSize = 20
}
pageNum := paramsDto.PageNum
if pageNum == 0 {
pageNum = int64(1)
pageNum = 1
}
// 构建API调用参数
apiParams := map[string]string{
"keyword": paramsDto.EntCode,
"pageSize": strconv.FormatInt(pageSize, 10),
"pageNum": strconv.FormatInt(pageNum, 10),
// 调用外部接口
reqParams := map[string]interface{}{
"key": "c67673dd2e92deb2d2ec91b87bb0a81c",
"creditCode": paramsDto.EntCode,
}
// 调用天眼查API - 税收违法
response, err := deps.TianYanChaService.CallAPI(ctx, "TaxContravention", apiParams)
apiPath := "/communication/personal/10233"
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
if err != nil {
return nil, convertTianYanChaError(err)
if errors.Is(err, shujubao.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
}
if errors.Is(err, shujubao.ErrQueryEmpty) {
data = map[string]interface{}{}
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
}
// 检查天眼查API调用是否成功
if !response.Success {
return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message))
// 原始返回结构处理 - data 是 map[string]interface{} 类型
dataMap, ok := data.(map[string]interface{})
if !ok {
return nil, errors.Join(processors.ErrSystem, errors.New("data不是map类型"))
}
// 返回天眼查响应数据
respBytes, err := json.Marshal(response.Data)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
// 提取 total
total := int64(0)
if v, ok := dataMap["total"]; ok {
switch val := v.(type) {
case float64:
total = int64(val)
case int:
total = int64(val)
case string:
total, _ = strconv.ParseInt(val, 10, 64)
}
}
return respBytes, nil
// 提取 items 数组
srcItems := make([]map[string]interface{}, 0)
if v, ok := dataMap["items"]; ok {
if arr, ok := v.([]interface{}); ok {
for _, item := range arr {
if itemMap, ok := item.(map[string]interface{}); ok {
srcItems = append(srcItems, itemMap)
}
}
}
}
// 构造返回数据
resp := QYGL4B2EResponse{
Total: total,
Items: make([]QYGL4B2EItem, 0, len(srcItems)),
}
getString := func(item map[string]interface{}, key string) string {
if v, ok := item[key]; ok {
if str, ok := v.(string); ok {
return str
}
}
return ""
}
for i, v := range srcItems {
resp.Items = append(resp.Items, QYGL4B2EItem{
ID: int64(i + 1),
TaxpayerName: getString(v, "entityName"),
Department: getString(v, "belongDepartment"),
CaseType: getString(v, "caseType"),
PublishTime: getString(v, "illegalTime"),
})
}
return json.Marshal(resp)
}

View File

@@ -0,0 +1,49 @@
package qygl
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shumai"
)
// ProcessQYGL4YABRequest QYGL4YAB API处理方法 - 企业四要素认证
func ProcessQYGL4YABRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGL4YABReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
reqFormData := map[string]interface{}{
"idCard": paramsDto.IDCard,
"legalPerson": paramsDto.LegalPerson,
"companyName": paramsDto.EntName,
"creditNo": paramsDto.EntCode,
}
apiPath := "/v4/company-four/check" // 接口路径,根据数脉文档填写(如 v4/xxx
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
if err != nil {
if errors.Is(err, shumai.ErrDatasource) {
// 数据源错误
return nil, errors.Join(processors.ErrDatasource, err)
} else if errors.Is(err, shumai.ErrSystem) {
// 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else if errors.Is(err, shumai.ErrNotFound) {
// 查无记录
return nil, errors.Join(processors.ErrNotFound, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
}
return respBytes, nil
}

View File

@@ -38,8 +38,10 @@ func ProcessQYGL6S1BRequest(ctx context.Context, params []byte, deps *processors
}
if errors.Is(err, shujubao.ErrQueryEmpty) {
return nil, errors.Join(processors.ErrNotFound, err)
// data = map[string]interface{}{}
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
return nil, errors.Join(processors.ErrSystem, err)
}
// 解析响应中的 JSON 字符串(使用 RecursiveParse

View File

@@ -8,8 +8,59 @@ import (
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shujubao"
)
/*
## 返回字段说明
| 返回值字段 | 字段类型 | 字段说明 | 备注 |
|------------|----------|----------|------|
| total | Number | int(11) | 总数 |
| items | Array | | |
| _child | Object | | |
| taxIdNumber | String | varchar(150) | 纳税人识别号 |
| newOwnTaxBalance | String | varchar(20) | 当前新发生欠税余额 |
| ownTaxAmount | String | varchar(50) | 欠税金额 |
| publishDate | String | 日期 | 发布时间 |
| ownTaxBalance | String | varchar(20) | 欠税余额 |
| type | String | varchar(10) | 税务类型 |
| personIdNumber | String | varchar(150) | 证件号码 |
| taxCategory | String | varchar(255) | 欠税税种 |
| taxpayerType | String | varchar(10) | 纳税人类型 |
| personIdName | String | varchar(50) | 法人证件名称 |
| name | String | varchar(255) | 纳税人名称 |
| location | String | varchar(150) | 经营地点 |
| department | String | varchar(200) | 税务机关 |
| regType | String | varchar(50) | 注册类型 |
| legalpersonName | String | varchar(150) | 法人或负责人名称 |
*/
// QYGL7D9AItem 返回列表项
type QYGL7D9AItem struct {
TaxIdNumber string `json:"taxIdNumber"`
NewOwnTaxBalance string `json:"newOwnTaxBalance"`
OwnTaxAmount string `json:"ownTaxAmount"`
PublishDate string `json:"publishDate"`
OwnTaxBalance string `json:"ownTaxBalance"`
Type string `json:"type"`
PersonIdNumber string `json:"personIdNumber"`
TaxCategory string `json:"taxCategory"`
TaxpayerType string `json:"taxpayerType"`
PersonIdName string `json:"personIdName"`
Name string `json:"name"`
Location string `json:"location"`
Department string `json:"department"`
RegType string `json:"regType"`
LegalpersonName string `json:"legalpersonName"`
}
// QYGL7D9AResponse 最终返回结构
type QYGL7D9AResponse struct {
Total int64 `json:"total"`
Items []QYGL7D9AItem `json:"items"`
}
// ProcessQYGL7D9ARequest QYGL7D9A API处理方法 - 欠税公告
func ProcessQYGL7D9ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGL5A3CReq
@@ -21,39 +72,100 @@ func ProcessQYGL7D9ARequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 设置默认值
// 默认值
pageSize := paramsDto.PageSize
if pageSize == 0 {
pageSize = int64(20)
pageSize = 20
}
pageNum := paramsDto.PageNum
if pageNum == 0 {
pageNum = int64(1)
pageNum = 1
}
// 构建API调用参数
apiParams := map[string]string{
"keyword": paramsDto.EntCode,
"pageSize": strconv.FormatInt(pageSize, 10),
"pageNum": strconv.FormatInt(pageNum, 10),
// 调用外部接口
reqParams := map[string]interface{}{
"key": "9ad1365cb0580863a239b0255649fb1a",
"creditCode": paramsDto.EntCode,
}
// 调用天眼查API - 欠税公告
response, err := deps.TianYanChaService.CallAPI(ctx, "OwnTax", apiParams)
apiPath := "/communication/personal/10235"
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
if err != nil {
return nil, convertTianYanChaError(err)
if errors.Is(err, shujubao.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
}
if errors.Is(err, shujubao.ErrQueryEmpty) {
data = map[string]interface{}{}
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
}
// 检查天眼查API调用是否成功
if !response.Success {
return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message))
// 原始返回结构处理 - data 是 map[string]interface{} 类型
dataMap, ok := data.(map[string]interface{})
if !ok {
return nil, errors.Join(processors.ErrSystem, errors.New("data不是map类型"))
}
// 返回天眼查响应数据
respBytes, err := json.Marshal(response.Data)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
// 提取 total
totalStr := ""
if v, ok := dataMap["total"]; ok {
if str, ok := v.(string); ok {
totalStr = str
}
}
return respBytes, nil
// 提取 items 数组
srcItems := make([]map[string]interface{}, 0)
if v, ok := dataMap["items"]; ok {
if arr, ok := v.([]interface{}); ok {
for _, item := range arr {
if itemMap, ok := item.(map[string]interface{}); ok {
srcItems = append(srcItems, itemMap)
}
}
}
}
// 构造返回数据(缺失字段留空字符串)
resp := QYGL7D9AResponse{
Total: 0,
Items: make([]QYGL7D9AItem, 0, len(srcItems)),
}
getString := func(item map[string]interface{}, key string) string {
if v, ok := item[key]; ok {
if str, ok := v.(string); ok {
return str
}
}
return ""
}
for _, v := range srcItems {
resp.Items = append(resp.Items, QYGL7D9AItem{
TaxIdNumber: getString(v, "taxpayerCode"),
NewOwnTaxBalance: getString(v, "thisOwedAmount"),
OwnTaxAmount: getString(v, "totalOwedAmount"),
PublishDate: getString(v, "publishDate"),
OwnTaxBalance: getString(v, "beforeOwedAmount"),
Type: getString(v, "taxBureauType"),
PersonIdNumber: "",
TaxCategory: getString(v, "taxOwedType"),
TaxpayerType: "",
PersonIdName: "",
Name: getString(v, "entityName"),
Location: getString(v, "businessAddress"),
Department: getString(v, "taxBureauName"),
RegType: "",
LegalpersonName: getString(v, "legalPerson"),
})
}
// total 转 int64
if totalStr != "" {
resp.Total, _ = strconv.ParseInt(totalStr, 10, 64)
}
return json.Marshal(resp)
}

View File

@@ -8,8 +8,50 @@ import (
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shujubao"
)
/*
## 返回字段说明
| 字段名 | 类型 | 说明 |
|--------|------|------|
| items | array | 融资历史记录列表,无记录时为空数组 |
| items[].round | string | 融资轮次 |
| items[].amount | string | 融资金额 |
| items[].date | string | 融资日期格式YYYY-MM-DD |
| items[].investors | array of string | 投资方列表 |
| items[].postValuation | string | 融资后估值 |
| items[].preValuation | string | 融资前估值 |
| items[].currency | string | 币种 |
| items[].intro | string | 项目简介 |
| items[].shareRatio | string | 持股比例 |
| total | integer | 符合条件的融资记录总数,无记录时为 0 |
| pageNum | integer | 当前页码 |
| pageSize | integer | 每页记录条数 |
*/
// QYGL8B4DItem 融资历史单项
type QYGL8B4DItem struct {
Round string `json:"round"`
Amount string `json:"amount"`
Date string `json:"date"`
Investors []string `json:"investors"`
PostValuation string `json:"postValuation"`
PreValuation string `json:"preValuation"`
Currency string `json:"currency"`
Intro string `json:"intro"`
ShareRatio string `json:"shareRatio"`
}
// QYGL8B4DResponse 融资历史返回结构
type QYGL8B4DResponse struct {
Items []QYGL8B4DItem `json:"items"`
Total int64 `json:"total"`
PageNum int64 `json:"pageNum"`
PageSize int64 `json:"pageSize"`
}
// ProcessQYGL8B4DRequest QYGL8B4D API处理方法 - 融资历史
func ProcessQYGL8B4DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGL8B4DReq
@@ -21,7 +63,7 @@ func ProcessQYGL8B4DRequest(ctx context.Context, params []byte, deps *processors
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 设置默认值
// 默认值
pageSize := paramsDto.PageSize
if pageSize == 0 {
pageSize = int64(20)
@@ -31,29 +73,100 @@ func ProcessQYGL8B4DRequest(ctx context.Context, params []byte, deps *processors
pageNum = int64(1)
}
// 构建API调用参数
apiParams := map[string]string{
"keyword": paramsDto.EntCode,
"pageSize": strconv.FormatInt(pageSize, 10),
"pageNum": strconv.FormatInt(pageNum, 10),
// 调用外部接口
reqParams := map[string]interface{}{
"key": "8887a17748d767b0a1f417171108873f",
"creditCode": paramsDto.EntCode,
}
// 调用天眼查API - 融资历史
response, err := deps.TianYanChaService.CallAPI(ctx, "FinancingHistory", apiParams)
apiPath := "/communication/personal/10435"
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
if err != nil {
return nil, convertTianYanChaError(err)
if errors.Is(err, shujubao.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err)
}
if errors.Is(err, shujubao.ErrQueryEmpty) {
data = map[string]interface{}{}
} else {
return nil, errors.Join(processors.ErrSystem, err)
}
}
// 检查天眼查API调用是否成功
if !response.Success {
return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message))
// 原始返回结构处理 - data 是 map[string]interface{} 类型
dataMap, ok := data.(map[string]interface{})
if !ok {
return nil, errors.Join(processors.ErrSystem, errors.New("data不是map类型"))
}
// 返回天眼查响应数据
respBytes, err := json.Marshal(response.Data)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
// 提取 page 对象中的 totalRecords
totalRecords := ""
if page, ok := dataMap["page"].(map[string]interface{}); ok {
if v, ok := page["totalRecords"]; ok {
if str, ok := v.(string); ok {
totalRecords = str
}
}
}
return respBytes, nil
// 提取 records 数组(不是 items
records := make([]map[string]interface{}, 0)
if v, ok := dataMap["records"]; ok {
if arr, ok := v.([]interface{}); ok {
for _, item := range arr {
if itemMap, ok := item.(map[string]interface{}); ok {
records = append(records, itemMap)
}
}
}
}
// 构造返回数据
resp := QYGL8B4DResponse{
Items: make([]QYGL8B4DItem, 0, len(records)),
PageNum: pageNum,
PageSize: pageSize,
}
for _, item := range records {
// 提取字段,使用类型断言
getString := func(key string) string {
if v, ok := item[key]; ok {
if str, ok := v.(string); ok {
return str
}
}
return ""
}
investAmount := getString("investAmount")
afterValuation := getString("afterInvestValuation")
// 计算持股比例:持股比例 = 本轮投资金额 / 投后估值 × 100%
shareRatio := ""
investAmountFloat, err1 := strconv.ParseFloat(investAmount, 64)
afterValuationFloat, err2 := strconv.ParseFloat(afterValuation, 64)
if err1 == nil && err2 == nil && afterValuationFloat > 0 {
ratio := investAmountFloat / afterValuationFloat * 100
shareRatio = strconv.FormatFloat(ratio, 'f', 2, 64) // 保留两位小数
}
resp.Items = append(resp.Items, QYGL8B4DItem{
Round: getString("financingRound"),
Amount: investAmount,
Date: getString("financingDate"),
Investors: []string{getString("financingRoundInvestor")},
PostValuation: afterValuation,
PreValuation: getString("beforeInvestValuation"),
Currency: getString("currency"),
Intro: "",
ShareRatio: shareRatio,
})
}
// total
if totalRecords != "" {
resp.Total, _ = strconv.ParseInt(totalRecords, 10, 64)
}
return json.Marshal(resp)
}

View File

@@ -0,0 +1,55 @@
package qygl
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/huibo"
)
// ProcessQYGLBH7YRequest QYGLBH7Y API处理方法 - 企业案件查询汇博
func ProcessQYGLBH7YRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGLBH7YReq
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if deps.HuiboService == nil {
return nil, errors.Join(processors.ErrSystem, errors.New("汇博服务未初始化"))
}
reqdata := map[string]interface{}{
"companyName": paramsDto.EntName,
}
respBytes, err := deps.HuiboService.CallAPI2(ctx, "E_004_0261", reqdata)
if err != nil {
return nil, errors.Join(processors.ErrDatasource, err)
}
// 解析响应
var response huibo.CallAPI2Response
if err := json.Unmarshal(respBytes, &response); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
// 处理状态码
switch response.Code {
case huibo.CallAPI2StatusSuccess:
// 查询成功
if response.Data == nil {
return []byte("{}"), nil
}
return respBytes, nil
case huibo.CallAPI2StatusNoData:
// 查询成功,无数据 - 按产品约定按调用成功计费
return []byte("{}"), nil
default:
// 其他错误状态码
message := huibo.GetCallAPI2StatusMessage(response.Code)
return nil, errors.Join(processors.ErrDatasource, errors.New(message))
}
}

View File

@@ -0,0 +1,48 @@
package qygl
import (
"context"
"encoding/json"
"errors"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shumai"
)
// ProcessQYGLDG77Request QYGLDG77 API处理方法 - 企业打款认证
func ProcessQYGLDG77Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
var paramsDto dto.QYGLDG77Req
if err := json.Unmarshal(params, &paramsDto); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
reqFormData := map[string]interface{}{
"companyName": paramsDto.EntName,
"accountNo": paramsDto.AccountNo,
"accountBank": paramsDto.AccountBank,
}
apiPath := "/v2/company/dkrz/check" // 接口路径,根据数脉文档填写(如 v4/xxx
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
if err != nil {
if errors.Is(err, shumai.ErrDatasource) {
// 数据源错误
return nil, errors.Join(processors.ErrDatasource, err)
} else if errors.Is(err, shumai.ErrSystem) {
// 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else if errors.Is(err, shumai.ErrNotFound) {
// 查无记录
return nil, errors.Join(processors.ErrNotFound, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
}
return respBytes, nil
}

View File

@@ -35,6 +35,8 @@ type Certification struct {
EsignFlowID string `gorm:"type:varchar(500)" json:"esign_flow_id,omitempty" comment:"签署流程ID"`
ContractURL string `gorm:"type:varchar(500)" json:"contract_url,omitempty" comment:"合同文件访问链接"`
ContractSignURL string `gorm:"type:varchar(500)" json:"contract_sign_url,omitempty" comment:"合同签署链接"`
// ContractCode 合作协议编号(与电子合同模板控件 xybh 一致,签署完成后写入用户域合同)
ContractCode string `gorm:"type:varchar(255)" json:"contract_code,omitempty" comment:"合作协议编号"`
// === 失败信息 ===
FailureReason enums.FailureReason `gorm:"type:varchar(100)" json:"failure_reason,omitempty" comment:"失败原因"`
@@ -323,6 +325,11 @@ func (c *Certification) ApplyContract(EsignFlowID string, ContractSignURL string
return nil
}
// SetContractCode 设置合作协议编号(首次生成合同时写入,后续换文件复用)
func (c *Certification) SetContractCode(code string) {
c.ContractCode = code
}
// AddContractFileID 生成合同文件
func (c *Certification) AddContractFileID(contractFileID string, contractURL string) error {
c.ContractFileID = contractFileID

View File

@@ -435,3 +435,31 @@ func (s *ProductManagementService) ListProductsWithSubscriptionStatus(ctx contex
return products, subscriptionStatusMap, total, nil
}
// GetAllProductsForDictionary 获取所有启用且可见的产品(用于导出产品字典)
func (s *ProductManagementService) GetAllProductsForDictionary(ctx context.Context) ([]*entities.Product, error) {
// 构建查询条件:启用且可见
isEnabled := true
isVisible := true
filters := map[string]interface{}{
"is_enabled": isEnabled,
"is_visible": isVisible,
}
options := interfaces.ListOptions{
Page: 1,
PageSize: 1000, // 获取所有产品
Sort: "id", // 按产品ID排序避免JOIN问题
Order: "asc",
}
// 获取产品列表
products, _, err := s.ListProducts(ctx, filters, options)
if err != nil {
s.logger.Error("获取产品字典数据失败", zap.Error(err))
return nil, fmt.Errorf("获取产品字典数据失败: %w", err)
}
return products, nil
}

View File

@@ -119,6 +119,58 @@ func NewContractInfo(enterpriseInfoID, userID, contractName string, contractType
return contractInfo, nil
}
// NewContractInfoWithContractCode 使用指定合同编号创建合同信息(与认证阶段生成的编号一致)
func NewContractInfoWithContractCode(enterpriseInfoID, userID, contractName string, contractType ContractType, contractFileID, contractFileURL, contractCode string) (*ContractInfo, error) {
if enterpriseInfoID == "" {
return nil, fmt.Errorf("企业信息ID不能为空")
}
if userID == "" {
return nil, fmt.Errorf("用户ID不能为空")
}
if contractName == "" {
return nil, fmt.Errorf("合同名称不能为空")
}
if contractType == "" {
return nil, fmt.Errorf("合同类型不能为空")
}
if contractFileID == "" {
return nil, fmt.Errorf("合同文件ID不能为空")
}
if contractFileURL == "" {
return nil, fmt.Errorf("合同文件URL不能为空")
}
if contractCode == "" {
return nil, fmt.Errorf("合同编号不能为空")
}
if !isValidContractType(contractType) {
return nil, fmt.Errorf("无效的合同类型: %s", contractType)
}
contractInfo := &ContractInfo{
ID: uuid.New().String(),
EnterpriseInfoID: enterpriseInfoID,
UserID: userID,
ContractCode: contractCode,
ContractName: contractName,
ContractType: contractType,
ContractFileID: contractFileID,
ContractFileURL: contractFileURL,
domainEvents: make([]interface{}, 0),
}
contractInfo.addDomainEvent(&ContractInfoCreatedEvent{
ContractInfoID: contractInfo.ID,
EnterpriseInfoID: enterpriseInfoID,
UserID: userID,
ContractCode: contractCode,
ContractName: contractName,
ContractType: string(contractType),
CreatedAt: time.Now(),
})
return contractInfo, nil
}
// ================ 聚合根核心方法 ================
// UpdateContractInfo 更新合同信息

View File

@@ -14,6 +14,7 @@ import (
type ContractAggregateService interface {
// 聚合根生命周期管理
CreateContract(ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL string) (*entities.ContractInfo, error)
CreateContractWithCode(ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL, contractCode string) (*entities.ContractInfo, error)
LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error)
SaveContract(ctx context.Context, contract *entities.ContractInfo) error
DeleteContract(ctx context.Context, contractID string) error
@@ -94,6 +95,51 @@ func (s *ContractAggregateServiceImpl) CreateContract(
return contract, nil
}
// CreateContractWithCode 使用指定合同编号创建合同信息(与认证合同模板上的编号一致)
func (s *ContractAggregateServiceImpl) CreateContractWithCode(
ctx context.Context,
enterpriseInfoID, userID, contractName string,
contractType entities.ContractType,
contractFileID, contractFileURL, contractCode string,
) (*entities.ContractInfo, error) {
s.logger.Debug("创建合同信息(指定编号)",
zap.String("enterprise_info_id", enterpriseInfoID),
zap.String("user_id", userID),
zap.String("contract_name", contractName),
zap.String("contract_code", contractCode),
zap.String("contract_type", string(contractType)))
exists, err := s.ExistsByContractFileID(ctx, contractFileID)
if err != nil {
return nil, fmt.Errorf("检查合同文件ID失败: %w", err)
}
if exists {
return nil, fmt.Errorf("合同文件ID已存在")
}
contract, err := entities.NewContractInfoWithContractCode(enterpriseInfoID, userID, contractName, contractType, contractFileID, contractFileURL, contractCode)
if err != nil {
return nil, fmt.Errorf("创建合同信息失败: %w", err)
}
if err := s.ValidateBusinessRules(ctx, contract); err != nil {
return nil, fmt.Errorf("业务规则验证失败: %w", err)
}
err = s.SaveContract(ctx, contract)
if err != nil {
return nil, fmt.Errorf("保存合同信息失败: %w", err)
}
s.logger.Info("合同信息创建成功",
zap.String("contract_id", contract.ID),
zap.String("enterprise_info_id", enterpriseInfoID),
zap.String("contract_code", contractCode),
zap.String("contract_name", contractName))
return contract, nil
}
// LoadContract 加载合同信息
func (s *ContractAggregateServiceImpl) LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error) {
s.logger.Debug("加载合同信息", zap.String("contract_id", contractID))