This commit is contained in:
Mrx
2026-03-20 13:25:47 +08:00
3 changed files with 49 additions and 81 deletions

View File

@@ -8,21 +8,9 @@ import (
"tyapi-server/internal/domains/api/dto" "tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/services/processors" "tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/infrastructure/external/shumai" "tyapi-server/internal/infrastructure/external/shujubao"
) )
// shumaiMobileThreeResp 数脉 /v4/mobile_three/check 返回的 data 结构
// result: 0-一致 1-不一致 2-无记录channel: cmcc/cucc/ctcc/gdcc
type shumaiMobileThreeResp struct {
OrderNo string `json:"order_no"`
Result string `json:"result"`
Desc string `json:"desc"`
Channel string `json:"channel"`
Sex string `json:"sex"`
Birthday string `json:"birthday"`
Address string `json:"address"`
}
// YYSY09CDResponse 最终返回结构 // YYSY09CDResponse 最终返回结构
// code: 1000一致 1001不一致 1002查无 // code: 1000一致 1001不一致 1002查无
type YYSY09CDResponse struct { type YYSY09CDResponse struct {
@@ -47,43 +35,48 @@ func ProcessYYSY09CDRequest(ctx context.Context, params []byte, deps *processors
if err := deps.Validator.ValidateStruct(paramsDto); err != nil { if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err) return nil, errors.Join(processors.ErrInvalidParam, err)
} }
reqFormData := map[string]interface{}{ reqParams := map[string]interface{}{
"idcard": paramsDto.IDCard, "key": "c115708d915451da8f34a23e144dda6b",
"name": paramsDto.Name, "name": paramsDto.Name,
"idcard": paramsDto.IDCard,
"mobile": paramsDto.MobileNo, "mobile": paramsDto.MobileNo,
} }
apiPath := "/v4/mobile_three/check" apiPath := "/communication/personal/1979"
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
// 先尝试使用政务接口app_id2 和 app_secret2
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true)
if err != nil { if err != nil {
// 使用实时接口app_id 和 app_secret重试 if errors.Is(err, shujubao.ErrDatasource) {
respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
// 如果重试后仍然失败,返回错误
if err != nil {
if errors.Is(err, shumai.ErrDatasource) {
return nil, errors.Join(processors.ErrDatasource, err) return nil, errors.Join(processors.ErrDatasource, err)
} else if errors.Is(err, shumai.ErrSystem) {
return nil, errors.Join(processors.ErrSystem, err)
} else {
return nil, errors.Join(processors.ErrSystem, err)
} }
if errors.Is(err, shujubao.ErrQueryEmpty) {
return nil, errors.Join(processors.ErrNotFound, err)
} }
return nil, errors.Join(processors.ErrSystem, err)
} }
out, err := mapShumaiMobileThreeToYYSY09CD(respBytes) out, err := mapYYSYK9R4ToYYSY09CD(data)
if err != nil { if err != nil {
return nil, errors.Join(processors.ErrSystem, err) return nil, errors.Join(processors.ErrSystem, err)
} }
return json.Marshal(out) return json.Marshal(out)
} }
// mapShumaiMobileThreeToYYSY09CD 数脉 mobile_three/check 的 data -> 最终格式 // yysyk9r4Resp 数据宝 YYSYK9R4 接口 data 结构
// result: 0->1000一致 1->1001不一致 2->1002查无 其它->1002查无channel: cmcc->CMCC cucc->CUCC ctcc->CTCC gdcc->CBN // state: 1-验证一致 2-验证不一致 3-异常情况
func mapShumaiMobileThreeToYYSY09CD(dataBytes []byte) (*YYSY09CDResponse, error) { type yysyk9r4Resp struct {
var r shumaiMobileThreeResp State string `json:"state"`
if err := json.Unmarshal(dataBytes, &r); err != nil { }
// mapYYSYK9R4ToYYSY09CD 数据宝 YYSYK9R4 的 data -> YYSY09CD 最终格式
// state: 1->1000一致 2->1001不一致 其它->1002查无
func mapYYSYK9R4ToYYSY09CD(data interface{}) (*YYSY09CDResponse, error) {
var r yysyk9r4Resp
b, err := json.Marshal(data)
if err != nil {
return nil, err
}
if err := json.Unmarshal(b, &r); err != nil {
return nil, err return nil, err
} }
@@ -91,44 +84,26 @@ func mapShumaiMobileThreeToYYSY09CD(dataBytes []byte) (*YYSY09CDResponse, error)
var codeStr string var codeStr string
var codeInt int var codeInt int
var msg string var msg string
switch strings.TrimSpace(r.Result) { switch strings.TrimSpace(r.State) {
case "0": case "1":
codeStr = "1000" codeStr = "1000"
codeInt = 1000 codeInt = 1000
msg = "一致" msg = "一致"
case "1": case "2":
codeStr = "1001" codeStr = "1001"
codeInt = 1001 codeInt = 1001
msg = "不一致" msg = "不一致"
case "2":
codeStr = "1002"
codeInt = 1002
msg = "查无"
default: default:
codeStr = "1002" codeStr = "1002"
codeInt = 1002 codeInt = 1002
msg = "查无" msg = "查无"
} }
// phoneType: cmcc->CMCC cucc->CUCC ctcc->CTCC gdcc->CBN(广电)
ch := strings.ToLower(strings.TrimSpace(r.Channel))
var phoneType string
switch ch {
case "cmcc":
phoneType = "CMCC"
case "cucc":
phoneType = "CUCC"
case "ctcc":
phoneType = "CTCC"
case "gdcc":
phoneType = "CBN"
}
return &YYSY09CDResponse{ return &YYSY09CDResponse{
Code: codeStr, Code: codeStr,
Data: YYSY09CDResponseData{ Data: YYSY09CDResponseData{
Msg: msg, Msg: msg,
PhoneType: phoneType, PhoneType: "",
Code: codeInt, Code: codeInt,
EncryptType: "MD5", EncryptType: "MD5",
}, },

View File

@@ -13,6 +13,18 @@ import (
"tyapi-server/internal/infrastructure/external/shumai" "tyapi-server/internal/infrastructure/external/shumai"
) )
// shumaiMobileThreeResp 数脉 /v4/mobile_three/check 返回的 data 结构
// result: 0-一致 1-不一致 2-无记录channel: cmcc/cucc/ctcc/gdcc
type shumaiMobileThreeResp struct {
OrderNo string `json:"order_no"`
Result string `json:"result"`
Desc string `json:"desc"`
Channel string `json:"channel"`
Sex string `json:"sex"`
Birthday string `json:"birthday"`
Address string `json:"address"`
}
// yysy9a1bOut 最终返回格式 // yysy9a1bOut 最终返回格式
// result: 01一致 02不一致 03不确定 04失败/虚拟号type: 1移动 2联通 3电信 4广电 // result: 01一致 02不一致 03不确定 04失败/虚拟号type: 1移动 2联通 3电信 4广电
type yysy9a1bOut struct { type yysy9a1bOut struct {

View File

@@ -160,20 +160,8 @@ func (h *QYGLReportHandler) GetQYGLReportPDFByID(c *gin.Context) {
} }
} }
// 先尝试从缓存中读取基于报告ID // 临时关闭企业全景报告 PDF 的读取缓存,强制每次都重新生成
if h.pdfCacheManager != nil { // 如果后续需要恢复缓存,可在此重新启用 pdfCacheManager.GetByReportID 的逻辑。
if cachedBytes, hit, _, err := h.pdfCacheManager.GetByReportID(id); err == nil && hit && len(cachedBytes) > 0 {
h.logger.Info("企业全景报告 PDF 缓存命中",
zap.String("report_id", id),
zap.Int("pdf_size", len(cachedBytes)),
)
encodedFileName := url.QueryEscape(fileName)
c.Header("Content-Type", "application/pdf")
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", encodedFileName))
c.Data(http.StatusOK, "application/pdf", cachedBytes)
return
}
}
// 根据当前请求推断访问协议(支持通过反向代理的 X-Forwarded-Proto // 根据当前请求推断访问协议(支持通过反向代理的 X-Forwarded-Proto
scheme := "http" scheme := "http"
@@ -205,15 +193,8 @@ func (h *QYGLReportHandler) GetQYGLReportPDFByID(c *gin.Context) {
return return
} }
// 将生成结果写入缓存(忽略写入错误,不影响主流程) // 临时关闭企业全景报告 PDF 的写入缓存,只返回最新生成的 PDF。
if h.pdfCacheManager != nil { // 若后续需要重新启用缓存,可恢复对 pdfCacheManager.SetByReportID 的调用。
if err := h.pdfCacheManager.SetByReportID(id, pdfBytes); err != nil {
h.logger.Warn("保存企业全景报告 PDF 到缓存失败",
zap.String("report_id", id),
zap.Error(err),
)
}
}
encodedFileName := url.QueryEscape(fileName) encodedFileName := url.QueryEscape(fileName)
c.Header("Content-Type", "application/pdf") c.Header("Content-Type", "application/pdf")