add ivyz9k2l
This commit is contained in:
@@ -299,6 +299,12 @@ type IVYZ3A7FReq struct {
|
|||||||
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IVYZ9K2LReq struct {
|
||||||
|
Name string `json:"name" validate:"required,min=1,validName"`
|
||||||
|
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
||||||
|
PhotoData string `json:"photo_data" validate:"omitempty,validBase64Image"`
|
||||||
|
}
|
||||||
|
|
||||||
type IVYZ9D2EReq struct {
|
type IVYZ9D2EReq struct {
|
||||||
Name string `json:"name" validate:"required,min=1,validName"`
|
Name string `json:"name" validate:"required,min=1,validName"`
|
||||||
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ func registerAllProcessors(combService *comb.CombService) {
|
|||||||
"IVYZ81NC": ivyz.ProcessIVYZ81NCRequest,
|
"IVYZ81NC": ivyz.ProcessIVYZ81NCRequest,
|
||||||
"IVYZ6G7H": ivyz.ProcessIVYZ6G7HRequest,
|
"IVYZ6G7H": ivyz.ProcessIVYZ6G7HRequest,
|
||||||
"IVYZ8I9J": ivyz.ProcessIVYZ8I9JRequest,
|
"IVYZ8I9J": ivyz.ProcessIVYZ8I9JRequest,
|
||||||
|
"IVYZ9K2L": ivyz.ProcessIVYZ9K2LRequest,
|
||||||
|
|
||||||
// COMB系列处理器 - 只注册有自定义逻辑的组合包
|
// COMB系列处理器 - 只注册有自定义逻辑的组合包
|
||||||
"COMB86PM": comb.ProcessCOMB86PMRequest, // 有自定义逻辑:重命名ApiCode
|
"COMB86PM": comb.ProcessCOMB86PMRequest, // 有自定义逻辑:重命名ApiCode
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string
|
|||||||
"IVYZ3P9M": &dto.IVYZ3P9MReq{},
|
"IVYZ3P9M": &dto.IVYZ3P9MReq{},
|
||||||
"IVYZ3A7F": &dto.IVYZ3A7FReq{},
|
"IVYZ3A7F": &dto.IVYZ3A7FReq{},
|
||||||
"IVYZ9D2E": &dto.IVYZ9D2EReq{},
|
"IVYZ9D2E": &dto.IVYZ9D2EReq{},
|
||||||
|
"IVYZ9K2L": &dto.IVYZ9K2LReq{},
|
||||||
"DWBG7F3A": &dto.DWBG7F3AReq{},
|
"DWBG7F3A": &dto.DWBG7F3AReq{},
|
||||||
"YYSY8F3A": &dto.YYSY8F3AReq{},
|
"YYSY8F3A": &dto.YYSY8F3AReq{},
|
||||||
"QCXG9P1C": &dto.QCXG9P1CReq{},
|
"QCXG9P1C": &dto.QCXG9P1CReq{},
|
||||||
@@ -368,6 +369,7 @@ func (s *FormConfigServiceImpl) generateFieldLabel(jsonTag string) string {
|
|||||||
"plate_type": "号牌类型",
|
"plate_type": "号牌类型",
|
||||||
"vin_code": "车辆识别代号VIN码",
|
"vin_code": "车辆识别代号VIN码",
|
||||||
"return_type": "返回类型",
|
"return_type": "返回类型",
|
||||||
|
"photo_data": "人脸图片",
|
||||||
}
|
}
|
||||||
|
|
||||||
if label, exists := labelMap[jsonTag]; exists {
|
if label, exists := labelMap[jsonTag]; exists {
|
||||||
@@ -409,6 +411,7 @@ func (s *FormConfigServiceImpl) generateExampleValue(fieldType reflect.Type, jso
|
|||||||
"plate_type": "01",
|
"plate_type": "01",
|
||||||
"vin_code": "LSGBF53M8DS123456",
|
"vin_code": "LSGBF53M8DS123456",
|
||||||
"return_type": "1",
|
"return_type": "1",
|
||||||
|
"photo_data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
|
||||||
}
|
}
|
||||||
|
|
||||||
if example, exists := exampleMap[jsonTag]; exists {
|
if example, exists := exampleMap[jsonTag]; exists {
|
||||||
@@ -459,6 +462,7 @@ func (s *FormConfigServiceImpl) generatePlaceholder(jsonTag string, fieldType st
|
|||||||
"plate_type": "请选择号牌类型(01或02)",
|
"plate_type": "请选择号牌类型(01或02)",
|
||||||
"vin_code": "请输入17位车辆识别代号VIN码",
|
"vin_code": "请输入17位车辆识别代号VIN码",
|
||||||
"return_type": "请选择返回类型",
|
"return_type": "请选择返回类型",
|
||||||
|
"photo_data": "请输入base64编码的人脸图片(支持JPG、BMP、PNG格式)",
|
||||||
}
|
}
|
||||||
|
|
||||||
if placeholder, exists := placeholderMap[jsonTag]; exists {
|
if placeholder, exists := placeholderMap[jsonTag]; exists {
|
||||||
@@ -511,6 +515,7 @@ func (s *FormConfigServiceImpl) generateDescription(jsonTag string, validation s
|
|||||||
"plate_type": "号牌类型:01-小型汽车;02-大型汽车(可选)",
|
"plate_type": "号牌类型:01-小型汽车;02-大型汽车(可选)",
|
||||||
"vin_code": "请输入17位车辆识别代号VIN码(Vehicle Identification Number)",
|
"vin_code": "请输入17位车辆识别代号VIN码(Vehicle Identification Number)",
|
||||||
"return_type": "返回类型:1-专业和学校名称数据返回编码形式(默认);2-专业和学校名称数据返回中文名称",
|
"return_type": "返回类型:1-专业和学校名称数据返回编码形式(默认);2-专业和学校名称数据返回中文名称",
|
||||||
|
"photo_data": "人脸图片(选填):base64编码的图片数据,仅支持JPG、BMP、PNG三种格式",
|
||||||
}
|
}
|
||||||
|
|
||||||
if desc, exists := descMap[jsonTag]; exists {
|
if desc, exists := descMap[jsonTag]; exists {
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package ivyz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tyapi-server/internal/domains/api/dto"
|
||||||
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
|
"tyapi-server/internal/infrastructure/external/westdex"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProcessIVYZ9K2LRequest IVYZ9K2L API处理方法 - 身份认证三要素(人脸图像版)
|
||||||
|
func ProcessIVYZ9K2LRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||||
|
var paramsDto dto.IVYZ9K2LReq
|
||||||
|
if err := json.Unmarshal(params, ¶msDto); err != nil {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
||||||
|
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密姓名
|
||||||
|
encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加密身份证号
|
||||||
|
encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成时间戳(毫秒)
|
||||||
|
timestamp := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
|
||||||
|
|
||||||
|
// 获取自定义编号(从 WestDexService 配置中获取 secret_id)
|
||||||
|
config := deps.WestDexService.GetConfig()
|
||||||
|
customNumber := config.SecretID
|
||||||
|
|
||||||
|
// 构建请求数据
|
||||||
|
reqData := map[string]interface{}{
|
||||||
|
"timeStamp": timestamp,
|
||||||
|
"customNumber": customNumber,
|
||||||
|
"xM": encryptedName,
|
||||||
|
"gMSFZHM": encryptedIDCard,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果提供了人脸图片,添加到请求数据中
|
||||||
|
if paramsDto.PhotoData != "" {
|
||||||
|
reqData["photoData"] = paramsDto.PhotoData
|
||||||
|
}
|
||||||
|
|
||||||
|
respBytes, err := deps.WestDexService.CallAPI(ctx, "idCardThreeElements", reqData)
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, westdex.ErrDatasource):
|
||||||
|
return nil, errors.Join(processors.ErrDatasource, err)
|
||||||
|
case errors.Is(err, westdex.ErrSystem):
|
||||||
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
|
default:
|
||||||
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return respBytes, nil
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package validator
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -93,6 +94,9 @@ func RegisterCustomValidators(validate *validator.Validate) {
|
|||||||
// 企业名称验证器
|
// 企业名称验证器
|
||||||
validate.RegisterValidation("enterprise_name", validateEnterpriseName)
|
validate.RegisterValidation("enterprise_name", validateEnterpriseName)
|
||||||
validate.RegisterValidation("validEnterpriseName", validateEnterpriseName)
|
validate.RegisterValidation("validEnterpriseName", validateEnterpriseName)
|
||||||
|
|
||||||
|
// Base64图片格式验证器(JPG、BMP、PNG)
|
||||||
|
validate.RegisterValidation("validBase64Image", validateBase64Image)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validatePhone 手机号验证
|
// validatePhone 手机号验证
|
||||||
@@ -938,3 +942,51 @@ func (bv *BusinessValidator) ValidateStruct(data interface{}) error {
|
|||||||
func (bv *BusinessValidator) ValidateField(field interface{}, tag string) error {
|
func (bv *BusinessValidator) ValidateField(field interface{}, tag string) error {
|
||||||
return bv.validator.Var(field, tag)
|
return bv.validator.Var(field, tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateBase64Image Base64图片格式验证器(JPG、BMP、PNG)
|
||||||
|
func validateBase64Image(fl validator.FieldLevel) bool {
|
||||||
|
base64Str := fl.Field().String()
|
||||||
|
|
||||||
|
// 如果为空,由 omitempty 处理
|
||||||
|
if base64Str == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 去除首尾空格
|
||||||
|
base64Str = strings.TrimSpace(base64Str)
|
||||||
|
if base64Str == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解码 base64 字符串
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(base64Str)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数据长度(至少要有文件头)
|
||||||
|
if len(decoded) < 4 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查文件头,判断图片格式
|
||||||
|
// JPG: FF D8 FF
|
||||||
|
// PNG: 89 50 4E 47
|
||||||
|
// BMP: 42 4D (BM)
|
||||||
|
if len(decoded) >= 3 && decoded[0] == 0xFF && decoded[1] == 0xD8 && decoded[2] == 0xFF {
|
||||||
|
// JPG格式
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(decoded) >= 4 && decoded[0] == 0x89 && decoded[1] == 0x50 && decoded[2] == 0x4E && decoded[3] == 0x47 {
|
||||||
|
// PNG格式
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(decoded) >= 2 && decoded[0] == 0x42 && decoded[1] == 0x4D {
|
||||||
|
// BMP格式
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user