f
This commit is contained in:
1081
internal/domains/api/dto/api_request_dto.go
Normal file
1081
internal/domains/api/dto/api_request_dto.go
Normal file
File diff suppressed because it is too large
Load Diff
10
internal/domains/api/dto/pdfg_dto.go
Normal file
10
internal/domains/api/dto/pdfg_dto.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package dto
|
||||
|
||||
// PDFG01GZReq PDFG01GZ 请求参数
|
||||
type PDFG01GZReq struct {
|
||||
Name string `json:"name" validate:"required,min=1,validName"`
|
||||
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
||||
MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"`
|
||||
Authorized string `json:"authorized" validate:"required,oneof=0 1"` // 授权标识,0或1
|
||||
}
|
||||
|
||||
154
internal/domains/api/entities/api_call.go
Normal file
154
internal/domains/api/entities/api_call.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/shopspring/decimal"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ApiCallStatus API调用状态
|
||||
const (
|
||||
ApiCallStatusPending = "pending"
|
||||
ApiCallStatusSuccess = "success"
|
||||
ApiCallStatusFailed = "failed"
|
||||
)
|
||||
|
||||
// ApiCall错误类型常量定义,供各领域服务和应用层统一引用。
|
||||
// 使用时可通过 entities.ApiCallErrorInvalidAccess 方式获得,编辑器可自动补全和提示。
|
||||
// 错误类型与业务含义:
|
||||
//
|
||||
// ApiCallErrorInvalidAccess = "invalid_access" // 无效AccessId
|
||||
// ApiCallErrorFrozenAccount = "frozen_account" // 账户冻结
|
||||
// ApiCallErrorInvalidIP = "invalid_ip" // IP无效
|
||||
// ApiCallErrorArrears = "arrears" // 账户欠费
|
||||
// ApiCallErrorNotSubscribed = "not_subscribed" // 未订阅产品
|
||||
// ApiCallErrorProductNotFound = "product_not_found" // 产品不存在
|
||||
// ApiCallErrorProductDisabled = "product_disabled" // 产品已停用
|
||||
// ApiCallErrorSystem = "system_error" // 系统错误
|
||||
// ApiCallErrorDatasource = "datasource_error" // 数据源异常
|
||||
// ApiCallErrorInvalidParam = "invalid_param" // 参数不正确
|
||||
// ApiCallErrorDecryptFail = "decrypt_fail" // 解密失败
|
||||
const (
|
||||
ApiCallErrorInvalidAccess = "invalid_access" // 无效AccessId
|
||||
ApiCallErrorFrozenAccount = "frozen_account" // 账户冻结
|
||||
ApiCallErrorInvalidIP = "invalid_ip" // IP无效
|
||||
ApiCallErrorArrears = "arrears" // 账户欠费
|
||||
ApiCallErrorNotSubscribed = "not_subscribed" // 未订阅产品
|
||||
ApiCallErrorProductNotFound = "product_not_found" // 产品不存在
|
||||
ApiCallErrorProductDisabled = "product_disabled" // 产品已停用
|
||||
ApiCallErrorSystem = "system_error" // 系统错误
|
||||
ApiCallErrorDatasource = "datasource_error" // 数据源异常
|
||||
ApiCallErrorInvalidParam = "invalid_param" // 参数不正确
|
||||
ApiCallErrorDecryptFail = "decrypt_fail" // 解密失败
|
||||
ApiCallErrorQueryEmpty = "query_empty" // 查询为空
|
||||
)
|
||||
|
||||
// ApiCall API调用(聚合根)
|
||||
type ApiCall struct {
|
||||
ID string `gorm:"type:varchar(64);primaryKey" json:"id"`
|
||||
AccessId string `gorm:"type:varchar(64);not null;index" json:"access_id"`
|
||||
UserId *string `gorm:"type:varchar(36);index" json:"user_id,omitempty"`
|
||||
ProductId *string `gorm:"type:varchar(64);index" json:"product_id,omitempty"`
|
||||
TransactionId string `gorm:"type:varchar(36);not null;uniqueIndex" json:"transaction_id"`
|
||||
ClientIp string `gorm:"type:varchar(64);not null;index" json:"client_ip"`
|
||||
RequestParams string `gorm:"type:text" json:"request_params"`
|
||||
ResponseData *string `gorm:"type:text" json:"response_data,omitempty"`
|
||||
Status string `gorm:"type:varchar(20);not null;default:'pending'" json:"status"`
|
||||
StartAt time.Time `gorm:"not null;index" json:"start_at"`
|
||||
EndAt *time.Time `gorm:"index" json:"end_at,omitempty"`
|
||||
Cost *decimal.Decimal `gorm:"default:0" json:"cost,omitempty"`
|
||||
ErrorType *string `gorm:"type:varchar(32)" json:"error_type,omitempty"`
|
||||
ErrorMsg *string `gorm:"type:varchar(256)" json:"error_msg,omitempty"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||
}
|
||||
|
||||
// NewApiCall 工厂方法
|
||||
func NewApiCall(accessId, requestParams, clientIp string) (*ApiCall, error) {
|
||||
if accessId == "" {
|
||||
return nil, errors.New("AccessId不能为空")
|
||||
}
|
||||
if clientIp == "" {
|
||||
return nil, errors.New("ClientIp不能为空")
|
||||
}
|
||||
|
||||
return &ApiCall{
|
||||
ID: uuid.New().String(),
|
||||
AccessId: accessId,
|
||||
TransactionId: GenerateTransactionID(),
|
||||
ClientIp: clientIp,
|
||||
RequestParams: requestParams,
|
||||
Status: ApiCallStatusPending,
|
||||
StartAt: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MarkSuccess 标记为成功
|
||||
func (a *ApiCall) MarkSuccess(cost decimal.Decimal) error {
|
||||
// 校验除ErrorMsg和ErrorType外所有字段不能为空
|
||||
if a.ID == "" || a.AccessId == "" || a.TransactionId == "" || a.Status == "" || a.StartAt.IsZero() {
|
||||
return errors.New("ApiCall字段不能为空(除ErrorMsg和ErrorType)")
|
||||
}
|
||||
// 可选字段也要有值
|
||||
if a.UserId == nil || a.ProductId == nil {
|
||||
return errors.New("ApiCall标记成功时UserId、ProductId不能为空")
|
||||
}
|
||||
a.Status = ApiCallStatusSuccess
|
||||
endAt := time.Now()
|
||||
a.EndAt = &endAt
|
||||
a.Cost = &cost
|
||||
a.ErrorType = nil
|
||||
a.ErrorMsg = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkFailed 标记为失败
|
||||
func (a *ApiCall) MarkFailed(errorType, errorMsg string) {
|
||||
a.Status = ApiCallStatusFailed
|
||||
a.ErrorType = &errorType
|
||||
shortMsg := errorMsg
|
||||
if len(shortMsg) > 120 {
|
||||
shortMsg = shortMsg[:120]
|
||||
}
|
||||
a.ErrorMsg = &shortMsg
|
||||
endAt := time.Now()
|
||||
a.EndAt = &endAt
|
||||
}
|
||||
|
||||
// Validate 校验ApiCall聚合根的业务规则
|
||||
func (a *ApiCall) Validate() error {
|
||||
if a.ID == "" {
|
||||
return errors.New("ID不能为空")
|
||||
}
|
||||
if a.AccessId == "" {
|
||||
return errors.New("AccessId不能为空")
|
||||
}
|
||||
if a.TransactionId == "" {
|
||||
return errors.New("TransactionId不能为空")
|
||||
}
|
||||
if a.Status != ApiCallStatusPending && a.Status != ApiCallStatusSuccess && a.Status != ApiCallStatusFailed {
|
||||
return errors.New("无效的调用状态")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateTransactionID 生成UUID格式的交易单号
|
||||
func GenerateTransactionID() string {
|
||||
return uuid.New().String()
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (ApiCall) TableName() string {
|
||||
return "api_calls"
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID
|
||||
func (c *ApiCall) BeforeCreate(tx *gorm.DB) error {
|
||||
if c.ID == "" {
|
||||
c.ID = uuid.New().String()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
362
internal/domains/api/entities/api_user.go
Normal file
362
internal/domains/api/entities/api_user.go
Normal file
@@ -0,0 +1,362 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"database/sql/driver"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ApiUserStatus API用户状态
|
||||
const (
|
||||
ApiUserStatusNormal = "normal"
|
||||
ApiUserStatusFrozen = "frozen"
|
||||
)
|
||||
|
||||
// WhiteListItem 白名单项,包含IP地址、添加时间和备注
|
||||
type WhiteListItem struct {
|
||||
IPAddress string `json:"ip_address"` // IP地址
|
||||
AddedAt time.Time `json:"added_at"` // 添加时间
|
||||
Remark string `json:"remark"` // 备注
|
||||
}
|
||||
|
||||
// WhiteList 白名单类型,支持向后兼容(旧的字符串数组格式)
|
||||
type WhiteList []WhiteListItem
|
||||
|
||||
// Value 实现 driver.Valuer 接口,用于数据库写入
|
||||
func (w WhiteList) Value() (driver.Value, error) {
|
||||
if w == nil {
|
||||
return "[]", nil
|
||||
}
|
||||
data, err := json.Marshal(w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
// Scan 实现 sql.Scanner 接口,用于数据库读取(支持向后兼容)
|
||||
func (w *WhiteList) Scan(value interface{}) error {
|
||||
if value == nil {
|
||||
*w = WhiteList{}
|
||||
return nil
|
||||
}
|
||||
|
||||
var bytes []byte
|
||||
switch v := value.(type) {
|
||||
case []byte:
|
||||
bytes = v
|
||||
case string:
|
||||
bytes = []byte(v)
|
||||
default:
|
||||
return errors.New("无法扫描 WhiteList 类型")
|
||||
}
|
||||
|
||||
if len(bytes) == 0 || string(bytes) == "[]" || string(bytes) == "null" {
|
||||
*w = WhiteList{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 首先尝试解析为新格式(结构体数组)
|
||||
var items []WhiteListItem
|
||||
if err := json.Unmarshal(bytes, &items); err == nil {
|
||||
// 成功解析为新格式
|
||||
*w = WhiteList(items)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 如果失败,尝试解析为旧格式(字符串数组)
|
||||
var oldFormat []string
|
||||
if err := json.Unmarshal(bytes, &oldFormat); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将旧格式转换为新格式
|
||||
now := time.Now()
|
||||
items = make([]WhiteListItem, 0, len(oldFormat))
|
||||
for _, ip := range oldFormat {
|
||||
items = append(items, WhiteListItem{
|
||||
IPAddress: ip,
|
||||
AddedAt: now, // 使用当前时间作为添加时间(因为旧数据没有时间信息)
|
||||
Remark: "", // 旧数据没有备注信息
|
||||
})
|
||||
}
|
||||
*w = WhiteList(items)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApiUser API用户(聚合根)
|
||||
type ApiUser struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(64)" json:"id"`
|
||||
UserId string `gorm:"type:varchar(36);not null;uniqueIndex" json:"user_id"`
|
||||
AccessId string `gorm:"type:varchar(64);not null;uniqueIndex" json:"access_id"`
|
||||
SecretKey string `gorm:"type:varchar(128);not null" json:"secret_key"`
|
||||
Status string `gorm:"type:varchar(20);not null;default:'normal'" json:"status"`
|
||||
WhiteList WhiteList `gorm:"type:json;default:'[]'" json:"white_list"` // 支持多个白名单,包含IP和添加时间,支持向后兼容
|
||||
|
||||
// 余额预警配置
|
||||
BalanceAlertEnabled bool `gorm:"default:true" json:"balance_alert_enabled" comment:"是否启用余额预警"`
|
||||
BalanceAlertThreshold float64 `gorm:"default:200.00" json:"balance_alert_threshold" comment:"余额预警阈值"`
|
||||
AlertPhone string `gorm:"type:varchar(20)" json:"alert_phone" comment:"预警手机号"`
|
||||
LastLowBalanceAlert *time.Time `json:"last_low_balance_alert" comment:"最后低余额预警时间"`
|
||||
LastArrearsAlert *time.Time `json:"last_arrears_alert" comment:"最后欠费预警时间"`
|
||||
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"`
|
||||
}
|
||||
|
||||
// IsWhiteListed 校验IP/域名是否在白名单
|
||||
func (u *ApiUser) IsWhiteListed(target string) bool {
|
||||
for _, w := range u.WhiteList {
|
||||
if w.IPAddress == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsActive 是否可用
|
||||
func (u *ApiUser) IsActive() bool {
|
||||
return u.Status == ApiUserStatusNormal
|
||||
}
|
||||
|
||||
// IsFrozen 是否冻结
|
||||
func (u *ApiUser) IsFrozen() bool {
|
||||
return u.Status == ApiUserStatusFrozen
|
||||
}
|
||||
|
||||
// NewApiUser 工厂方法
|
||||
func NewApiUser(userId string, defaultAlertEnabled bool, defaultAlertThreshold float64) (*ApiUser, error) {
|
||||
if userId == "" {
|
||||
return nil, errors.New("用户ID不能为空")
|
||||
}
|
||||
accessId, err := GenerateSecretId()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
secretKey, err := GenerateSecretKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ApiUser{
|
||||
ID: uuid.New().String(),
|
||||
UserId: userId,
|
||||
AccessId: accessId,
|
||||
SecretKey: secretKey,
|
||||
Status: ApiUserStatusNormal,
|
||||
WhiteList: WhiteList{},
|
||||
BalanceAlertEnabled: defaultAlertEnabled,
|
||||
BalanceAlertThreshold: defaultAlertThreshold,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 领域行为
|
||||
func (u *ApiUser) Freeze() {
|
||||
u.Status = ApiUserStatusFrozen
|
||||
}
|
||||
func (u *ApiUser) Unfreeze() {
|
||||
u.Status = ApiUserStatusNormal
|
||||
}
|
||||
func (u *ApiUser) UpdateWhiteList(list []WhiteListItem) {
|
||||
u.WhiteList = WhiteList(list)
|
||||
}
|
||||
|
||||
// AddToWhiteList 新增白名单项(防御性校验)
|
||||
func (u *ApiUser) AddToWhiteList(entry string, remark string) error {
|
||||
if len(u.WhiteList) >= 10 {
|
||||
return errors.New("白名单最多只能有10个")
|
||||
}
|
||||
if net.ParseIP(entry) == nil {
|
||||
return errors.New("非法IP")
|
||||
}
|
||||
for _, w := range u.WhiteList {
|
||||
if w.IPAddress == entry {
|
||||
return errors.New("白名单已存在")
|
||||
}
|
||||
}
|
||||
u.WhiteList = append(u.WhiteList, WhiteListItem{
|
||||
IPAddress: entry,
|
||||
AddedAt: time.Now(),
|
||||
Remark: remark,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// BeforeUpdate GORM钩子:更新前确保WhiteList不为nil
|
||||
func (u *ApiUser) BeforeUpdate(tx *gorm.DB) error {
|
||||
if u.WhiteList == nil {
|
||||
u.WhiteList = WhiteList{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveFromWhiteList 删除白名单项
|
||||
func (u *ApiUser) RemoveFromWhiteList(entry string) error {
|
||||
newList := make([]WhiteListItem, 0, len(u.WhiteList))
|
||||
for _, w := range u.WhiteList {
|
||||
if w.IPAddress != entry {
|
||||
newList = append(newList, w)
|
||||
}
|
||||
}
|
||||
if len(newList) == len(u.WhiteList) {
|
||||
return errors.New("白名单不存在")
|
||||
}
|
||||
u.WhiteList = newList
|
||||
return nil
|
||||
}
|
||||
|
||||
// 余额预警相关方法
|
||||
|
||||
// UpdateBalanceAlertSettings 更新余额预警设置
|
||||
func (u *ApiUser) UpdateBalanceAlertSettings(enabled bool, threshold float64, phone string) error {
|
||||
if threshold < 0 {
|
||||
return errors.New("预警阈值不能为负数")
|
||||
}
|
||||
if phone != "" && len(phone) != 11 {
|
||||
return errors.New("手机号格式不正确")
|
||||
}
|
||||
|
||||
u.BalanceAlertEnabled = enabled
|
||||
u.BalanceAlertThreshold = threshold
|
||||
u.AlertPhone = phone
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShouldSendLowBalanceAlert 是否应该发送低余额预警(24小时冷却期)
|
||||
func (u *ApiUser) ShouldSendLowBalanceAlert(balance float64) bool {
|
||||
if !u.BalanceAlertEnabled || u.AlertPhone == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 余额低于阈值
|
||||
if balance < u.BalanceAlertThreshold {
|
||||
// 检查是否已经发送过预警(避免频繁发送)
|
||||
if u.LastLowBalanceAlert != nil {
|
||||
// 如果距离上次预警不足24小时,不发送
|
||||
if time.Since(*u.LastLowBalanceAlert) < 24*time.Hour {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ShouldSendArrearsAlert 是否应该发送欠费预警(不受冷却期限制)
|
||||
func (u *ApiUser) ShouldSendArrearsAlert(balance float64) bool {
|
||||
if !u.BalanceAlertEnabled || u.AlertPhone == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 余额为负数(欠费)- 欠费预警不受冷却期限制
|
||||
if balance < 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MarkLowBalanceAlertSent 标记低余额预警已发送
|
||||
func (u *ApiUser) MarkLowBalanceAlertSent() {
|
||||
now := time.Now()
|
||||
u.LastLowBalanceAlert = &now
|
||||
}
|
||||
|
||||
// MarkArrearsAlertSent 标记欠费预警已发送
|
||||
func (u *ApiUser) MarkArrearsAlertSent() {
|
||||
now := time.Now()
|
||||
u.LastArrearsAlert = &now
|
||||
}
|
||||
|
||||
// Validate 校验ApiUser聚合根的业务规则
|
||||
func (u *ApiUser) Validate() error {
|
||||
if u.UserId == "" {
|
||||
return errors.New("用户ID不能为空")
|
||||
}
|
||||
if u.AccessId == "" {
|
||||
return errors.New("AccessId不能为空")
|
||||
}
|
||||
if u.SecretKey == "" {
|
||||
return errors.New("SecretKey不能为空")
|
||||
}
|
||||
switch u.Status {
|
||||
case ApiUserStatusNormal, ApiUserStatusFrozen:
|
||||
// ok
|
||||
default:
|
||||
return errors.New("无效的用户状态")
|
||||
}
|
||||
if len(u.WhiteList) > 10 {
|
||||
return errors.New("白名单最多只能有10个")
|
||||
}
|
||||
for _, item := range u.WhiteList {
|
||||
if net.ParseIP(item.IPAddress) == nil {
|
||||
return errors.New("白名单项必须为合法IP地址: " + item.IPAddress)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 生成AES-128密钥的函数,符合市面规范
|
||||
func GenerateSecretKey() (string, error) {
|
||||
key := make([]byte, 16) // 16字节密钥
|
||||
_, err := io.ReadFull(rand.Reader, key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(key), nil
|
||||
}
|
||||
|
||||
func GenerateSecretId() (string, error) {
|
||||
// 创建一个字节数组,用于存储随机数据
|
||||
bytes := make([]byte, 8) // 因为每个字节表示两个16进制字符
|
||||
|
||||
// 读取随机字节到数组中
|
||||
_, err := rand.Read(bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 将字节数组转换为16进制字符串
|
||||
return hex.EncodeToString(bytes), nil
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (ApiUser) TableName() string {
|
||||
return "api_users"
|
||||
}
|
||||
|
||||
// BeforeCreate GORM钩子:创建前自动生成UUID并确保WhiteList不为nil
|
||||
func (c *ApiUser) BeforeCreate(tx *gorm.DB) error {
|
||||
if c.ID == "" {
|
||||
c.ID = uuid.New().String()
|
||||
}
|
||||
if c.WhiteList == nil {
|
||||
c.WhiteList = WhiteList{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AfterFind GORM钩子:查询后处理数据,确保AddedAt不为零值
|
||||
func (u *ApiUser) AfterFind(tx *gorm.DB) error {
|
||||
// 如果 WhiteList 为空,初始化为空数组
|
||||
if u.WhiteList == nil {
|
||||
u.WhiteList = WhiteList{}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 确保所有项的AddedAt不为零值(处理可能从旧数据迁移的情况)
|
||||
now := time.Now()
|
||||
for i := range u.WhiteList {
|
||||
if u.WhiteList[i].AddedAt.IsZero() {
|
||||
u.WhiteList[i].AddedAt = now
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
35
internal/domains/api/entities/enterprise_report.go
Normal file
35
internal/domains/api/entities/enterprise_report.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package entities
|
||||
|
||||
import "time"
|
||||
|
||||
// Report 报告记录实体
|
||||
// 用于持久化存储各类报告(企业报告等),通过编号和类型区分
|
||||
type Report struct {
|
||||
// 报告编号,直接使用业务生成的 reportId 作为主键
|
||||
ReportID string `gorm:"primaryKey;type:varchar(64)" json:"report_id"`
|
||||
|
||||
// 报告类型,例如 enterprise(企业报告)、personal 等
|
||||
Type string `gorm:"type:varchar(32);not null;index" json:"type"`
|
||||
|
||||
// 调用来源API编码,例如 QYGLJ1U9
|
||||
ApiCode string `gorm:"type:varchar(32);not null;index" json:"api_code"`
|
||||
|
||||
// 企业名称和统一社会信用代码,便于后续检索
|
||||
EntName string `gorm:"type:varchar(255);index" json:"ent_name"`
|
||||
EntCode string `gorm:"type:varchar(64);index" json:"ent_code"`
|
||||
|
||||
// 原始请求参数(JSON字符串),用于审计和排错
|
||||
RequestParams string `gorm:"type:text" json:"request_params"`
|
||||
|
||||
// 报告完整JSON内容
|
||||
ReportData string `gorm:"type:text" json:"report_data"`
|
||||
|
||||
// 创建时间
|
||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
|
||||
}
|
||||
|
||||
// TableName 指定数据库表名
|
||||
func (Report) TableName() string {
|
||||
return "reports"
|
||||
}
|
||||
|
||||
50
internal/domains/api/repositories/api_call_repository.go
Normal file
50
internal/domains/api/repositories/api_call_repository.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"hyapi-server/internal/domains/api/entities"
|
||||
"hyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
type ApiCallRepository interface {
|
||||
Create(ctx context.Context, call *entities.ApiCall) error
|
||||
Update(ctx context.Context, call *entities.ApiCall) error
|
||||
FindById(ctx context.Context, id string) (*entities.ApiCall, error)
|
||||
FindByUserId(ctx context.Context, userId string, limit, offset int) ([]*entities.ApiCall, error)
|
||||
|
||||
// 新增:分页查询用户API调用记录
|
||||
ListByUserId(ctx context.Context, userId string, options interfaces.ListOptions) ([]*entities.ApiCall, int64, error)
|
||||
|
||||
// 新增:根据条件筛选API调用记录
|
||||
ListByUserIdWithFilters(ctx context.Context, userId string, filters map[string]interface{}, options interfaces.ListOptions) ([]*entities.ApiCall, int64, error)
|
||||
|
||||
// 新增:根据条件筛选API调用记录(包含产品名称)
|
||||
ListByUserIdWithFiltersAndProductName(ctx context.Context, userId string, filters map[string]interface{}, options interfaces.ListOptions) (map[string]string, []*entities.ApiCall, int64, error)
|
||||
|
||||
// 新增:统计用户API调用次数
|
||||
CountByUserId(ctx context.Context, userId string) (int64, error)
|
||||
|
||||
// 新增:根据用户ID和产品ID统计API调用次数
|
||||
CountByUserIdAndProductId(ctx context.Context, userId string, productId string) (int64, error)
|
||||
|
||||
// 新增:根据TransactionID查询
|
||||
FindByTransactionId(ctx context.Context, transactionId string) (*entities.ApiCall, error)
|
||||
|
||||
// 统计相关方法
|
||||
CountByUserIdAndDateRange(ctx context.Context, userId string, startDate, endDate time.Time) (int64, error)
|
||||
GetDailyStatsByUserId(ctx context.Context, userId string, startDate, endDate time.Time) ([]map[string]interface{}, error)
|
||||
GetMonthlyStatsByUserId(ctx context.Context, userId string, startDate, endDate time.Time) ([]map[string]interface{}, error)
|
||||
|
||||
// 管理端:根据条件筛选所有API调用记录(包含产品名称)
|
||||
ListWithFiltersAndProductName(ctx context.Context, filters map[string]interface{}, options interfaces.ListOptions) (map[string]string, []*entities.ApiCall, int64, error)
|
||||
|
||||
// 系统级别统计方法
|
||||
GetSystemTotalCalls(ctx context.Context) (int64, error)
|
||||
GetSystemCallsByDateRange(ctx context.Context, startDate, endDate time.Time) (int64, error)
|
||||
GetSystemDailyStats(ctx context.Context, startDate, endDate time.Time) ([]map[string]interface{}, error)
|
||||
GetSystemMonthlyStats(ctx context.Context, startDate, endDate time.Time) ([]map[string]interface{}, error)
|
||||
|
||||
// API受欢迎程度排行榜
|
||||
GetApiPopularityRanking(ctx context.Context, period string, limit int) ([]map[string]interface{}, error)
|
||||
}
|
||||
13
internal/domains/api/repositories/api_user_repository.go
Normal file
13
internal/domains/api/repositories/api_user_repository.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hyapi-server/internal/domains/api/entities"
|
||||
)
|
||||
|
||||
type ApiUserRepository interface {
|
||||
Create(ctx context.Context, user *entities.ApiUser) error
|
||||
Update(ctx context.Context, user *entities.ApiUser) error
|
||||
FindByAccessId(ctx context.Context, accessId string) (*entities.ApiUser, error)
|
||||
FindByUserId(ctx context.Context, userId string) (*entities.ApiUser, error)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"hyapi-server/internal/domains/api/entities"
|
||||
)
|
||||
|
||||
// ReportRepository 报告记录仓储接口
|
||||
type ReportRepository interface {
|
||||
// Create 创建报告记录
|
||||
Create(ctx context.Context, report *entities.Report) error
|
||||
|
||||
// FindByReportID 根据报告编号查询记录
|
||||
FindByReportID(ctx context.Context, reportID string) (*entities.Report, error)
|
||||
}
|
||||
69
internal/domains/api/services/api_call_aggregate_service.go
Normal file
69
internal/domains/api/services/api_call_aggregate_service.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"hyapi-server/internal/domains/api/entities"
|
||||
repo "hyapi-server/internal/domains/api/repositories"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ApiCallAggregateService 聚合服务,管理ApiCall生命周期
|
||||
type ApiCallAggregateService interface {
|
||||
CreateApiCall(accessId, requestParams, clientIp string) (*entities.ApiCall, error)
|
||||
LoadApiCall(ctx context.Context, id string) (*entities.ApiCall, error)
|
||||
SaveApiCall(ctx context.Context, call *entities.ApiCall) error
|
||||
}
|
||||
|
||||
type ApiCallAggregateServiceImpl struct {
|
||||
apiUserRepo repo.ApiUserRepository
|
||||
apiCallRepo repo.ApiCallRepository
|
||||
}
|
||||
|
||||
func NewApiCallAggregateService(apiUserRepo repo.ApiUserRepository, apiCallRepo repo.ApiCallRepository) ApiCallAggregateService {
|
||||
return &ApiCallAggregateServiceImpl{
|
||||
apiUserRepo: apiUserRepo,
|
||||
apiCallRepo: apiCallRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// NewApiCall 创建ApiCall
|
||||
func (s *ApiCallAggregateServiceImpl) CreateApiCall(accessId, requestParams, clientIp string) (*entities.ApiCall, error) {
|
||||
return entities.NewApiCall(accessId, requestParams, clientIp)
|
||||
}
|
||||
|
||||
// GetApiCallById 查询ApiCall
|
||||
func (s *ApiCallAggregateServiceImpl) LoadApiCall(ctx context.Context, id string) (*entities.ApiCall, error) {
|
||||
return s.apiCallRepo.FindById(ctx, id)
|
||||
}
|
||||
|
||||
// SaveApiCall 保存ApiCall
|
||||
func (s *ApiCallAggregateServiceImpl) SaveApiCall(ctx context.Context, call *entities.ApiCall) error {
|
||||
// 先尝试查找现有记录
|
||||
existingCall, err := s.apiCallRepo.FindById(ctx, call.ID)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 记录不存在,执行创建
|
||||
err = s.apiCallRepo.Create(ctx, call)
|
||||
if err != nil {
|
||||
return fmt.Errorf("创建ApiCall失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// 其他错误
|
||||
return fmt.Errorf("查询ApiCall失败: %w", err)
|
||||
}
|
||||
|
||||
// 记录存在,执行更新
|
||||
if existingCall != nil {
|
||||
err = s.apiCallRepo.Update(ctx, call)
|
||||
if err != nil {
|
||||
return fmt.Errorf("更新ApiCall失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 理论上不会到达这里,但为了安全起见
|
||||
return s.apiCallRepo.Create(ctx, call)
|
||||
}
|
||||
430
internal/domains/api/services/api_request_service.go
Normal file
430
internal/domains/api/services/api_request_service.go
Normal file
@@ -0,0 +1,430 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"hyapi-server/internal/application/api/commands"
|
||||
appconfig "hyapi-server/internal/config"
|
||||
api_repositories "hyapi-server/internal/domains/api/repositories"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/domains/api/services/processors/comb"
|
||||
"hyapi-server/internal/domains/api/services/processors/dwbg"
|
||||
"hyapi-server/internal/domains/api/services/processors/flxg"
|
||||
"hyapi-server/internal/domains/api/services/processors/ivyz"
|
||||
"hyapi-server/internal/domains/api/services/processors/jrzq"
|
||||
"hyapi-server/internal/domains/api/services/processors/pdfg"
|
||||
"hyapi-server/internal/domains/api/services/processors/qcxg"
|
||||
"hyapi-server/internal/domains/api/services/processors/qygl"
|
||||
"hyapi-server/internal/domains/api/services/processors/test"
|
||||
"hyapi-server/internal/domains/api/services/processors/yysy"
|
||||
"hyapi-server/internal/domains/product/services"
|
||||
"hyapi-server/internal/infrastructure/external/alicloud"
|
||||
"hyapi-server/internal/infrastructure/external/jiguang"
|
||||
"hyapi-server/internal/infrastructure/external/muzi"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
"hyapi-server/internal/infrastructure/external/tianyancha"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
"hyapi-server/internal/infrastructure/external/yushan"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
"hyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDatasource = processors.ErrDatasource
|
||||
ErrSystem = processors.ErrSystem
|
||||
ErrInvalidParam = processors.ErrInvalidParam
|
||||
ErrNotFound = processors.ErrNotFound
|
||||
)
|
||||
|
||||
type ApiRequestService struct {
|
||||
// 可注入依赖,如第三方服务、模型等
|
||||
westDexService *westdex.WestDexService
|
||||
muziService *muzi.MuziService
|
||||
yushanService *yushan.YushanService
|
||||
tianYanChaService *tianyancha.TianYanChaService
|
||||
alicloudService *alicloud.AlicloudService
|
||||
validator interfaces.RequestValidator
|
||||
processorDeps *processors.ProcessorDependencies
|
||||
combService *comb.CombService
|
||||
config *appconfig.Config
|
||||
|
||||
reportRepo api_repositories.ReportRepository
|
||||
}
|
||||
|
||||
func NewApiRequestService(
|
||||
westDexService *westdex.WestDexService,
|
||||
shujubaoService *shujubao.ShujubaoService,
|
||||
muziService *muzi.MuziService,
|
||||
yushanService *yushan.YushanService,
|
||||
tianYanChaService *tianyancha.TianYanChaService,
|
||||
alicloudService *alicloud.AlicloudService,
|
||||
zhichaService *zhicha.ZhichaService,
|
||||
xingweiService *xingwei.XingweiService,
|
||||
jiguangService *jiguang.JiguangService,
|
||||
shumaiService *shumai.ShumaiService,
|
||||
validator interfaces.RequestValidator,
|
||||
productManagementService *services.ProductManagementService,
|
||||
cfg *appconfig.Config,
|
||||
) *ApiRequestService {
|
||||
return NewApiRequestServiceWithRepos(
|
||||
westDexService,
|
||||
shujubaoService,
|
||||
muziService,
|
||||
yushanService,
|
||||
tianYanChaService,
|
||||
alicloudService,
|
||||
zhichaService,
|
||||
xingweiService,
|
||||
jiguangService,
|
||||
shumaiService,
|
||||
validator,
|
||||
productManagementService,
|
||||
cfg,
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
}
|
||||
|
||||
// NewApiRequestServiceWithRepos 带自定义仓储的构造函数,便于扩展(例如企业报告记录)
|
||||
func NewApiRequestServiceWithRepos(
|
||||
westDexService *westdex.WestDexService,
|
||||
shujubaoService *shujubao.ShujubaoService,
|
||||
muziService *muzi.MuziService,
|
||||
yushanService *yushan.YushanService,
|
||||
tianYanChaService *tianyancha.TianYanChaService,
|
||||
alicloudService *alicloud.AlicloudService,
|
||||
zhichaService *zhicha.ZhichaService,
|
||||
xingweiService *xingwei.XingweiService,
|
||||
jiguangService *jiguang.JiguangService,
|
||||
shumaiService *shumai.ShumaiService,
|
||||
validator interfaces.RequestValidator,
|
||||
productManagementService *services.ProductManagementService,
|
||||
cfg *appconfig.Config,
|
||||
reportRepo api_repositories.ReportRepository,
|
||||
qyglReportPDFScheduler processors.QYGLReportPDFScheduler,
|
||||
) *ApiRequestService {
|
||||
// 创建组合包服务
|
||||
combService := comb.NewCombService(productManagementService)
|
||||
|
||||
apiPublicBase := ""
|
||||
if cfg != nil {
|
||||
apiPublicBase = appconfig.ResolveAPIPublicBaseURL(&cfg.API)
|
||||
}
|
||||
|
||||
// 创建处理器依赖容器
|
||||
processorDeps := processors.NewProcessorDependencies(
|
||||
westDexService,
|
||||
shujubaoService,
|
||||
muziService,
|
||||
yushanService,
|
||||
tianYanChaService,
|
||||
alicloudService,
|
||||
zhichaService,
|
||||
xingweiService,
|
||||
jiguangService,
|
||||
shumaiService,
|
||||
validator,
|
||||
combService,
|
||||
reportRepo,
|
||||
qyglReportPDFScheduler,
|
||||
apiPublicBase,
|
||||
)
|
||||
|
||||
// 统一注册所有处理器
|
||||
registerAllProcessors(combService)
|
||||
|
||||
return &ApiRequestService{
|
||||
westDexService: westDexService,
|
||||
muziService: muziService,
|
||||
yushanService: yushanService,
|
||||
tianYanChaService: tianYanChaService,
|
||||
alicloudService: alicloudService,
|
||||
validator: validator,
|
||||
processorDeps: processorDeps,
|
||||
combService: combService,
|
||||
config: cfg,
|
||||
reportRepo: reportRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// registerAllProcessors 统一注册所有处理器
|
||||
func registerAllProcessors(combService *comb.CombService) {
|
||||
// 定义所有处理器映射
|
||||
processorMap := map[string]processors.ProcessorFunc{
|
||||
// FLXG系列处理器
|
||||
"FLXG0V3B": flxg.ProcessFLXG0V3Bequest,
|
||||
"FLXG0V4B": flxg.ProcessFLXG0V4BRequest,
|
||||
"FLXG162A": flxg.ProcessFLXG162ARequest,
|
||||
"FLXG3D56": flxg.ProcessFLXG3D56Request,
|
||||
"FLXG54F5": flxg.ProcessFLXG54F5Request,
|
||||
"FLXG5876": flxg.ProcessFLXG5876Request,
|
||||
"FLXG75FE": flxg.ProcessFLXG75FERequest,
|
||||
"FLXG9687": flxg.ProcessFLXG9687Request,
|
||||
"FLXG970F": flxg.ProcessFLXG970FRequest,
|
||||
"FLXGC9D1": flxg.ProcessFLXGC9D1Request,
|
||||
"FLXGCA3D": flxg.ProcessFLXGCA3DRequest,
|
||||
"FLXGDEC7": flxg.ProcessFLXGDEC7Request,
|
||||
"FLXG8A3F": flxg.ProcessFLXG8A3FRequest,
|
||||
"FLXG5B2E": flxg.ProcessFLXG5B2ERequest,
|
||||
"FLXG0687": flxg.ProcessFLXG0687Request,
|
||||
"FLXGBC21": flxg.ProcessFLXGBC21Request,
|
||||
"FLXGDEA8": flxg.ProcessFLXGDEA8Request,
|
||||
"FLXGDEA9": flxg.ProcessFLXGDEA9Request,
|
||||
"FLXG5A3B": flxg.ProcessFLXG5A3BRequest,
|
||||
"FLXG9C1D": flxg.ProcessFLXG9C1DRequest,
|
||||
"FLXG2E8F": flxg.ProcessFLXG2E8FRequest,
|
||||
"FLXG7E8F": flxg.ProcessFLXG7E8FRequest,
|
||||
"FLXG3A9B": flxg.ProcessFLXG3A9BRequest,
|
||||
"FLXGK5D2": flxg.ProcessFLXGK5D2Request,
|
||||
"FLXGDJG3": flxg.ProcessFLXGDJG3Request, //董监高司法综合信息核验
|
||||
// JRZQ系列处理器
|
||||
"JRZQ8203": jrzq.ProcessJRZQ8203Request,
|
||||
"JRZQ0A03": jrzq.ProcessJRZQ0A03Request,
|
||||
"JRZQ4AA8": jrzq.ProcessJRZQ4AA8Request,
|
||||
"JRZQDCBE": jrzq.ProcessJRZQDCBERequest,
|
||||
"JRZQACAB": jrzq.ProcessJRZQACABERequest, // 银行卡四要素
|
||||
"JRZQ09J8": jrzq.ProcessJRZQ09J8Request,
|
||||
"JRZQ1D09": jrzq.ProcessJRZQ1D09Request,
|
||||
"JRZQ3C7B": jrzq.ProcessJRZQ3C7BRequest,
|
||||
"JRZQ8A2D": jrzq.ProcessJRZQ8A2DRequest,
|
||||
"JRZQ5E9F": jrzq.ProcessJRZQ5E9FRequest,
|
||||
"JRZQ4B6C": jrzq.ProcessJRZQ4B6CRequest,
|
||||
"JRZQ7F1A": jrzq.ProcessJRZQ7F1ARequest,
|
||||
"JRZQ9E2A": jrzq.ProcessJRZQ9E2ARequest,
|
||||
"JRZQ6F2A": jrzq.ProcessJRZQ6F2ARequest,
|
||||
"JRZQ8B3C": jrzq.ProcessJRZQ8B3CRequest,
|
||||
"JRZQ9D4E": jrzq.ProcessJRZQ9D4ERequest,
|
||||
"JRZQ0L85": jrzq.ProcessJRZQ0L85Request,
|
||||
"JRZQ2F8A": jrzq.ProcessJRZQ2F8ARequest,
|
||||
"JRZQ1E7B": jrzq.ProcessJRZQ1E7BRequest,
|
||||
"JRZQ3C9R": jrzq.ProcessJRZQ3C9RRequest,
|
||||
"JRZQ0B6Y": jrzq.ProcessJRZQ0B6YRequest,
|
||||
"JRZQ9A1W": jrzq.ProcessJRZQ9A1WRequest,
|
||||
"JRZQ8F7C": jrzq.ProcessJRZQ8F7CRequest,
|
||||
"JRZQ1W4X": jrzq.ProcessJRZQ1W4XRequest,
|
||||
"JRZQ3P01": jrzq.ProcessJRZQ3P01Request,
|
||||
"JRZQ3AG6": jrzq.ProcessJRZQ3AG6Request,
|
||||
"JRZQO6L7": jrzq.ProcessJRZQO6L7Request, // 全国自然人经济特征评分模型v3 简版
|
||||
"JRZQO7L1": jrzq.ProcessJRZQO7L1Request, // 全国自然人经济特征评分模型v4 详版
|
||||
"JRZQS7G0": jrzq.ProcessJRZQS7G0Request, // 社保综合评分V1
|
||||
"JRZQ1P5G": jrzq.ProcessJRZQ1P5GRequest, // 全国自然人借贷压力指数查询(2)
|
||||
"JRZQOCRE": jrzq.ProcessJRZQOCREERequest, // 银行卡OCR数卖
|
||||
"JRZQOCRY": jrzq.ProcessJRZQOCRYERequest, // 银行卡OCR数据宝
|
||||
|
||||
// QYGL系列处理器
|
||||
"QYGL8261": qygl.ProcessQYGL8261Request,
|
||||
"QYGL2ACD": qygl.ProcessQYGL2ACDRequest,
|
||||
"QYGL45BD": qygl.ProcessQYGL45BDRequest,
|
||||
"QYGL6F2D": qygl.ProcessQYGL6F2DRequest,
|
||||
"QYGL8271": qygl.ProcessQYGL8271Request,
|
||||
"QYGLB4C0": qygl.ProcessQYGLB4C0Request,
|
||||
"QYGL23T7": qygl.ProcessQYGL23T7Request, // 企业三要素验证
|
||||
"QYGL5A3C": qygl.ProcessQYGL5A3CRequest, // 对外投资历史
|
||||
"QYGL8B4D": qygl.ProcessQYGL8B4DRequest, // 融资历史
|
||||
"QYGL9E2F": qygl.ProcessQYGL9E2FRequest, // 行政处罚
|
||||
"QYGL7C1A": qygl.ProcessQYGL7C1ARequest, // 经营异常
|
||||
"QYGL3F8E": qygl.ProcessQYGL3F8ERequest, // 人企关系加强版
|
||||
"QYGL7D9A": qygl.ProcessQYGL7D9ARequest, // 欠税公告
|
||||
"QYGL4B2E": qygl.ProcessQYGL4B2ERequest, // 税收违法
|
||||
"COMENT01": qygl.ProcessCOMENT01Request, // 企业风险报告
|
||||
"QYGL5F6A": qygl.ProcessQYGL5F6ARequest, // 企业相关查询
|
||||
"QYGL2B5C": qygl.ProcessQYGL2B5CRequest, // 企业联系人实际经营地址
|
||||
"QYGL6S1B": qygl.ProcessQYGL6S1BRequest, //董监高司法综合信息核验
|
||||
"QYGL9T1Q": qygl.ProcessQYGL9T1QRequest, //全国企业借贷意向验证查询_V1
|
||||
"QYGL5A9T": qygl.ProcessQYGL5A9TRequest, //全国企业各类工商风险统计数量查询
|
||||
"QYGL2S0W": qygl.ProcessQYGL2S0WRequest, //失信被执行企业个人查询
|
||||
"QYGL5CMP": qygl.ProcessQYGL5CMPRequest, //企业五要素验证
|
||||
"QYGL66SL": qygl.ProcessQYGL66SLRequest, //全国企业司法模型服务查询_V1
|
||||
"QYGL2NAO": qygl.ProcessQYGL2naoRequest, //股权变更
|
||||
"QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息
|
||||
"QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透
|
||||
"QYGL5S1I": qygl.ProcessQYGL5S1IRequest, //企业司法涉诉I
|
||||
"QYGLJ1U9": qygl.ProcessQYGLJ1U9Request, //企业全景报告(聚合 QYGLUY3S/QYGLJ0Q1/QYGL5S1I)
|
||||
"QYGLJ0Q1": qygl.ProcessQYGLJ0Q1Request, //企业股权结构全景查询
|
||||
"QYGLUY3S": qygl.ProcessQYGLUY3SRequest, //企业经营状态全景查询
|
||||
"QYGLDJ12": qygl.ProcessQYGLDJ12Request, //企业年报信息核验
|
||||
"QYGL8848": qygl.ProcessQYGL8848Request, //企业税收违法核查
|
||||
|
||||
// YYSY系列处理器
|
||||
"YYSY35TA": yysy.ProcessYYSY35TARequest, //运营商归属地数卖
|
||||
"YYSYD50F": yysy.ProcessYYSYD50FRequest,
|
||||
"YYSY09CD": yysy.ProcessYYSY09CDRequest,
|
||||
"YYSY4B21": yysy.ProcessYYSY4B21Request,
|
||||
"YYSY4B37": yysy.ProcessYYSY4B37Request,
|
||||
"YYSY6F2E": yysy.ProcessYYSY6F2ERequest,
|
||||
"YYSYBE08": yysy.ProcessYYSYBE08Request,
|
||||
"YYSYBE08TEST": yysy.ProcessYYSYBE08testRequest, // 二要素(阿里云市场),与 YYSYBE08 入参一致
|
||||
"YYSYF7DB": yysy.ProcessYYSYF7DBRequest,
|
||||
"YYSY4F2E": yysy.ProcessYYSY4F2ERequest,
|
||||
"YYSY8B1C": yysy.ProcessYYSY8B1CRequest,
|
||||
"YYSY6D9A": yysy.ProcessYYSY6D9ARequest,
|
||||
"YYSY3E7F": yysy.ProcessYYSY3E7FRequest,
|
||||
"YYSY8F3A": yysy.ProcessYYSY8F3ARequest,
|
||||
"YYSY9A1B": yysy.ProcessYYSY9A1BRequest,
|
||||
"YYSY8C2D": yysy.ProcessYYSY8C2DRequest,
|
||||
"YYSY7D3E": yysy.ProcessYYSY7D3ERequest,
|
||||
"YYSY9E4A": yysy.ProcessYYSY9E4ARequest,
|
||||
"YYSY9F1B": yysy.ProcessYYSY9F1BYequest,
|
||||
"YYSY6F2B": yysy.ProcessYYSY6F2BRequest,
|
||||
"YYSY3M8S": yysy.ProcessYYSY3M8SRequest, //运营商二要素查询
|
||||
"YYSYC4R9": yysy.ProcessYYSYC4R9Request, //运营商三要素详版查询
|
||||
"YYSYH6D2": yysy.ProcessYYSYH6D2Request, //运营商三要素简版查询
|
||||
"YYSYP0T4": yysy.ProcessYYSYP0T4Request, //在网时长查询
|
||||
"YYSYE7V5": yysy.ProcessYYSYE7V5Request, //手机在网状态查询
|
||||
"YYSYS9W1": yysy.ProcessYYSYS9W1Request, //手机携号转网查询
|
||||
"YYSYK8R3": yysy.ProcessYYSYK8R3Request, //手机空号检测查询
|
||||
"YYSYH6F3": yysy.ProcessYYSYH6F3Request, //运营商三要素即时版查询
|
||||
"YYSYK9R4": yysy.ProcessYYSYK9R4Request, //全网手机三要素验证1979周更新版
|
||||
"YYSYF2T7": yysy.ProcessYYSYF2T7Request, //手机二次放号检测查询
|
||||
|
||||
// IVYZ系列处理器
|
||||
"IVYZ0B03": ivyz.ProcessIVYZ0B03Request,
|
||||
"IVYZ2125": ivyz.ProcessIVYZ2125Request,
|
||||
"IVYZ385E": ivyz.ProcessIVYZ385ERequest,
|
||||
"IVYZ5733": ivyz.ProcessIVYZ5733Request,
|
||||
"IVYZ9363": ivyz.ProcessIVYZ9363Request,
|
||||
"IVYZ9A2B": ivyz.ProcessIVYZ9A2BRequest,
|
||||
"IVYZADEE": ivyz.ProcessIVYZADEERequest,
|
||||
"IVYZ7F2A": ivyz.ProcessIVYZ7F2ARequest,
|
||||
"IVYZ4E8B": ivyz.ProcessIVYZ4E8BRequest,
|
||||
"IVYZ1C9D": ivyz.ProcessIVYZ1C9DRequest,
|
||||
"IVYZGZ08": ivyz.ProcessIVYZGZ08Request,
|
||||
"IVYZ2A8B": ivyz.ProcessIVYZ2A8BRequest,
|
||||
"IVYZ7C9D": ivyz.ProcessIVYZ7C9DRequest,
|
||||
"IVYZ5E3F": ivyz.ProcessIVYZ5E3FRequest,
|
||||
"IVYZ7F3A": ivyz.ProcessIVYZ7F3ARequest,
|
||||
"IVYZ3P9M": ivyz.ProcessIVYZ3P9MRequest,
|
||||
"IVYZ3A7F": ivyz.ProcessIVYZ3A7FRequest,
|
||||
"IVYZ9D2E": ivyz.ProcessIVYZ9D2ERequest,
|
||||
"IVYZ81NC": ivyz.ProcessIVYZ81NCRequest,
|
||||
"IVYZ2MN6": ivyz.ProcessIVYZ2MN6Request,
|
||||
"IVYZ6G7H": ivyz.ProcessIVYZ6G7HRequest,
|
||||
"IVYZ8I9J": ivyz.ProcessIVYZ8I9JRequest,
|
||||
"IVYZ9K2L": ivyz.ProcessIVYZ9K2LRequest,
|
||||
"IVYZ2C1P": ivyz.ProcessIVYZ2C1PRequest,
|
||||
"IVYZP2Q6": ivyz.ProcessIVYZP2Q6Request,
|
||||
"IVYZ2B2T": ivyz.ProcessIVYZ2B2TRequest, //能力资质核验(学历)
|
||||
"IVYZ5A9O": ivyz.ProcessIVYZ5A9ORequest, //全国⾃然⼈⻛险评估评分模型
|
||||
"IVYZ6M8P": ivyz.ProcessIVYZ6M8PRequest, //职业资格证书
|
||||
"IVYZ9H2M": ivyz.ProcessIVYZ9H2MRequest, //极光个人婚姻查询(V2版)
|
||||
"IVYZZQT3": ivyz.ProcessIVYZZQT3Request, //人脸比对V3
|
||||
"IVYZBPQ2": ivyz.ProcessIVYZBPQ2Request, //人脸比对V2
|
||||
"IVYZSFEL": ivyz.ProcessIVYZSFELRequest, //全国自然人人像三要素核验_V1
|
||||
"IVYZ0S0D": ivyz.ProcessIVYZ0S0DRequest, //劳动仲裁信息查询(个人版)
|
||||
"IVYZ1J7H": ivyz.ProcessIVYZ1J7HRequest, //行驶证核查v2
|
||||
"IVYZ9K7F": ivyz.ProcessIVYZ9K7FRequest, //身份证实名认证即时版
|
||||
"IVYZA1B3": ivyz.ProcessIVYZA1B3Request, //公安三要素人脸识别
|
||||
"IVYZFIC1": ivyz.ProcessIVYZFIC1Request, //人脸身份证比对(数脉)
|
||||
"IVYZN2P8": ivyz.ProcessIVYZN2P8Request, //身份证实名认证政务版
|
||||
"IVYZX5QZ": ivyz.ProcessIVYZX5QZRequest, //活体检测
|
||||
"IVYZX5Q2": ivyz.ProcessIVYZX5Q2Request, //活体识别步骤二
|
||||
"IVYZOCR1": ivyz.ProcessIVYZOCR1Request, //身份证OCR
|
||||
"IVYZOCR2": ivyz.ProcessIVYZOCR2Request, //身份证OCR2数卖
|
||||
"IVYZ18HY": ivyz.ProcessIVYZ18HYRequest, //婚姻状况核验V2(单人)
|
||||
"IVYZ28HY": ivyz.ProcessIVYZ28HYRequest, //婚姻状况核验(单人)
|
||||
"IVYZ38SR": ivyz.ProcessIVYZ38SRRequest, //婚姻状态核验(双人)
|
||||
"IVYZ48SR": ivyz.ProcessIVYZ48SRRequest, //婚姻状态核验V2(双人)
|
||||
"IVYZ5E22": ivyz.ProcessIVYZ5E22Request, //双人婚姻评估查询zhicha版本
|
||||
|
||||
// COMB系列处理器 - 只注册有自定义逻辑的组合包
|
||||
"COMB86PM": comb.ProcessCOMB86PMRequest, // 有自定义逻辑:重命名ApiCode
|
||||
"COMBHZY2": comb.ProcessCOMBHZY2Request, // 自定义处理:生成合规报告
|
||||
"COMBWD01": comb.ProcessCOMBWD01Request, // 自定义处理:将返回结构从数组改为对象
|
||||
|
||||
// QCXG系列处理器
|
||||
"QCXG7A2B": qcxg.ProcessQCXG7A2BRequest,
|
||||
"QCXG9P1C": qcxg.ProcessQCXG9P1CRequest,
|
||||
"QCXG8A3D": qcxg.ProcessQCXG8A3DRequest,
|
||||
"QCXG6B4E": qcxg.ProcessQCXG6B4ERequest,
|
||||
"QCXG4896": qcxg.ProcessQCXG4896Request,
|
||||
"QCXG5F3A": qcxg.ProcessQCXG5F3ARequest, // 极光个人车辆查询
|
||||
"QCXG4D2E": qcxg.ProcessQCXG4D2ERequest, // 极光名下车辆数量查询
|
||||
"QCXGJJ2A": qcxg.ProcessQCXGJJ2ARequest, // vin码查车辆信息(一对多)
|
||||
"QCXGGJ3A": qcxg.ProcessQCXGGJ3ARequest, // 车辆vin码查询号牌
|
||||
"QCXGYTS2": qcxg.ProcessQCXGYTS2Request, // 车辆二要素核验v2
|
||||
"QCXGP00W": qcxg.ProcessQCXGP00WRequest, // 车辆出险详版查询
|
||||
"QCXGGB2Q": qcxg.ProcessQCXGGB2QRequest, // 车辆二要素核验V1
|
||||
"QCXG4I1Z": qcxg.ProcessQCXG4I1ZRequest, // 车辆过户详版查询
|
||||
"QCXG1H7Y": qcxg.ProcessQCXG1H7YRequest, // 车辆过户简版查询
|
||||
"QCXG3Z3L": qcxg.ProcessQCXG3Z3LRequest, // 车辆维保详细版查询
|
||||
"QCXG3Y6B": qcxg.ProcessQCXG3Y6BRequest, // 车辆维保简版查询
|
||||
"QCXG2T6S": qcxg.ProcessQCXG2T6SRequest, // 车辆里程记录(品牌查询)
|
||||
"QCXG1U4U": qcxg.ProcessQCXG1U4URequest, //
|
||||
"QCXG9F5C": qcxg.ProcessQCXG9F5CERequest, //疑似营运车辆注册平台数 10386
|
||||
"QCXG3B8Z": qcxg.ProcessQCXG3B8ZRequest, //疑似运营车辆查询(月度里程)10268
|
||||
"QCXGP1W3": qcxg.ProcessQCXGP1W3Request, //疑似运营车辆查询(季度里程)10269
|
||||
"QCXGM7R9": qcxg.ProcessQCXGM7R9Request, //疑似运营车辆查询(半年度里程)10270
|
||||
"QCXGU2K4": qcxg.ProcessQCXGU2K4Request, //疑似运营车辆查询(年度里程)10271
|
||||
"QCXG5U0Z": qcxg.ProcessQCXG5U0ZRequest, // 车辆静态信息查询 10479
|
||||
"QCXGY7F2": qcxg.ProcessQCXGY7F2Request, // 二手车VIN估值 10443
|
||||
"QCXG3M7Z": qcxg.ProcessQCXG3M7ZRequest, //人车关系核验(ETC)10093 月更
|
||||
|
||||
// DWBG系列处理器 - 多维报告
|
||||
"DWBG6A2C": dwbg.ProcessDWBG6A2CRequest,
|
||||
"DWBG8B4D": dwbg.ProcessDWBG8B4DRequest,
|
||||
"DWBG7F3A": dwbg.ProcessDWBG7F3ARequest,
|
||||
"DWBG5SAM": dwbg.ProcessDWBG5SAMRequest,
|
||||
|
||||
// FLXG系列处理器 - 风险管控 (包含原FXHY功能)
|
||||
"FLXG8B4D": flxg.ProcessFLXG8B4DRequest,
|
||||
|
||||
// TEST系列处理器 - 测试用处理器
|
||||
"TEST001": test.ProcessTestRequest,
|
||||
"TEST002": test.ProcessTestErrorRequest,
|
||||
"TEST003": test.ProcessTestTimeoutRequest,
|
||||
|
||||
// PDFG系列处理器 - PDF生成
|
||||
"PDFG01GZ": pdfg.ProcessPDFG01GZRequest,
|
||||
}
|
||||
|
||||
// 批量注册到组合包服务
|
||||
for apiCode, processor := range processorMap {
|
||||
combService.RegisterProcessor(apiCode, processor)
|
||||
}
|
||||
|
||||
// 同时设置全局处理器映射
|
||||
RequestProcessors = processorMap
|
||||
}
|
||||
|
||||
// 注册API处理器 - 现在通过registerAllProcessors统一管理
|
||||
var RequestProcessors map[string]processors.ProcessorFunc
|
||||
|
||||
// PreprocessRequestApi 调用指定的请求处理函数
|
||||
func (a *ApiRequestService) PreprocessRequestApi(ctx context.Context, apiCode string, params []byte, options *commands.ApiCallOptions, callContext *processors.CallContext) ([]byte, error) {
|
||||
// 设置Options和CallContext到依赖容器
|
||||
deps := a.processorDeps.WithOptions(options).WithCallContext(callContext)
|
||||
|
||||
// 将apiCode放入context,供外部服务使用
|
||||
ctx = context.WithValue(ctx, "api_code", apiCode)
|
||||
// 将config放入context,供处理器使用
|
||||
ctx = context.WithValue(ctx, "config", a.config)
|
||||
|
||||
// 1. 优先查找已注册的自定义处理器
|
||||
if processor, exists := RequestProcessors[apiCode]; exists {
|
||||
return processor(ctx, params, deps)
|
||||
}
|
||||
|
||||
// 2. 检查是否为组合包(COMB开头),使用通用组合包处理器
|
||||
if len(apiCode) >= 4 && apiCode[:4] == "COMB" {
|
||||
return a.processGenericCombRequest(ctx, apiCode, params, deps)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%s: 未找到处理器: %s", ErrSystem, apiCode)
|
||||
}
|
||||
|
||||
// processGenericCombRequest 通用组合包处理器
|
||||
func (a *ApiRequestService) processGenericCombRequest(ctx context.Context, apiCode string, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
// 调用组合包服务处理请求
|
||||
// 这里不需要验证参数,因为组合包的参数验证由各个子处理器负责
|
||||
combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, apiCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 直接返回组合结果,无任何自定义处理
|
||||
return json.Marshal(combinedResult)
|
||||
}
|
||||
135
internal/domains/api/services/api_user_aggregate_service.go
Normal file
135
internal/domains/api/services/api_user_aggregate_service.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
"hyapi-server/internal/config"
|
||||
"hyapi-server/internal/domains/api/entities"
|
||||
repo "hyapi-server/internal/domains/api/repositories"
|
||||
)
|
||||
|
||||
type ApiUserAggregateService interface {
|
||||
CreateApiUser(ctx context.Context, apiUserId string) error
|
||||
UpdateWhiteList(ctx context.Context, apiUserId string, whiteList []string) error
|
||||
AddToWhiteList(ctx context.Context, apiUserId string, entry string, remark string) error
|
||||
RemoveFromWhiteList(ctx context.Context, apiUserId string, entry string) error
|
||||
FreezeApiUser(ctx context.Context, apiUserId string) error
|
||||
UnfreezeApiUser(ctx context.Context, apiUserId string) error
|
||||
LoadApiUserByUserId(ctx context.Context, apiUserId string) (*entities.ApiUser, error)
|
||||
LoadApiUserByAccessId(ctx context.Context, accessId string) (*entities.ApiUser, error)
|
||||
SaveApiUser(ctx context.Context, apiUser *entities.ApiUser) error
|
||||
}
|
||||
|
||||
type ApiUserAggregateServiceImpl struct {
|
||||
repo repo.ApiUserRepository
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
func NewApiUserAggregateService(repo repo.ApiUserRepository, cfg *config.Config) ApiUserAggregateService {
|
||||
return &ApiUserAggregateServiceImpl{repo: repo, cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) CreateApiUser(ctx context.Context, apiUserId string) error {
|
||||
apiUser, err := entities.NewApiUser(apiUserId, s.cfg.Wallet.BalanceAlert.DefaultEnabled, s.cfg.Wallet.BalanceAlert.DefaultThreshold)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := apiUser.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.repo.Create(ctx, apiUser)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) UpdateWhiteList(ctx context.Context, apiUserId string, whiteList []string) error {
|
||||
apiUser, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 将字符串数组转换为WhiteListItem数组
|
||||
items := make([]entities.WhiteListItem, 0, len(whiteList))
|
||||
now := time.Now()
|
||||
for _, ip := range whiteList {
|
||||
items = append(items, entities.WhiteListItem{
|
||||
IPAddress: ip,
|
||||
AddedAt: now, // 批量更新时使用当前时间
|
||||
})
|
||||
}
|
||||
apiUser.UpdateWhiteList(items) // UpdateWhiteList 会转换为 WhiteList 类型
|
||||
return s.repo.Update(ctx, apiUser)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) AddToWhiteList(ctx context.Context, apiUserId string, entry string, remark string) error {
|
||||
apiUser, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = apiUser.AddToWhiteList(entry, remark)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.repo.Update(ctx, apiUser)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) RemoveFromWhiteList(ctx context.Context, apiUserId string, entry string) error {
|
||||
apiUser, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = apiUser.RemoveFromWhiteList(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.repo.Update(ctx, apiUser)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) FreezeApiUser(ctx context.Context, apiUserId string) error {
|
||||
apiUser, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiUser.Freeze()
|
||||
return s.repo.Update(ctx, apiUser)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) UnfreezeApiUser(ctx context.Context, apiUserId string) error {
|
||||
apiUser, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiUser.Unfreeze()
|
||||
return s.repo.Update(ctx, apiUser)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) LoadApiUserByAccessId(ctx context.Context, accessId string) (*entities.ApiUser, error) {
|
||||
return s.repo.FindByAccessId(ctx, accessId)
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) LoadApiUserByUserId(ctx context.Context, apiUserId string) (*entities.ApiUser, error) {
|
||||
apiUser, err := s.repo.FindByUserId(ctx, apiUserId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 确保WhiteList不为nil
|
||||
if apiUser.WhiteList == nil {
|
||||
apiUser.WhiteList = entities.WhiteList{}
|
||||
}
|
||||
|
||||
return apiUser, nil
|
||||
}
|
||||
|
||||
func (s *ApiUserAggregateServiceImpl) SaveApiUser(ctx context.Context, apiUser *entities.ApiUser) error {
|
||||
exists, err := s.repo.FindByUserId(ctx, apiUser.UserId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists != nil {
|
||||
// 确保WhiteList不为nil
|
||||
if apiUser.WhiteList == nil {
|
||||
apiUser.WhiteList = []entities.WhiteListItem{}
|
||||
}
|
||||
return s.repo.Update(ctx, apiUser)
|
||||
} else {
|
||||
return s.repo.Create(ctx, apiUser)
|
||||
}
|
||||
}
|
||||
804
internal/domains/api/services/form_config_service.go
Normal file
804
internal/domains/api/services/form_config_service.go
Normal file
@@ -0,0 +1,804 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"strings"
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
product_services "hyapi-server/internal/domains/product/services"
|
||||
)
|
||||
|
||||
// FormField 表单字段配置
|
||||
type FormField struct {
|
||||
Name string `json:"name"`
|
||||
Label string `json:"label"`
|
||||
Type string `json:"type"`
|
||||
Required bool `json:"required"`
|
||||
Validation string `json:"validation"`
|
||||
Description string `json:"description"`
|
||||
Example string `json:"example"`
|
||||
Placeholder string `json:"placeholder"`
|
||||
}
|
||||
|
||||
// FormConfig 表单配置
|
||||
type FormConfig struct {
|
||||
ApiCode string `json:"api_code"`
|
||||
Fields []FormField `json:"fields"`
|
||||
}
|
||||
|
||||
// FormConfigService 表单配置服务接口
|
||||
type FormConfigService interface {
|
||||
GetFormConfig(ctx context.Context, apiCode string) (*FormConfig, error)
|
||||
}
|
||||
|
||||
// FormConfigServiceImpl 表单配置服务实现
|
||||
type FormConfigServiceImpl struct {
|
||||
productManagementService *product_services.ProductManagementService
|
||||
}
|
||||
|
||||
// NewFormConfigService 创建表单配置服务
|
||||
func NewFormConfigService(productManagementService *product_services.ProductManagementService) FormConfigService {
|
||||
return &FormConfigServiceImpl{
|
||||
productManagementService: productManagementService,
|
||||
}
|
||||
}
|
||||
|
||||
// NewFormConfigServiceWithoutDependencies 创建表单配置服务(不注入依赖,用于测试)
|
||||
func NewFormConfigServiceWithoutDependencies() FormConfigService {
|
||||
return &FormConfigServiceImpl{
|
||||
productManagementService: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// GetFormConfig 获取指定API的表单配置
|
||||
func (s *FormConfigServiceImpl) GetFormConfig(ctx context.Context, apiCode string) (*FormConfig, error) {
|
||||
// 根据API代码获取对应的DTO结构体
|
||||
dtoStruct, err := s.getDTOStruct(ctx, apiCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if dtoStruct == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 通过反射解析结构体字段
|
||||
fields := s.parseDTOFields(dtoStruct)
|
||||
|
||||
config := &FormConfig{
|
||||
ApiCode: apiCode,
|
||||
Fields: fields,
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// getDTOStruct 根据API代码获取对应的DTO结构体
|
||||
func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string) (interface{}, error) {
|
||||
// 建立API代码到DTO结构体的映射
|
||||
dtoMap := map[string]interface{}{
|
||||
"IVYZ9363": &dto.IVYZ9363Req{},
|
||||
"IVYZ385E": &dto.IVYZ385EReq{},
|
||||
"IVYZ5733": &dto.IVYZ5733Req{},
|
||||
"FLXG3D56": &dto.FLXG3D56Req{},
|
||||
"FLXG75FE": &dto.FLXG75FEReq{},
|
||||
"FLXG0V3B": &dto.FLXG0V3BReq{},
|
||||
"FLXG0V4B": &dto.FLXG0V4BReq{},
|
||||
"FLXG54F5": &dto.FLXG54F5Req{},
|
||||
"FLXG162A": &dto.FLXG162AReq{},
|
||||
"FLXG0687": &dto.FLXG0687Req{},
|
||||
"FLXGBC21": &dto.FLXGBC21Req{},
|
||||
"FLXG970F": &dto.FLXG970FReq{},
|
||||
"FLXG5876": &dto.FLXG5876Req{},
|
||||
"FLXG9687": &dto.FLXG9687Req{},
|
||||
"FLXGC9D1": &dto.FLXGC9D1Req{},
|
||||
"FLXGCA3D": &dto.FLXGCA3DReq{},
|
||||
"FLXGDEC7": &dto.FLXGDEC7Req{},
|
||||
"JRZQ0A03": &dto.JRZQ0A03Req{},
|
||||
"JRZQ4AA8": &dto.JRZQ4AA8Req{},
|
||||
"JRZQ8203": &dto.JRZQ8203Req{},
|
||||
"JRZQDCBE": &dto.JRZQDCBEReq{},
|
||||
"QYGL2ACD": &dto.QYGL2ACDReq{},
|
||||
"QYGL6F2D": &dto.QYGL6F2DReq{},
|
||||
"QYGL45BD": &dto.QYGL45BDReq{},
|
||||
"QYGL8261": &dto.QYGL8261Req{},
|
||||
"QYGL8271": &dto.QYGL8271Req{},
|
||||
"QYGLB4C0": &dto.QYGLB4C0Req{},
|
||||
"QYGL23T7": &dto.QYGL23T7Req{},
|
||||
"QYGL5A3C": &dto.QYGL5A3CReq{},
|
||||
"QYGL8B4D": &dto.QYGL8B4DReq{},
|
||||
"QYGL9E2F": &dto.QYGL9E2FReq{},
|
||||
"QYGL7C1A": &dto.QYGL7C1AReq{},
|
||||
"QYGL3F8E": &dto.QYGL3F8EReq{},
|
||||
"YYSY4B37": &dto.YYSY4B37Req{},
|
||||
"YYSY4B21": &dto.YYSY4B21Req{},
|
||||
"YYSY6F2E": &dto.YYSY6F2EReq{},
|
||||
"YYSY09CD": &dto.YYSY09CDReq{},
|
||||
"IVYZ0B03": &dto.IVYZ0B03Req{},
|
||||
"YYSYBE08": &dto.YYSYBE08Req{},
|
||||
"YYSYBE08TEST": &dto.YYSYBE08Req{},
|
||||
"YYSYD50F": &dto.YYSYD50FReq{},
|
||||
"YYSYF7DB": &dto.YYSYF7DBReq{},
|
||||
"IVYZ9A2B": &dto.IVYZ9A2BReq{},
|
||||
"IVYZ7F2A": &dto.IVYZ7F2AReq{},
|
||||
"IVYZ4E8B": &dto.IVYZ4E8BReq{},
|
||||
"IVYZ1C9D": &dto.IVYZ1C9DReq{},
|
||||
"IVYZGZ08": &dto.IVYZGZ08Req{},
|
||||
"FLXG8A3F": &dto.FLXG8A3FReq{},
|
||||
"FLXG5B2E": &dto.FLXG5B2EReq{},
|
||||
"COMB298Y": &dto.COMB298YReq{},
|
||||
"COMB86PM": &dto.COMB86PMReq{},
|
||||
"QCXG7A2B": &dto.QCXG7A2BReq{},
|
||||
"COMENT01": &dto.COMENT01Req{},
|
||||
"JRZQ09J8": &dto.JRZQ09J8Req{},
|
||||
"FLXGDEA8": &dto.FLXGDEA8Req{},
|
||||
"FLXGDEA9": &dto.FLXGDEA9Req{},
|
||||
"JRZQ1D09": &dto.JRZQ1D09Req{},
|
||||
"IVYZ2A8B": &dto.IVYZ2A8BReq{},
|
||||
"IVYZ7C9D": &dto.IVYZ7C9DReq{},
|
||||
"IVYZ5E3F": &dto.IVYZ5E3FReq{},
|
||||
"YYSY4F2E": &dto.YYSY4F2EReq{},
|
||||
"YYSY8B1C": &dto.YYSY8B1CReq{},
|
||||
"YYSY6D9A": &dto.YYSY6D9AReq{},
|
||||
"YYSY3E7F": &dto.YYSY3E7FReq{},
|
||||
"FLXG5A3B": &dto.FLXG5A3BReq{},
|
||||
"FLXG9C1D": &dto.FLXG9C1DReq{},
|
||||
"FLXG2E8F": &dto.FLXG2E8FReq{},
|
||||
"JRZQ3C7B": &dto.JRZQ3C7BReq{},
|
||||
"JRZQ8A2D": &dto.JRZQ8A2DReq{},
|
||||
"JRZQ5E9F": &dto.JRZQ5E9FReq{},
|
||||
"JRZQ4B6C": &dto.JRZQ4B6CReq{},
|
||||
"JRZQ7F1A": &dto.JRZQ7F1AReq{},
|
||||
"DWBG6A2C": &dto.DWBG6A2CReq{},
|
||||
"DWBG8B4D": &dto.DWBG8B4DReq{},
|
||||
"FLXG8B4D": &dto.FLXG8B4DReq{},
|
||||
"IVYZ81NC": &dto.IVYZ81NCReq{},
|
||||
"IVYZ2MN6": &dto.IVYZ2MN6Req{},
|
||||
"IVYZ7F3A": &dto.IVYZ7F3AReq{},
|
||||
"IVYZ3P9M": &dto.IVYZ3P9MReq{},
|
||||
"IVYZ3A7F": &dto.IVYZ3A7FReq{},
|
||||
"IVYZ9D2E": &dto.IVYZ9D2EReq{},
|
||||
"IVYZ9K2L": &dto.IVYZ9K2LReq{},
|
||||
"DWBG7F3A": &dto.DWBG7F3AReq{},
|
||||
"YYSY8F3A": &dto.YYSY8F3AReq{},
|
||||
"QCXG9P1C": &dto.QCXG9P1CReq{},
|
||||
"JRZQ9E2A": &dto.JRZQ9E2AReq{},
|
||||
"YYSY9A1B": &dto.YYSY9A1BReq{},
|
||||
"YYSY8C2D": &dto.YYSY8C2DReq{},
|
||||
"YYSY7D3E": &dto.YYSY7D3EReq{},
|
||||
"YYSY9E4A": &dto.YYSY9E4AReq{},
|
||||
"JRZQ6F2A": &dto.JRZQ6F2AReq{},
|
||||
"JRZQ8B3C": &dto.JRZQ8B3CReq{},
|
||||
"JRZQ9D4E": &dto.JRZQ9D4EReq{},
|
||||
"FLXG7E8F": &dto.FLXG7E8FReq{},
|
||||
"QYGL5F6A": &dto.QYGL5F6AReq{},
|
||||
"IVYZ6G7H": &dto.IVYZ6G7HReq{},
|
||||
"IVYZ8I9J": &dto.IVYZ8I9JReq{},
|
||||
"JRZQ0L85": &dto.JRZQ0L85Req{},
|
||||
"COMBHZY2": &dto.COMBHZY2Req{}, //
|
||||
"QCXG8A3D": &dto.QCXG8A3DReq{},
|
||||
"QCXG6B4E": &dto.QCXG6B4EReq{},
|
||||
"QYGL2B5C": &dto.QYGL2B5CReq{},
|
||||
"QYGLJ1U9": &dto.QYGLJ1U9Req{},
|
||||
"JRZQ2F8A": &dto.JRZQ2F8AReq{},
|
||||
"JRZQ1E7B": &dto.JRZQ1E7BReq{},
|
||||
"JRZQ3C9R": &dto.JRZQ3C9RReq{},
|
||||
"IVYZ2C1P": &dto.IVYZ2C1PReq{},
|
||||
"YYSY9F1B": &dto.YYSY9F1BReq{},
|
||||
"YYSY6F2B": &dto.YYSY6F2BReq{},
|
||||
"QYGL6S1B": &dto.QYGL6S1BReq{},
|
||||
"JRZQ0B6Y": &dto.JRZQ0B6YReq{},
|
||||
"JRZQ9A1W": &dto.JRZQ9A1WReq{},
|
||||
"JRZQ8F7C": &dto.JRZQ8F7CReq{}, //综合多头
|
||||
"FLXGK5D2": &dto.FLXGK5D2Req{},
|
||||
"FLXG3A9B": &dto.FLXG3A9BReq{},
|
||||
"IVYZP2Q6": &dto.IVYZP2Q6Req{},
|
||||
"JRZQ1W4X": &dto.JRZQ1W4XReq{}, //全景档案
|
||||
"QYGL2S0W": &dto.QYGL2S0WReq{}, //失信被执行企业个人查询
|
||||
"QYGL9T1Q": &dto.QYGL9T1QReq{}, //全国企业借贷意向验证查询_V1
|
||||
"QYGL5A9T": &dto.QYGL5A9TReq{}, //全国企业各类工商风险统计数量查询
|
||||
"JRZQ3P01": &dto.JRZQ3P01Req{}, //海宇风控决策
|
||||
"JRZQ3AG6": &dto.JRZQ3AG6Req{}, //轻松查公积
|
||||
"IVYZ2B2T": &dto.IVYZ2B2TReq{}, //能力资质核验(学历)
|
||||
"IVYZ5A9O": &dto.IVYZ5A9OReq{}, //全国⾃然⼈⻛险评估评分模型
|
||||
"IVYZ6M8P": &dto.IVYZ6M8PReq{}, //职业资格证书
|
||||
"IVYZ9H2M": &dto.IVYZ9H2MReq{}, //极光个人婚姻查询(V2版)
|
||||
"QYGL5CMP": &dto.QYGL5CMPReq{}, //企业五要素验证
|
||||
"QCXG4896": &dto.QCXG4896Req{}, //网约车风险查询
|
||||
"IVYZZQT3": &dto.IVYZZQT3Req{}, //人脸比对V3
|
||||
"IVYZBPQ2": &dto.IVYZBPQ2Req{}, //人脸比对V2
|
||||
"IVYZSFEL": &dto.IVYZSFELReq{}, //全国自然人人像三要素核验_V1
|
||||
"QYGL66SL": &dto.QYGL66SLReq{}, //全国企业司法模型服务查询_V1
|
||||
"QCXG5F3A": &dto.QCXG5F3AReq{}, //极光个人车辆查询
|
||||
"QCXG4D2E": &dto.QCXG4D2EReq{}, //极光名下车辆数量查询
|
||||
"QYGLP0HT": &dto.QYGLP0HTReq{}, //股权穿透
|
||||
"QYGL2NAO": &dto.QYGL2naoReq{}, //股权变更
|
||||
"QYGLNIO8": &dto.QYGLNIO8Req{}, //企业基本信息
|
||||
"QYGL4B2E": &dto.QYGL5A3CReq{}, //税收违法
|
||||
"QYGL7D9A": &dto.QYGL5A3CReq{}, //欠税公告
|
||||
"IVYZ0S0D": &dto.IVYZ0S0DReq{}, //劳动仲裁信息查询(个人版)
|
||||
"IVYZ1J7H": &dto.IVYZ1J7HReq{}, //行驶证核查v2
|
||||
"QCXGJJ2A": &dto.QCXGJJ2AReq{}, //vin码查车辆信息(一对多)
|
||||
"QCXGGJ3A": &dto.QCXGGJ3AReq{}, //车辆vin码查询号牌
|
||||
"QCXGYTS2": &dto.QCXGYTS2Req{}, //车辆二要素核验v2
|
||||
"QCXGP00W": &dto.QCXGP00WReq{}, //车辆出险详版查询
|
||||
"QCXGGB2Q": &dto.QCXGGB2QReq{}, //车辆二要素核验V1
|
||||
"QCXG4I1Z": &dto.QCXG4I1ZReq{}, //车辆过户详版查询
|
||||
"QCXG1H7Y": &dto.QCXG1H7YReq{}, //车辆过户简版查询
|
||||
"QCXG3Z3L": &dto.QCXG3Z3LReq{}, //车辆维保详细版查询
|
||||
"QCXG3Y6B": &dto.QCXG1U4UReq{}, //车辆维保简版查询
|
||||
"QCXG2T6S": &dto.QCXG2T6SReq{}, //车辆里程记录(品牌查询)
|
||||
"QCXG1U4U": &dto.QCXG1U4UReq{}, //车辆里程记录(混合查询)
|
||||
"JRZQO6L7": &dto.JRZQO6L7Req{}, //全国自然人经济特征评分模型v3 简版
|
||||
"JRZQO7L1": &dto.JRZQO7L1Req{}, //全国自然人经济特征评分模型v4 详版
|
||||
"JRZQS7G0": &dto.JRZQS7G0Req{}, //社保综合评分V1
|
||||
"IVYZ9K7F": &dto.IVYZ9K7FReq{}, //身份证实名认证即时版
|
||||
"YYSY3M8S": &dto.YYSY3M8SReq{}, //运营商二要素查询
|
||||
"YYSYC4R9": &dto.YYSYC4R9Req{}, //运营商三要素详版查询
|
||||
"YYSYH6D2": &dto.YYSYH6D2Req{}, //运营商三要素简版政务版查询
|
||||
"YYSYP0T4": &dto.YYSYP0T4Req{}, //在网时长查询
|
||||
"YYSYE7V5": &dto.YYSYE7V5Req{}, //手机在网状态查询
|
||||
"YYSYS9W1": &dto.YYSYS9W1Req{}, //手机携号转网查询
|
||||
"YYSYK8R3": &dto.YYSYK8R3Req{}, //手机空号检测查询
|
||||
"YYSYF2T7": &dto.YYSYF2T7Req{}, //手机二次放号检测查询
|
||||
"IVYZA1B3": &dto.IVYZA1B3Req{}, //公安三要素人脸识别
|
||||
"IVYZFIC1": &dto.IVYZFIC1Req{}, //人脸身份证比对(数脉)
|
||||
"IVYZX5QZ": &dto.IVYZX5QZReq{}, //活体识别
|
||||
"IVYZN2P8": &dto.IVYZ9K7FReq{}, //身份证实名认证政务版
|
||||
"YYSYH6F3": &dto.YYSYH6F3Req{}, //运营商三要素简版即时版查询
|
||||
"IVYZX5Q2": &dto.IVYZX5Q2Req{}, //活体识别步骤二
|
||||
"PDFG01GZ": &dto.PDFG01GZReq{}, //
|
||||
"QYGL5S1I": &dto.QYGL5S1IReq{}, //企业司法涉诉V2
|
||||
"JRZQACAB": &dto.JRZQACABReq{}, //银行卡四要素
|
||||
"QCXG9F5C": &dto.QCXG9F5CReq{}, //疑似营运车辆注册平台数 10386
|
||||
"QCXG3B8Z": &dto.QCXG3B8ZReq{}, //疑似运营车辆查询(月度里程)10268
|
||||
"QCXGP1W3": &dto.QCXGP1W3Req{}, //疑似运营车辆查询(季度里程)10269
|
||||
"QCXGM7R9": &dto.QCXGM7R9Req{}, //疑似运营车辆查询(半年度里程)10270
|
||||
"QCXGU2K4": &dto.QCXGU2K4Req{}, //疑似运营车辆查询(年度里程)10271
|
||||
"QCXG5U0Z": &dto.QCXG5U0ZReq{}, //车辆静态信息查询 10479
|
||||
"QCXGY7F2": &dto.QCXGY7F2Req{}, //二手车VIN估值 10443
|
||||
"YYSYK9R4": &dto.YYSYK9R4Req{}, //全网手机三要素验证1979周更新版
|
||||
"QCXG3M7Z": &dto.QCXG3M7ZReq{}, //人车关系核验(ETC)10093 月更
|
||||
"JRZQ1P5G": &dto.JRZQ1P5GReq{}, //全国自然人借贷压力指数查询(2)
|
||||
"IVYZOCR1": &dto.IVYZOCR1Req{}, //身份证OCR
|
||||
"IVYZOCR2": &dto.IVYZOCR1Req{}, //身份证OCR2数卖
|
||||
"QYGLJ0Q1": &dto.QYGLJ0Q1Req{}, //企业股权结构全景查询
|
||||
"QYGLUY3S": &dto.QYGLUY3SReq{}, //企业全量信息核验V2 可用
|
||||
"JRZQOCRE": &dto.JRZQOCREReq{}, //银行卡OCR数卖
|
||||
"JRZQOCRY": &dto.JRZQOCRYReq{}, //银行卡OCR数据宝
|
||||
"YYSY35TA": &dto.YYSY35TAReq{}, //运营商归属地数卖
|
||||
"QYGLDJ12": &dto.QYGLDJ12Req{}, //企业年报信息核验
|
||||
"FLXGDJG3": &dto.FLXGDJG3Req{}, //董监高司法综合信息核验
|
||||
"QYGL8848": &dto.QYGLDJ12Req{}, //企业税收违法核查
|
||||
"IVYZ18HY": &dto.IVYZ18HYReq{}, //婚姻状况核验V2(单人)
|
||||
"IVYZ28HY": &dto.IVYZ28HYReq{}, //婚姻状况核验(单人)
|
||||
"IVYZ38SR": &dto.IVYZ38SRReq{}, //婚姻状态核验(双人)
|
||||
"IVYZ48SR": &dto.IVYZ48SRReq{}, //婚姻状态核验V2(双人)
|
||||
"IVYZ5E22": &dto.IVYZ5E22Req{}, //双人婚姻评估查询zhicha版本
|
||||
"DWBG5SAM": &dto.DWBG5SAMReq{}, //海宇指迷报告
|
||||
}
|
||||
|
||||
// 优先返回已配置的DTO
|
||||
if dto, exists := dtoMap[apiCode]; exists {
|
||||
return dto, nil
|
||||
}
|
||||
|
||||
// 检查是否为通用组合包(COMB开头且未单独配置)
|
||||
if len(apiCode) >= 4 && apiCode[:4] == "COMB" {
|
||||
// 动态从数据库获取组合包的子产品信息,并合并DTO
|
||||
return s.mergeCombPackageDTOs(ctx, apiCode, dtoMap)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// parseDTOFields 通过反射解析DTO结构体字段
|
||||
func (s *FormConfigServiceImpl) parseDTOFields(dtoStruct interface{}) []FormField {
|
||||
var fields []FormField
|
||||
|
||||
t := reflect.TypeOf(dtoStruct).Elem()
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
|
||||
// 获取JSON标签
|
||||
jsonTag := field.Tag.Get("json")
|
||||
if jsonTag == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取验证标签
|
||||
validateTag := field.Tag.Get("validate")
|
||||
|
||||
// 解析验证规则
|
||||
required := strings.Contains(validateTag, "required")
|
||||
validation := s.parseValidationRules(validateTag)
|
||||
|
||||
// 根据字段类型和验证规则生成前端字段类型
|
||||
fieldType := s.getFieldType(field.Type, validation)
|
||||
|
||||
// 生成字段标签(将下划线转换为中文)
|
||||
label := s.generateFieldLabel(jsonTag)
|
||||
|
||||
// 生成示例值
|
||||
example := s.generateExampleValue(field.Type, jsonTag)
|
||||
|
||||
// 生成占位符
|
||||
placeholder := s.generatePlaceholder(jsonTag, fieldType)
|
||||
|
||||
// 生成字段描述
|
||||
description := s.generateDescription(jsonTag, validation)
|
||||
|
||||
formField := FormField{
|
||||
Name: jsonTag,
|
||||
Label: label,
|
||||
Type: fieldType,
|
||||
Required: required,
|
||||
Validation: validation,
|
||||
Description: description,
|
||||
Example: example,
|
||||
Placeholder: placeholder,
|
||||
}
|
||||
|
||||
fields = append(fields, formField)
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// parseValidationRules 解析验证规则
|
||||
func (s *FormConfigServiceImpl) parseValidationRules(validateTag string) string {
|
||||
if validateTag == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 将验证规则转换为前端可理解的格式
|
||||
rules := strings.Split(validateTag, ",")
|
||||
var frontendRules []string
|
||||
|
||||
for _, rule := range rules {
|
||||
rule = strings.TrimSpace(rule)
|
||||
switch {
|
||||
case rule == "required":
|
||||
frontendRules = append(frontendRules, "必填")
|
||||
case strings.HasPrefix(rule, "min="):
|
||||
min := strings.TrimPrefix(rule, "min=")
|
||||
frontendRules = append(frontendRules, "最小长度"+min)
|
||||
case strings.HasPrefix(rule, "max="):
|
||||
max := strings.TrimPrefix(rule, "max=")
|
||||
frontendRules = append(frontendRules, "最大长度"+max)
|
||||
case rule == "validMobileNo":
|
||||
frontendRules = append(frontendRules, "手机号格式")
|
||||
case rule == "validIDCard":
|
||||
frontendRules = append(frontendRules, "身份证格式")
|
||||
case rule == "validName":
|
||||
frontendRules = append(frontendRules, "姓名格式")
|
||||
case rule == "validUSCI":
|
||||
frontendRules = append(frontendRules, "统一社会信用代码格式")
|
||||
case rule == "validEnterpriseName" || rule == "enterprise_name":
|
||||
frontendRules = append(frontendRules, "企业名称格式")
|
||||
case rule == "validBankCard":
|
||||
frontendRules = append(frontendRules, "银行卡号格式")
|
||||
case rule == "validDate":
|
||||
frontendRules = append(frontendRules, "日期格式")
|
||||
case rule == "validAuthDate":
|
||||
frontendRules = append(frontendRules, "授权日期格式")
|
||||
case rule == "validDateRange":
|
||||
frontendRules = append(frontendRules, "日期范围格式(YYYYMMDD-YYYYMMDD)")
|
||||
case rule == "validTimeRange":
|
||||
frontendRules = append(frontendRules, "时间范围格式")
|
||||
case rule == "validMobileType":
|
||||
frontendRules = append(frontendRules, "手机类型")
|
||||
case rule == "validUniqueID":
|
||||
frontendRules = append(frontendRules, "唯一标识格式")
|
||||
case rule == "validReturnURL":
|
||||
frontendRules = append(frontendRules, "返回链接格式")
|
||||
case rule == "validAuthorizationURL":
|
||||
frontendRules = append(frontendRules, "授权链接格式")
|
||||
case rule == "validBase64Image":
|
||||
frontendRules = append(frontendRules, "Base64图片格式(JPG、BMP、PNG)")
|
||||
case rule == "base64" || rule == "validBase64":
|
||||
frontendRules = append(frontendRules, "Base64编码格式(支持图片/PDF)")
|
||||
case strings.HasPrefix(rule, "oneof="):
|
||||
values := strings.TrimPrefix(rule, "oneof=")
|
||||
frontendRules = append(frontendRules, "可选值: "+values)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return strings.Join(frontendRules, "、")
|
||||
}
|
||||
|
||||
// getFieldType 根据字段类型和验证规则确定前端字段类型
|
||||
func (s *FormConfigServiceImpl) getFieldType(fieldType reflect.Type, validation string) string {
|
||||
switch fieldType.Kind() {
|
||||
case reflect.String:
|
||||
if strings.Contains(validation, "手机号") {
|
||||
return "tel"
|
||||
} else if strings.Contains(validation, "身份证") {
|
||||
return "text"
|
||||
} else if strings.Contains(validation, "姓名") {
|
||||
return "text"
|
||||
} else if strings.Contains(validation, "时间范围格式") {
|
||||
return "text" // time_range是HH:MM-HH:MM格式,使用文本输入
|
||||
} else if strings.Contains(validation, "授权日期格式") {
|
||||
return "text" // auth_date是YYYYMMDD-YYYYMMDD格式,使用文本输入
|
||||
} else if strings.Contains(validation, "日期范围格式") {
|
||||
return "text" // date_range 为 YYYYMMDD-YYYYMMDD,使用文本输入便于直接输入
|
||||
} else if strings.Contains(validation, "日期") {
|
||||
return "date"
|
||||
} else if strings.Contains(validation, "链接") {
|
||||
return "url"
|
||||
} else if strings.Contains(validation, "可选值") {
|
||||
return "select"
|
||||
} else if strings.Contains(validation, "Base64图片") || strings.Contains(validation, "Base64编码") || strings.Contains(validation, "base64") {
|
||||
return "textarea"
|
||||
} else if strings.Contains(validation, "图片地址") {
|
||||
return "url"
|
||||
}
|
||||
return "text"
|
||||
case reflect.Int64:
|
||||
return "number"
|
||||
case reflect.Bool:
|
||||
return "checkbox"
|
||||
default:
|
||||
return "text"
|
||||
}
|
||||
}
|
||||
|
||||
// generateFieldLabel 生成字段标签
|
||||
func (s *FormConfigServiceImpl) generateFieldLabel(jsonTag string) string {
|
||||
// 将下划线命名转换为中文标签
|
||||
labelMap := map[string]string{
|
||||
"mobile_no": "手机号码",
|
||||
"id_card": "身份证号",
|
||||
"idCard": "身份证号",
|
||||
"name": "姓名",
|
||||
"man_name": "男方姓名",
|
||||
"woman_name": "女方姓名",
|
||||
"man_id_card": "男方身份证",
|
||||
"woman_id_card": "女方身份证",
|
||||
"ent_name": "企业名称",
|
||||
"legal_person": "法人姓名",
|
||||
"ent_code": "企业代码",
|
||||
"ent_reg_no": "企业注册号",
|
||||
"auth_date": "授权日期",
|
||||
"date_range": "日期范围",
|
||||
"time_range": "时间范围",
|
||||
"authorized": "是否授权",
|
||||
"authorization_url": "授权链接",
|
||||
"unique_id": "唯一标识",
|
||||
"return_url": "返回链接",
|
||||
"mobile_type": "手机类型",
|
||||
"start_date": "开始日期",
|
||||
"years": "年数",
|
||||
"bank_card": "银行卡号",
|
||||
"user_type": "关系类型",
|
||||
"vehicle_type": "车辆类型",
|
||||
"page_num": "页码",
|
||||
"page_size": "每页数量",
|
||||
"use_scenario": "使用场景",
|
||||
"auth_authorize_file_code": "授权文件编码",
|
||||
"plate_no": "车牌号",
|
||||
"plate_type": "号牌类型",
|
||||
"vin_code": "车辆识别代号VIN码",
|
||||
"return_type": "返回类型",
|
||||
"photo_data": "入参图片base64编码",
|
||||
"owner_type": "企业主类型",
|
||||
"type": "查询类型",
|
||||
"query_reason_id": "查询原因ID",
|
||||
"flag": "层次",
|
||||
"dir": "方向",
|
||||
"min_percent": "股权穿透比例下限",
|
||||
"max_percent": "股权穿透比例上限",
|
||||
"engine_number": "发动机号码",
|
||||
"notice_model": "车辆型号",
|
||||
"vlphoto_data": "行驶证图片",
|
||||
"carplate_type": "车辆号牌类型",
|
||||
"image_url": "入参图片地址",
|
||||
"reg_url": "车辆登记证图片地址",
|
||||
"token": "token采集及获取结果时所使用的凭证,有效期2个小时,在此时效内,应用侧可以发起采集请求(重复的采集所触发的结果会被忽略)和结果查询",
|
||||
"vehicle_name": "车型名称",
|
||||
"vehicle_location": "车辆所在地",
|
||||
"first_registrationdate": "首次登记日期",
|
||||
"color": "颜色",
|
||||
"plate_color": "车牌颜色",
|
||||
"marital_type": "婚姻状况类型",
|
||||
"auth_authorize_file_base64": "PDF授权文件Base64编码(5MB以内)",
|
||||
}
|
||||
|
||||
if label, exists := labelMap[jsonTag]; exists {
|
||||
return label
|
||||
}
|
||||
|
||||
// 如果没有预定义,尝试自动转换
|
||||
return strings.ReplaceAll(jsonTag, "_", " ")
|
||||
}
|
||||
|
||||
// generateExampleValue 生成示例值
|
||||
func (s *FormConfigServiceImpl) generateExampleValue(fieldType reflect.Type, jsonTag string) string {
|
||||
exampleMap := map[string]string{
|
||||
"mobile_no": "13800138000",
|
||||
"id_card": "110101199001011234",
|
||||
"idCard": "110101199001011234",
|
||||
"name": "张三",
|
||||
"man_name": "张三",
|
||||
"woman_name": "李四",
|
||||
"ent_name": "示例企业有限公司",
|
||||
"legal_person": "王五",
|
||||
"ent_code": "91110000123456789X",
|
||||
"ent_reg_no": "110000000123456",
|
||||
"auth_date": "20240101-20241231",
|
||||
"date_range": "20240101-20241231",
|
||||
"time_range": "09:00-18:00",
|
||||
"authorized": "1",
|
||||
"years": "5",
|
||||
"bank_card": "6222021234567890123",
|
||||
"mobile_type": "移动",
|
||||
"start_date": "2024-01-01",
|
||||
"unique_id": "UNIQUE123456",
|
||||
"return_url": "https://example.com/return",
|
||||
"authorization_url": "https://example.com/auth20250101.pdf 注意:请不要使用示例链接,示例链接仅作为参考格式。必须为实际的被查询人授权具有法律效益的授权书文件链接,如访问不到或为不实授权书将追究责任。协议必须为http https",
|
||||
"user_type": "1",
|
||||
"vehicle_type": "0",
|
||||
"page_num": "1",
|
||||
"page_size": "10",
|
||||
"use_scenario": "1",
|
||||
"auth_authorize_file_code": "AUTH123456",
|
||||
"plate_no": "京A12345",
|
||||
"plate_type": "01",
|
||||
"vin_code": "LSGBF53M8DS123456",
|
||||
"return_type": "1",
|
||||
"photo_data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
|
||||
"ownerType": "1",
|
||||
"type": "per",
|
||||
"query_reason_id": "1",
|
||||
"flag": "4",
|
||||
"dir": "down",
|
||||
"min_percent": "0",
|
||||
"max_percent": "1",
|
||||
"engine_number": "1234567890",
|
||||
"notice_model": "1",
|
||||
"vlphoto_data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
|
||||
"carplate_type": "01",
|
||||
"image_url": "https://example.com/images/driving_license.jpg",
|
||||
"reg_url": "https://example.com/images/vehicle_registration.jpg",
|
||||
"token": "0fc79b80371f45e2ac1c693ef9136b24",
|
||||
"vehicle_name": "车型名称,示例:凌派 2020款 锐·混动 1.5L 锐·舒适版",
|
||||
"vehicle_location": "车辆所在地,示例:北京",
|
||||
"first_registrationdate": "初登日期,示例:2020-05",
|
||||
"color": "示例:白色",
|
||||
"plate_color": "0",
|
||||
"marital_type": "10",
|
||||
"auth_authorize_file_base64": "JVBERi0xLjQKJcTl8uXr...(示例PDF的Base64编码)",
|
||||
}
|
||||
|
||||
if example, exists := exampleMap[jsonTag]; exists {
|
||||
return example
|
||||
}
|
||||
|
||||
// 根据字段类型生成默认示例
|
||||
switch fieldType.Kind() {
|
||||
case reflect.String:
|
||||
return "示例值"
|
||||
case reflect.Int64:
|
||||
return "123"
|
||||
case reflect.Bool:
|
||||
return "true"
|
||||
default:
|
||||
return "示例值"
|
||||
}
|
||||
}
|
||||
|
||||
// generatePlaceholder 生成占位符
|
||||
func (s *FormConfigServiceImpl) generatePlaceholder(jsonTag string, fieldType string) string {
|
||||
placeholderMap := map[string]string{
|
||||
"mobile_no": "请输入11位手机号码",
|
||||
"id_card": "请输入18位身份证号码",
|
||||
"idCard": "请输入18位身份证号码",
|
||||
"name": "请输入真实姓名",
|
||||
"man_name": "请输入男方真实姓名",
|
||||
"woman_name": "请输入女方真实姓名",
|
||||
"ent_name": "请输入企业全称",
|
||||
"legal_person": "请输入法人真实姓名",
|
||||
"ent_code": "请输入统一社会信用代码",
|
||||
"ent_reg_no": "请输入企业注册号(统一社会信用代码)",
|
||||
"auth_date": "请输入授权日期范围(YYYYMMDD-YYYYMMDD)",
|
||||
"date_range": "请输入日期范围(YYYYMMDD-YYYYMMDD)",
|
||||
"time_range": "请输入时间范围(HH:MM-HH:MM)",
|
||||
"authorized": "请选择是否授权",
|
||||
"years": "请输入查询年数(0-100)",
|
||||
"bank_card": "请输入银行卡号",
|
||||
"mobile_type": "请选择手机类型",
|
||||
"start_date": "请选择开始日期",
|
||||
"unique_id": "请输入唯一标识",
|
||||
"return_url": "请输入返回链接",
|
||||
"authorization_url": "请输入授权链接",
|
||||
"user_type": "请选择关系类型",
|
||||
"vehicle_type": "请选择车辆类型",
|
||||
"page_num": "请输入页码",
|
||||
"page_size": "请输入每页数量(1-100)",
|
||||
"use_scenario": "请选择使用场景",
|
||||
"auth_authorize_file_code": "请输入授权文件编码",
|
||||
"plate_no": "请输入车牌号",
|
||||
"plate_type": "请选择号牌类型(01或02)",
|
||||
"vin_code": "请输入17位车辆识别代号VIN码",
|
||||
"return_type": "请选择返回类型",
|
||||
"photo_data": "请输入base64编码的入参图片(支持JPG、BMP、PNG格式)",
|
||||
"ownerType": "请选择企业主类型",
|
||||
"type": "请选择查询类型",
|
||||
"query_reason_id": "请选择查询原因ID",
|
||||
"flag": "请输入层次(最大4)",
|
||||
"dir": "请选择方向(up-向上,down-向下)",
|
||||
"min_percent": "请输入股权穿透比例下限(默认0)",
|
||||
"max_percent": "请输入股权穿透比例上限(默认1)",
|
||||
"engine_number": "请输入发动机号码",
|
||||
"notice_model": "请输入车辆型号",
|
||||
"vlphoto_data": "请输入行驶证图片",
|
||||
"carplate_type": "请选择车辆号牌类型(01-大型汽车 02-小型汽车 03-使馆汽车 04-领馆汽车 05-境外汽车 06-外籍汽车 07-普通摩托车 08-轻便摩托车 09-使馆摩托车 10-领馆摩托车 11-境外摩托车 12-外籍摩托车 13-低速车 14-拖拉机 15-挂车 16-教练汽车 17-教练摩托车 20-临时入境汽车 21-临时入境摩托车 22-临时行驶车 23-警用汽车 24-警用摩托 51-新能源大型车 52-新能源小型车)",
|
||||
"image_url": "请输入入参图片地址",
|
||||
"reg_url": "请输入车辆登记证图片地址",
|
||||
"token": "请输入token",
|
||||
"vehicle_name": "请输入车型名称",
|
||||
"vehicle_location": "请输入车辆所在地",
|
||||
"first_registrationdate": "请输入首次登记日期,格式:YYYY-MM",
|
||||
"color": "请输入颜色",
|
||||
"plate_color": "请输入车牌颜色",
|
||||
"marital_type": "请选择婚姻状况类型",
|
||||
"auth_authorize_file_base64": "请输入PDF文件的Base64编码字符串",
|
||||
}
|
||||
|
||||
if placeholder, exists := placeholderMap[jsonTag]; exists {
|
||||
return placeholder
|
||||
}
|
||||
|
||||
// 根据字段类型生成默认占位符
|
||||
switch fieldType {
|
||||
case "tel":
|
||||
return "请输入电话号码"
|
||||
case "date":
|
||||
return "请选择日期"
|
||||
case "url":
|
||||
return "请输入链接地址"
|
||||
case "number":
|
||||
return "请输入数字"
|
||||
default:
|
||||
return "请输入" + s.generateFieldLabel(jsonTag)
|
||||
}
|
||||
}
|
||||
|
||||
// generateDescription 生成字段描述
|
||||
func (s *FormConfigServiceImpl) generateDescription(jsonTag string, validation string) string {
|
||||
descMap := map[string]string{
|
||||
"mobile_no": "请输入11位手机号码",
|
||||
"id_card": "请输入18位身份证号码最后一位如是字母请大写",
|
||||
"idCard": "请输入18位身份证号码最后一位如是字母请大写",
|
||||
"name": "请输入真实姓名",
|
||||
"man_name": "请输入男方真实姓名",
|
||||
"woman_name": "请输入女方真实姓名",
|
||||
"ent_name": "请输入企业全称",
|
||||
"legal_person": "请输入法人真实姓名",
|
||||
"ent_code": "请输入统一社会信用代码",
|
||||
"ent_reg_no": "请输入企业注册号(统一社会信用代码)",
|
||||
"auth_date": "请输入授权日期范围,格式:YYYYMMDD-YYYYMMDD,且日期范围必须包括今天",
|
||||
"date_range": "请输入日期范围,格式:YYYYMMDD-YYYYMMDD",
|
||||
"time_range": "请输入时间范围,格式:HH:MM-HH:MM",
|
||||
"authorized": "请输入是否授权:0-未授权,1-已授权",
|
||||
"years": "请输入查询年数(0-100)",
|
||||
"bank_card": "请输入银行卡号",
|
||||
"mobile_type": "请选择手机类型",
|
||||
"start_date": "请选择开始日期",
|
||||
"unique_id": "请输入唯一标识",
|
||||
"return_url": "请输入返回链接",
|
||||
"authorization_url": "请输入授权链接",
|
||||
"user_type": "关系类型:1-ETC开户人;2-车辆所有人;3-ETC经办人(默认1-ETC开户人)",
|
||||
"vehicle_type": "车辆类型:0-客车;1-货车;2-全部(默认查全部)",
|
||||
"page_num": "请输入页码,从1开始",
|
||||
"page_size": "请输入每页数量,范围1-100",
|
||||
"use_scenario": "使用场景:1-信贷审核;2-保险评估;3-招聘背景调查;4-其他业务场景;99-其他",
|
||||
"auth_authorize_file_code": "请输入授权文件编码",
|
||||
"plate_no": "请输入车牌号",
|
||||
"plate_type": "号牌类型:01-小型汽车;02-大型汽车(可选)",
|
||||
"vin_code": "请输入17位车辆识别代号VIN码(Vehicle Identification Number)",
|
||||
"return_type": "返回类型:1-专业和学校名称数据返回编码形式(默认);2-专业和学校名称数据返回中文名称",
|
||||
"photo_data": "入参图片:base64编码的图片数据,仅支持JPG、BMP、PNG三种格式",
|
||||
"owner_type": "企业主类型编码:1-法定代表人;2-主要人员;3-自然人股东;4-法定代表人及自然人股东;5-其他",
|
||||
"type": "查询类型:per-人员,ent-企业 ",
|
||||
"query_reason_id": "查询原因ID:1-授信审批;2-贷中管理;3-贷后管理;4-异议处理;5-担保查询;6-租赁资质审查;7-融资租赁审批;8-借贷撮合查询;9-保险审批;10-资质审核;11-风控审核;12-企业背调",
|
||||
"flag": "层次,最大4",
|
||||
"dir": "方向:up-向上穿透,down-向下穿透",
|
||||
"min_percent": "股权穿透比例下限(大于等于),默认为0,支持小数点后两位(以小数指代百分比)",
|
||||
"max_percent": "股权穿透比例上限(小于等于),默认为1,支持小数点后两位(以小数指代百分比)",
|
||||
"engine_number": "发动机号码",
|
||||
"notice_model": "车辆型号",
|
||||
"vlphoto_data": "行驶证图片:base64编码的图片数据,仅支持JPG、BMP、PNG三种格式",
|
||||
"carplate_type": "车辆号牌类型:01-大型汽车;02-小型汽车;03-使馆汽车;04-领馆汽车;05-境外汽车;06-外籍汽车;07-普通摩托车;08-轻便摩托车;09-使馆摩托车;10-领馆摩托车;11-境外摩托车;12-外籍摩托车;13-低速车;14-拖拉机;15-挂车;16-教练汽车;17-教练摩托车;20-临时入境汽车;21-临时入境摩托车;22-临时行驶车;23-警用汽车;24-警用摩托;51-新能源大型车;52-新能源小型车",
|
||||
"image_url": "入参图片url地址",
|
||||
"reg_url": "车辆登记证图片地址(非必填):请提供车辆登记证的图片URL地址",
|
||||
"token": "token采集及获取结果时所使用的凭证,有效期2个小时,在此时效内,应用侧可以发起采集请求(重复的采集所触发的结果会被忽略)和结果查询",
|
||||
"vehicle_name": "车型名称,示例:凌派 2020款 锐·混动 1.5L 锐·舒适版",
|
||||
"vehicle_location": "车辆所在地",
|
||||
"first_registrationdate": "首次登记日期,格式:YYYY-MM",
|
||||
"color": "颜色",
|
||||
"plate_color": "车牌颜色",
|
||||
"marital_type": "婚姻状况类型:10-未登记(无登记记录),20-已婚,30-丧偶,40-离异",
|
||||
"auth_authorize_file_base64": "请输入PDF文件的Base64编码字符串",
|
||||
}
|
||||
|
||||
if desc, exists := descMap[jsonTag]; exists {
|
||||
return desc
|
||||
}
|
||||
|
||||
return "请输入" + s.generateFieldLabel(jsonTag)
|
||||
}
|
||||
|
||||
// mergeCombPackageDTOs 动态合并组合包的子产品DTO结构体
|
||||
func (s *FormConfigServiceImpl) mergeCombPackageDTOs(ctx context.Context, apiCode string, dtoMap map[string]interface{}) (interface{}, error) {
|
||||
// 如果productManagementService为nil(测试环境),返回空结构体
|
||||
if s.productManagementService == nil {
|
||||
return &struct{}{}, nil
|
||||
}
|
||||
|
||||
// 1. 从数据库获取组合包产品信息
|
||||
packageProduct, err := s.productManagementService.GetProductByCode(ctx, apiCode)
|
||||
if err != nil {
|
||||
// 如果获取失败,返回空结构体
|
||||
return &struct{}{}, nil
|
||||
}
|
||||
|
||||
// 2. 检查是否为组合包
|
||||
if !packageProduct.IsPackage {
|
||||
return &struct{}{}, nil
|
||||
}
|
||||
|
||||
// 3. 获取组合包的所有子产品
|
||||
packageItems, err := s.productManagementService.GetPackageItems(ctx, packageProduct.ID)
|
||||
if err != nil || len(packageItems) == 0 {
|
||||
return &struct{}{}, nil
|
||||
}
|
||||
|
||||
// 4. 收集所有子产品的DTO字段并去重
|
||||
// 使用map记录已存在的字段,key为json tag
|
||||
fieldMap := make(map[string]reflect.StructField)
|
||||
|
||||
for _, item := range packageItems {
|
||||
subProductCode := item.Product.Code
|
||||
// 在dtoMap中查找子产品的DTO
|
||||
if subDTO, exists := dtoMap[subProductCode]; exists {
|
||||
// 解析DTO的字段
|
||||
dtoType := reflect.TypeOf(subDTO).Elem()
|
||||
for i := 0; i < dtoType.NumField(); i++ {
|
||||
field := dtoType.Field(i)
|
||||
jsonTag := field.Tag.Get("json")
|
||||
if jsonTag != "" && jsonTag != "-" {
|
||||
// 去除omitempty等选项
|
||||
jsonTag = strings.Split(jsonTag, ",")[0]
|
||||
// 如果字段不存在或已存在但新字段有required标记,则覆盖
|
||||
if existingField, exists := fieldMap[jsonTag]; !exists {
|
||||
fieldMap[jsonTag] = field
|
||||
} else {
|
||||
// 如果新字段有required且旧字段没有,则用新字段
|
||||
newValidate := field.Tag.Get("validate")
|
||||
oldValidate := existingField.Tag.Get("validate")
|
||||
if strings.Contains(newValidate, "required") && !strings.Contains(oldValidate, "required") {
|
||||
fieldMap[jsonTag] = field
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 动态创建结构体
|
||||
fields := make([]reflect.StructField, 0, len(fieldMap))
|
||||
for _, field := range fieldMap {
|
||||
fields = append(fields, field)
|
||||
}
|
||||
|
||||
// 创建结构体类型
|
||||
structType := reflect.StructOf(fields)
|
||||
|
||||
// 创建并返回结构体实例
|
||||
structValue := reflect.New(structType)
|
||||
return structValue.Interface(), nil
|
||||
}
|
||||
134
internal/domains/api/services/form_config_service_test.go
Normal file
134
internal/domains/api/services/form_config_service_test.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFormConfigService_GetFormConfig(t *testing.T) {
|
||||
service := NewFormConfigServiceWithoutDependencies()
|
||||
|
||||
// 测试获取存在的API配置
|
||||
config, err := service.GetFormConfig(context.Background(), "IVYZ9363")
|
||||
if err != nil {
|
||||
t.Fatalf("获取表单配置失败: %v", err)
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
t.Fatal("表单配置不应为空")
|
||||
}
|
||||
|
||||
if config.ApiCode != "IVYZ9363" {
|
||||
t.Errorf("期望API代码为 IVYZ9363,实际为 %s", config.ApiCode)
|
||||
}
|
||||
|
||||
if len(config.Fields) == 0 {
|
||||
t.Fatal("字段列表不应为空")
|
||||
}
|
||||
|
||||
// 验证字段信息
|
||||
expectedFields := map[string]bool{
|
||||
"man_name": false,
|
||||
"man_id_card": false,
|
||||
"woman_name": false,
|
||||
"woman_id_card": false,
|
||||
}
|
||||
|
||||
for _, field := range config.Fields {
|
||||
if _, exists := expectedFields[field.Name]; !exists {
|
||||
t.Errorf("意外的字段: %s", field.Name)
|
||||
}
|
||||
expectedFields[field.Name] = true
|
||||
}
|
||||
|
||||
for fieldName, found := range expectedFields {
|
||||
if !found {
|
||||
t.Errorf("缺少字段: %s", fieldName)
|
||||
}
|
||||
}
|
||||
|
||||
// 测试获取不存在的API配置
|
||||
config, err = service.GetFormConfig(context.Background(), "NONEXISTENT")
|
||||
if err != nil {
|
||||
t.Fatalf("获取不存在的API配置不应返回错误: %v", err)
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
t.Fatal("不存在的API配置应返回nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormConfigService_FieldValidation(t *testing.T) {
|
||||
service := NewFormConfigServiceWithoutDependencies()
|
||||
|
||||
config, err := service.GetFormConfig(context.Background(), "FLXG3D56")
|
||||
if err != nil {
|
||||
t.Fatalf("获取表单配置失败: %v", err)
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
t.Fatal("表单配置不应为空")
|
||||
}
|
||||
|
||||
// 验证手机号字段
|
||||
var mobileField *FormField
|
||||
for _, field := range config.Fields {
|
||||
if field.Name == "mobile_no" {
|
||||
mobileField = &field
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if mobileField == nil {
|
||||
t.Fatal("应找到mobile_no字段")
|
||||
}
|
||||
|
||||
if !mobileField.Required {
|
||||
t.Error("mobile_no字段应为必填")
|
||||
}
|
||||
|
||||
if mobileField.Type != "tel" {
|
||||
t.Errorf("mobile_no字段类型应为tel,实际为%s", mobileField.Type)
|
||||
}
|
||||
|
||||
if !contains(mobileField.Validation, "手机号格式") {
|
||||
t.Errorf("mobile_no字段验证规则应包含'手机号格式',实际为: %s", mobileField.Validation)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormConfigService_FieldLabels(t *testing.T) {
|
||||
service := NewFormConfigServiceWithoutDependencies()
|
||||
|
||||
config, err := service.GetFormConfig(context.Background(), "IVYZ9363")
|
||||
if err != nil {
|
||||
t.Fatalf("获取表单配置失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证字段标签
|
||||
expectedLabels := map[string]string{
|
||||
"man_name": "男方姓名",
|
||||
"man_id_card": "男方身份证",
|
||||
"woman_name": "女方姓名",
|
||||
"woman_id_card": "女方身份证",
|
||||
}
|
||||
|
||||
for _, field := range config.Fields {
|
||||
if expectedLabel, exists := expectedLabels[field.Name]; exists {
|
||||
if field.Label != expectedLabel {
|
||||
t.Errorf("字段 %s 的标签应为 %s,实际为 %s", field.Name, expectedLabel, field.Label)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数
|
||||
func contains(s, substr string) bool {
|
||||
return len(s) >= len(substr) && (s == substr || (len(s) > len(substr) && (s[:len(substr)] == substr || s[len(s)-len(substr):] == substr || func() bool {
|
||||
for i := 0; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}())))
|
||||
}
|
||||
128
internal/domains/api/services/processors/README.md
Normal file
128
internal/domains/api/services/processors/README.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# 处理器错误处理解决方案
|
||||
|
||||
## 问题描述
|
||||
|
||||
在使用 `errors.Join(processors.ErrInvalidParam, err)` 包装错误后,外层的 `errors.Is(err, processors.ErrInvalidParam)` 无法正确识别错误类型。
|
||||
|
||||
## 原因分析
|
||||
|
||||
`fmt.Errorf` 创建的包装错误虽然实现了 `Unwrap()` 接口,但没有实现 `Is()` 接口,因此 `errors.Is` 无法正确判断错误类型。
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 🎯 **推荐方案:使用 `errors.Join`(Go 1.20+)**
|
||||
|
||||
这是最简洁、最标准的解决方案,Go 1.20+ 原生支持:
|
||||
|
||||
```go
|
||||
// 在处理器中创建错误
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
|
||||
// 在应用服务层判断错误
|
||||
if errors.Is(err, processors.ErrInvalidParam) {
|
||||
// 现在可以正确识别了!
|
||||
businessError = ErrInvalidParam
|
||||
return ErrInvalidParam
|
||||
}
|
||||
```
|
||||
|
||||
### ✅ **优势**
|
||||
|
||||
1. **极简代码**:一行代码解决问题
|
||||
2. **标准库支持**:Go 1.20+ 原生功能
|
||||
3. **完全兼容**:`errors.Is` 可以正确识别错误类型
|
||||
4. **性能优秀**:标准库实现,性能最佳
|
||||
5. **向后兼容**:现有的错误处理代码无需修改
|
||||
|
||||
### 📝 **使用方法**
|
||||
|
||||
#### 在处理器中(替换旧方式):
|
||||
```go
|
||||
// 旧方式 ❌
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
|
||||
// 新方式 ✅
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
```
|
||||
|
||||
#### 在应用服务层(现在可以正确工作):
|
||||
```go
|
||||
if errors.Is(err, processors.ErrInvalidParam) {
|
||||
// 现在可以正确识别了!
|
||||
businessError = ErrInvalidParam
|
||||
return ErrInvalidParam
|
||||
}
|
||||
```
|
||||
|
||||
## 其他方案对比
|
||||
|
||||
### 方案1:`errors.Join`(推荐 ⭐⭐⭐⭐⭐)
|
||||
- **简洁度**:⭐⭐⭐⭐⭐
|
||||
- **兼容性**:⭐⭐⭐⭐⭐
|
||||
- **性能**:⭐⭐⭐⭐⭐
|
||||
- **维护性**:⭐⭐⭐⭐⭐
|
||||
|
||||
### 方案2:自定义错误类型
|
||||
- **简洁度**:⭐⭐⭐
|
||||
- **兼容性**:⭐⭐⭐⭐⭐
|
||||
- **性能**:⭐⭐⭐⭐
|
||||
- **维护性**:⭐⭐⭐
|
||||
|
||||
### 方案3:继续使用 `fmt.Errorf`
|
||||
- **简洁度**:⭐⭐⭐⭐
|
||||
- **兼容性**:❌(无法识别错误类型)
|
||||
- **性能**:⭐⭐⭐⭐
|
||||
- **维护性**:❌
|
||||
|
||||
## 迁移指南
|
||||
|
||||
### 步骤1: 检查Go版本
|
||||
确保项目使用 Go 1.20 或更高版本
|
||||
|
||||
### 步骤2: 更新错误创建
|
||||
将所有处理器中的 `fmt.Errorf("%s: %w", processors.ErrXXX, err)` 替换为 `errors.Join(processors.ErrXXX, err)`
|
||||
|
||||
### 步骤3: 验证错误判断
|
||||
确保应用服务层的 `errors.Is(err, processors.ErrXXX)` 能正确工作
|
||||
|
||||
### 步骤4: 测试验证
|
||||
运行测试确保所有错误处理逻辑正常工作
|
||||
|
||||
## 示例
|
||||
|
||||
```go
|
||||
// 处理器层
|
||||
func ProcessRequest(ctx context.Context, params []byte, deps *ProcessorDependencies) ([]byte, error) {
|
||||
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
// ... 其他逻辑
|
||||
}
|
||||
|
||||
// 应用服务层
|
||||
if err := s.apiRequestService.PreprocessRequestApi(ctx, cmd.ApiName, requestParams, &cmd.Options, callContext); err != nil {
|
||||
if errors.Is(err, processors.ErrInvalidParam) {
|
||||
// 现在可以正确识别了!
|
||||
businessError = ErrInvalidParam
|
||||
return ErrInvalidParam
|
||||
}
|
||||
// ... 其他错误处理
|
||||
}
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **Go版本要求**:需要 Go 1.20 或更高版本
|
||||
2. **错误消息格式**:`errors.Join` 使用换行符分隔多个错误
|
||||
3. **完全兼容**:`errors.Is` 现在可以正确识别所有错误类型
|
||||
4. **性能提升**:标准库实现,性能优于自定义解决方案
|
||||
|
||||
## 总结
|
||||
|
||||
使用 `errors.Join` 是最简洁、最标准的解决方案:
|
||||
- ✅ 一行代码解决问题
|
||||
- ✅ 完全兼容 `errors.Is`
|
||||
- ✅ Go 1.20+ 原生支持
|
||||
- ✅ 性能优秀,维护简单
|
||||
|
||||
如果你的项目使用 Go 1.20+,强烈推荐使用这个方案!
|
||||
74
internal/domains/api/services/processors/comb/README.md
Normal file
74
internal/domains/api/services/processors/comb/README.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# 组合包处理器说明
|
||||
|
||||
## 🚀 动态组合包机制
|
||||
|
||||
从现在开始,组合包支持**动态处理机制**,大大简化了组合包的开发和维护工作。
|
||||
|
||||
## 📋 工作原理
|
||||
|
||||
### 1. 自动识别
|
||||
- 所有以 `COMB` 开头的API编码会被自动识别为组合包
|
||||
- 系统会自动调用通用组合包处理器处理请求
|
||||
|
||||
### 2. 处理流程
|
||||
1. **优先级检查**:首先检查是否有注册的自定义处理器
|
||||
2. **通用处理**:如果没有自定义处理器,且API编码以COMB开头,使用通用处理器
|
||||
3. **数据库驱动**:根据数据库中的组合包配置自动调用相应的子产品处理器
|
||||
|
||||
## 🛠️ 使用方式
|
||||
|
||||
### 普通组合包(无自定义逻辑)
|
||||
**只需要在数据库配置,无需编写任何代码!**
|
||||
|
||||
1. 在 `products` 表中创建组合包产品:
|
||||
```sql
|
||||
INSERT INTO products (code, name, is_package, ...)
|
||||
VALUES ('COMB1234', '新组合包', true, ...);
|
||||
```
|
||||
|
||||
2. 在 `product_package_items` 表中配置子产品:
|
||||
```sql
|
||||
INSERT INTO product_package_items (package_id, product_id, sort_order)
|
||||
VALUES
|
||||
('组合包产品ID', '子产品1ID', 1),
|
||||
('组合包产品ID', '子产品2ID', 2);
|
||||
```
|
||||
|
||||
3. **直接调用**:无需任何额外编码,API立即可用!
|
||||
|
||||
### 自定义组合包(有特殊逻辑)
|
||||
如果需要对组合包结果进行后处理,才需要编写代码:
|
||||
|
||||
1. **创建处理器文件**:`combXXXX_processor.go`
|
||||
2. **注册处理器**:在 `api_request_service.go` 中注册
|
||||
3. **实现自定义逻辑**:在处理器中实现特殊业务逻辑
|
||||
|
||||
## 📁 现有组合包示例
|
||||
|
||||
### COMB86PM(自定义处理器)
|
||||
```go
|
||||
// 有自定义逻辑:重命名子产品ApiCode
|
||||
for _, resp := range combinedResult.Responses {
|
||||
if resp.ApiCode == "FLXGBC21" {
|
||||
resp.ApiCode = "FLXG54F5"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### COMB298Y(通用处理器)
|
||||
- **无需编码**:已删除专门的处理器文件
|
||||
- **自动处理**:通过数据库配置自动工作
|
||||
|
||||
## ✅ 优势
|
||||
|
||||
1. **零配置**:普通组合包只需数据库配置,无需编码
|
||||
2. **灵活性**:特殊需求仍可通过自定义处理器实现
|
||||
3. **维护性**:减少重复代码,统一处理逻辑
|
||||
4. **扩展性**:新增组合包极其简单,配置即用
|
||||
|
||||
## 🔧 开发建议
|
||||
|
||||
1. **优先使用通用处理器**:除非有特殊业务逻辑,否则不要编写自定义处理器
|
||||
2. **命名规范**:组合包编码必须以 `COMB` 开头
|
||||
3. **数据库配置**:确保组合包在数据库中正确配置了 `is_package=true` 和子产品关系
|
||||
4. **排序控制**:通过 `sort_order` 字段控制子产品在响应中的顺序
|
||||
@@ -0,0 +1,36 @@
|
||||
package comb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
)
|
||||
|
||||
// ProcessCOMB86PMRequest COMB86PM API处理方法
|
||||
func ProcessCOMB86PMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.COMB86PMReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 调用组合包服务处理请求
|
||||
// Options会自动传递给所有子处理器
|
||||
combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, "COMB86PM")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 如果有ApiCode为FLXG54F5的子产品,改名为FLXG54F6
|
||||
for _, resp := range combinedResult.Responses {
|
||||
if resp.ApiCode == "FLXGBC21" {
|
||||
resp.ApiCode = "FLXG54F5"
|
||||
}
|
||||
}
|
||||
return json.Marshal(combinedResult)
|
||||
}
|
||||
178
internal/domains/api/services/processors/comb/comb_service.go
Normal file
178
internal/domains/api/services/processors/comb/comb_service.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package comb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/domains/product/entities"
|
||||
"hyapi-server/internal/domains/product/services"
|
||||
)
|
||||
|
||||
// CombService 组合包服务
|
||||
type CombService struct {
|
||||
productManagementService *services.ProductManagementService
|
||||
processorRegistry map[string]processors.ProcessorFunc
|
||||
}
|
||||
|
||||
// NewCombService 创建组合包服务
|
||||
func NewCombService(productManagementService *services.ProductManagementService) *CombService {
|
||||
return &CombService{
|
||||
productManagementService: productManagementService,
|
||||
processorRegistry: make(map[string]processors.ProcessorFunc),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterProcessor 注册处理器
|
||||
func (cs *CombService) RegisterProcessor(apiCode string, processor processors.ProcessorFunc) {
|
||||
cs.processorRegistry[apiCode] = processor
|
||||
}
|
||||
|
||||
// GetProcessor 获取处理器(用于内部调用)
|
||||
func (cs *CombService) GetProcessor(apiCode string) (processors.ProcessorFunc, bool) {
|
||||
processor, exists := cs.processorRegistry[apiCode]
|
||||
return processor, exists
|
||||
}
|
||||
|
||||
// ProcessCombRequest 处理组合包请求 - 实现 CombServiceInterface
|
||||
func (cs *CombService) ProcessCombRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies, packageCode string) (*processors.CombinedResult, error) {
|
||||
// 1. 根据组合包code获取产品信息
|
||||
packageProduct, err := cs.productManagementService.GetProductByCode(ctx, packageCode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取组合包信息失败: %s", err.Error())
|
||||
}
|
||||
|
||||
if !packageProduct.IsPackage {
|
||||
return nil, fmt.Errorf("产品 %s 不是组合包", packageCode)
|
||||
}
|
||||
|
||||
// 2. 获取组合包的所有子产品
|
||||
packageItems, err := cs.productManagementService.GetPackageItems(ctx, packageProduct.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取组合包子产品失败: %s", err.Error())
|
||||
}
|
||||
|
||||
if len(packageItems) == 0 {
|
||||
return nil, fmt.Errorf("组合包 %s 没有配置子产品", packageCode)
|
||||
}
|
||||
|
||||
// 3. 并发调用所有子产品的处理器
|
||||
results := cs.processSubProducts(ctx, params, deps, packageItems)
|
||||
|
||||
// 4. 组合结果
|
||||
return cs.combineResults(results)
|
||||
}
|
||||
|
||||
// processSubProducts 并发处理子产品
|
||||
func (cs *CombService) processSubProducts(
|
||||
ctx context.Context,
|
||||
params []byte,
|
||||
deps *processors.ProcessorDependencies,
|
||||
packageItems []*entities.ProductPackageItem,
|
||||
) []*processors.SubProductResult {
|
||||
results := make([]*processors.SubProductResult, 0, len(packageItems))
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
|
||||
// 并发处理每个子产品
|
||||
for _, item := range packageItems {
|
||||
wg.Add(1)
|
||||
go func(item *entities.ProductPackageItem) {
|
||||
defer wg.Done()
|
||||
|
||||
result := cs.processSingleSubProduct(ctx, params, deps, item)
|
||||
|
||||
mu.Lock()
|
||||
results = append(results, result)
|
||||
mu.Unlock()
|
||||
}(item)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
// 按SortOrder排序
|
||||
sort.Slice(results, func(i, j int) bool {
|
||||
return results[i].SortOrder < results[j].SortOrder
|
||||
})
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// processSingleSubProduct 处理单个子产品
|
||||
func (cs *CombService) processSingleSubProduct(
|
||||
ctx context.Context,
|
||||
params []byte,
|
||||
deps *processors.ProcessorDependencies,
|
||||
item *entities.ProductPackageItem,
|
||||
) *processors.SubProductResult {
|
||||
result := &processors.SubProductResult{
|
||||
ApiCode: item.Product.Code,
|
||||
SortOrder: item.SortOrder,
|
||||
Success: false,
|
||||
}
|
||||
|
||||
// 查找对应的处理器
|
||||
processor, exists := cs.processorRegistry[item.Product.Code]
|
||||
if !exists {
|
||||
result.Error = fmt.Sprintf("未找到处理器: %s", item.Product.Code)
|
||||
return result
|
||||
}
|
||||
|
||||
// 调用处理器
|
||||
respBytes, err := processor(ctx, params, deps)
|
||||
if err != nil {
|
||||
result.Error = err.Error()
|
||||
return result
|
||||
}
|
||||
|
||||
// 解析响应
|
||||
var responseData interface{}
|
||||
if err := json.Unmarshal(respBytes, &responseData); err != nil {
|
||||
result.Error = fmt.Sprintf("解析响应失败: %s", err.Error())
|
||||
return result
|
||||
}
|
||||
|
||||
result.Success = true
|
||||
result.Data = responseData
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// combineResults 组合所有子产品的结果
|
||||
// 只要至少有一个子产品成功,就返回成功结果(部分成功也算成功)
|
||||
// 只有当所有子产品都失败时,才返回错误
|
||||
func (cs *CombService) combineResults(results []*processors.SubProductResult) (*processors.CombinedResult, error) {
|
||||
// 检查是否至少有一个成功的子产品
|
||||
hasSuccess := false
|
||||
for _, result := range results {
|
||||
if result.Success {
|
||||
hasSuccess = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 构建组合结果
|
||||
combinedResult := &processors.CombinedResult{
|
||||
Responses: results,
|
||||
}
|
||||
|
||||
// 如果所有子产品都失败,返回错误
|
||||
if !hasSuccess && len(results) > 0 {
|
||||
// 构建错误信息,包含所有失败的原因
|
||||
errorMessages := make([]string, 0, len(results))
|
||||
for _, result := range results {
|
||||
if result.Error != "" {
|
||||
errorMessages = append(errorMessages, fmt.Sprintf("%s: %s", result.ApiCode, result.Error))
|
||||
}
|
||||
}
|
||||
errorMsg := fmt.Sprintf("组合包所有子产品调用失败: %s", strings.Join(errorMessages, "; "))
|
||||
return nil, fmt.Errorf(errorMsg)
|
||||
}
|
||||
|
||||
// 至少有一个成功,返回成功结果
|
||||
return combinedResult, nil
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package comb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/shared/logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ProcessCOMBHZY2Request 处理 COMBHZY2 组合包请求
|
||||
func ProcessCOMBHZY2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
log := logger.GetGlobalLogger()
|
||||
|
||||
var req dto.COMBHZY2Req
|
||||
if err := json.Unmarshal(params, &req); err != nil {
|
||||
log.Error("COMBHZY2请求参数反序列化失败",
|
||||
zap.Error(err),
|
||||
zap.String("params", string(params)),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
if err := deps.Validator.ValidateStruct(req); err != nil {
|
||||
log.Error("COMBHZY2请求参数验证失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
|
||||
combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, "COMBHZY2")
|
||||
if err != nil {
|
||||
log.Error("COMBHZY2组合包服务调用失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if combinedResult == nil {
|
||||
log.Error("COMBHZY2组合包响应为空",
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, errors.New("组合包响应为空")
|
||||
}
|
||||
|
||||
log.Info("COMBHZY2组合包服务调用成功",
|
||||
zap.Int("子产品数量", len(combinedResult.Responses)),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
|
||||
sourceCtx, err := buildSourceContextFromCombined(ctx, combinedResult)
|
||||
if err != nil {
|
||||
log.Error("COMBHZY2构建源数据上下文失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
report := buildTargetReport(ctx, sourceCtx)
|
||||
|
||||
reportBytes, err := json.Marshal(report)
|
||||
if err != nil {
|
||||
log.Error("COMBHZY2报告序列化失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return reportBytes, nil
|
||||
}
|
||||
|
||||
func buildSourceContextFromCombined(ctx context.Context, result *processors.CombinedResult) (*sourceContext, error) {
|
||||
log := logger.GetGlobalLogger()
|
||||
|
||||
if result == nil {
|
||||
log.Error("组合包响应为空", zap.String("api_code", "COMBHZY2"))
|
||||
return nil, errors.New("组合包响应为空")
|
||||
}
|
||||
|
||||
src := sourceFile{Responses: make([]sourceResponse, 0, len(result.Responses))}
|
||||
successCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, resp := range result.Responses {
|
||||
if !resp.Success {
|
||||
log.Warn("子产品调用失败,跳过",
|
||||
zap.String("api_code", resp.ApiCode),
|
||||
zap.String("error", resp.Error),
|
||||
zap.String("parent_api_code", "COMBHZY2"),
|
||||
)
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
if resp.Data == nil {
|
||||
log.Warn("子产品数据为空,跳过",
|
||||
zap.String("api_code", resp.ApiCode),
|
||||
zap.String("parent_api_code", "COMBHZY2"),
|
||||
)
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
raw, err := json.Marshal(resp.Data)
|
||||
if err != nil {
|
||||
log.Error("序列化子产品数据失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", resp.ApiCode),
|
||||
zap.String("parent_api_code", "COMBHZY2"),
|
||||
)
|
||||
failedCount++
|
||||
continue
|
||||
}
|
||||
|
||||
src.Responses = append(src.Responses, sourceResponse{
|
||||
ApiCode: resp.ApiCode,
|
||||
Data: raw,
|
||||
Success: resp.Success,
|
||||
})
|
||||
successCount++
|
||||
}
|
||||
|
||||
log.Info("组合包子产品处理完成",
|
||||
zap.Int("成功数量", successCount),
|
||||
zap.Int("失败数量", failedCount),
|
||||
zap.Int("总数量", len(result.Responses)),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
|
||||
if len(src.Responses) == 0 {
|
||||
log.Error("组合包子产品全部调用失败",
|
||||
zap.Int("总数量", len(result.Responses)),
|
||||
zap.String("api_code", "COMBHZY2"),
|
||||
)
|
||||
return nil, errors.New("组合包子产品全部调用失败")
|
||||
}
|
||||
|
||||
return buildSourceContext(ctx, src)
|
||||
}
|
||||
2053
internal/domains/api/services/processors/comb/combhzy2_transform.go
Normal file
2053
internal/domains/api/services/processors/comb/combhzy2_transform.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
package comb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/shared/logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ProcessCOMBWD01Request 处理 COMBWD01 组合包请求
|
||||
// 将返回结构从数组改为以 api_code 为 key 的对象结构
|
||||
func ProcessCOMBWD01Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
log := logger.GetGlobalLogger()
|
||||
|
||||
// 调用组合包服务处理请求
|
||||
combinedResult, err := deps.CombService.ProcessCombRequest(ctx, params, deps, "COMBWD01")
|
||||
if err != nil {
|
||||
log.Error("COMBWD01组合包服务调用失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", "COMBWD01"),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if combinedResult == nil {
|
||||
log.Error("COMBWD01组合包响应为空",
|
||||
zap.String("api_code", "COMBWD01"),
|
||||
)
|
||||
return nil, errors.New("组合包响应为空")
|
||||
}
|
||||
|
||||
log.Info("COMBWD01组合包服务调用成功",
|
||||
zap.Int("子产品数量", len(combinedResult.Responses)),
|
||||
zap.String("api_code", "COMBWD01"),
|
||||
)
|
||||
|
||||
// 将数组结构转换为对象结构
|
||||
responsesMap := make(map[string]*ResponseItem)
|
||||
for _, resp := range combinedResult.Responses {
|
||||
item := &ResponseItem{
|
||||
ApiCode: resp.ApiCode,
|
||||
Success: resp.Success,
|
||||
}
|
||||
|
||||
// 根据成功/失败状态设置 data 和 error 字段
|
||||
if resp.Success {
|
||||
// 成功时:data 有值(可能为 nil),error 为 null
|
||||
item.Data = resp.Data
|
||||
item.Error = nil
|
||||
} else {
|
||||
// 失败时:data 为 null,error 有值
|
||||
item.Data = nil
|
||||
if resp.Error != "" {
|
||||
item.Error = resp.Error
|
||||
} else {
|
||||
item.Error = "未知错误"
|
||||
}
|
||||
}
|
||||
|
||||
responsesMap[resp.ApiCode] = item
|
||||
}
|
||||
|
||||
// 构建新的响应结构
|
||||
result := map[string]interface{}{
|
||||
"responses": responsesMap,
|
||||
}
|
||||
|
||||
// 序列化并返回
|
||||
resultBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
log.Error("COMBWD01响应序列化失败",
|
||||
zap.Error(err),
|
||||
zap.String("api_code", "COMBWD01"),
|
||||
)
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return resultBytes, nil
|
||||
}
|
||||
|
||||
// ResponseItem 响应项结构
|
||||
type ResponseItem struct {
|
||||
ApiCode string `json:"api_code"`
|
||||
Success bool `json:"success"`
|
||||
Data interface{} `json:"data"`
|
||||
Error interface{} `json:"error"`
|
||||
}
|
||||
124
internal/domains/api/services/processors/dependencies.go
Normal file
124
internal/domains/api/services/processors/dependencies.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package processors
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"hyapi-server/internal/application/api/commands"
|
||||
"hyapi-server/internal/domains/api/repositories"
|
||||
"hyapi-server/internal/infrastructure/external/alicloud"
|
||||
"hyapi-server/internal/infrastructure/external/jiguang"
|
||||
"hyapi-server/internal/infrastructure/external/muzi"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
"hyapi-server/internal/infrastructure/external/tianyancha"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
"hyapi-server/internal/infrastructure/external/yushan"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
"hyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
// CombServiceInterface 组合包服务接口
|
||||
type CombServiceInterface interface {
|
||||
ProcessCombRequest(ctx context.Context, params []byte, deps *ProcessorDependencies, packageCode string) (*CombinedResult, error)
|
||||
}
|
||||
|
||||
// CallContext CallApi调用上下文,包含调用相关的数据
|
||||
type CallContext struct {
|
||||
ContractCode string // 合同编号
|
||||
}
|
||||
|
||||
// ProcessorDependencies 处理器依赖容器
|
||||
type ProcessorDependencies struct {
|
||||
WestDexService *westdex.WestDexService
|
||||
ShujubaoService *shujubao.ShujubaoService
|
||||
MuziService *muzi.MuziService
|
||||
YushanService *yushan.YushanService
|
||||
TianYanChaService *tianyancha.TianYanChaService
|
||||
AlicloudService *alicloud.AlicloudService
|
||||
ZhichaService *zhicha.ZhichaService
|
||||
XingweiService *xingwei.XingweiService
|
||||
JiguangService *jiguang.JiguangService
|
||||
ShumaiService *shumai.ShumaiService
|
||||
Validator interfaces.RequestValidator
|
||||
CombService CombServiceInterface // Changed to interface to break import cycle
|
||||
Options *commands.ApiCallOptions // 添加Options支持
|
||||
CallContext *CallContext // 添加CallApi调用上下文
|
||||
|
||||
// 企业报告记录仓储,用于持久化 QYGLJ1U9 生成的企业报告
|
||||
ReportRepo repositories.ReportRepository
|
||||
|
||||
// 企业报告 PDF 异步预生成(可为 nil)
|
||||
ReportPDFScheduler QYGLReportPDFScheduler
|
||||
|
||||
// APIPublicBaseURL 对外 API 根地址(无尾斜杠),用于 QYGL reportUrl 等
|
||||
APIPublicBaseURL string
|
||||
}
|
||||
|
||||
// NewProcessorDependencies 创建处理器依赖容器
|
||||
func NewProcessorDependencies(
|
||||
westDexService *westdex.WestDexService,
|
||||
shujubaoService *shujubao.ShujubaoService,
|
||||
muziService *muzi.MuziService,
|
||||
yushanService *yushan.YushanService,
|
||||
tianYanChaService *tianyancha.TianYanChaService,
|
||||
alicloudService *alicloud.AlicloudService,
|
||||
zhichaService *zhicha.ZhichaService,
|
||||
xingweiService *xingwei.XingweiService,
|
||||
jiguangService *jiguang.JiguangService,
|
||||
shumaiService *shumai.ShumaiService,
|
||||
validator interfaces.RequestValidator,
|
||||
combService CombServiceInterface, // Changed to interface
|
||||
reportRepo repositories.ReportRepository,
|
||||
reportPDFScheduler QYGLReportPDFScheduler,
|
||||
apiPublicBaseURL string,
|
||||
) *ProcessorDependencies {
|
||||
return &ProcessorDependencies{
|
||||
WestDexService: westDexService,
|
||||
ShujubaoService: shujubaoService,
|
||||
MuziService: muziService,
|
||||
YushanService: yushanService,
|
||||
TianYanChaService: tianYanChaService,
|
||||
AlicloudService: alicloudService,
|
||||
ZhichaService: zhichaService,
|
||||
XingweiService: xingweiService,
|
||||
JiguangService: jiguangService,
|
||||
ShumaiService: shumaiService,
|
||||
Validator: validator,
|
||||
CombService: combService,
|
||||
Options: nil, // 初始化为nil,在调用时设置
|
||||
CallContext: nil, // 初始化为nil,在调用时设置
|
||||
ReportRepo: reportRepo,
|
||||
ReportPDFScheduler: reportPDFScheduler,
|
||||
APIPublicBaseURL: apiPublicBaseURL,
|
||||
}
|
||||
}
|
||||
|
||||
// WithOptions 设置Options的便捷方法
|
||||
func (deps *ProcessorDependencies) WithOptions(options *commands.ApiCallOptions) *ProcessorDependencies {
|
||||
deps.Options = options
|
||||
return deps
|
||||
}
|
||||
|
||||
// WithCallContext 设置CallContext的便捷方法
|
||||
func (deps *ProcessorDependencies) WithCallContext(callContext *CallContext) *ProcessorDependencies {
|
||||
deps.CallContext = callContext
|
||||
return deps
|
||||
}
|
||||
|
||||
// ProcessorFunc 处理器函数类型定义
|
||||
type ProcessorFunc func(ctx context.Context, params []byte, deps *ProcessorDependencies) ([]byte, error)
|
||||
|
||||
// CombinedResult 组合结果
|
||||
type CombinedResult struct {
|
||||
Responses []*SubProductResult `json:"responses"` // 子接口响应列表
|
||||
}
|
||||
|
||||
// SubProductResult 子产品处理结果
|
||||
type SubProductResult struct {
|
||||
ApiCode string `json:"api_code"` // 子接口标识
|
||||
Data interface{} `json:"data"` // 子接口返回数据
|
||||
Success bool `json:"success"` // 是否成功
|
||||
Error string `json:"error,omitempty"` // 错误信息(仅在失败时)
|
||||
SortOrder int `json:"-"` // 排序字段,不输出到JSON
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dwbg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessDWBG5SAMRequest DWBG5SAM 海宇指迷报告
|
||||
func ProcessDWBG5SAMRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.DWBG5SAMReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"accessoryUrl": paramsDto.AuthorizationURL,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI112", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤响应数据,删除指定字段
|
||||
if respMap, ok := respData.(map[string]interface{}); ok {
|
||||
delete(respMap, "reportUrl")
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package dwbg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessDWBG6A2CRequest DWBG6A2C API处理方法 - 司南报告
|
||||
func ProcessDWBG6A2CRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.DWBG6A2CReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"accessoryUrl": paramsDto.AuthorizationURL,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI102", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤响应数据,删除指定字段
|
||||
if respMap, ok := respData.(map[string]interface{}); ok {
|
||||
delete(respMap, "reportUrl")
|
||||
delete(respMap, "multCourtInfo")
|
||||
// delete(respMap, "judiciaRiskInfos")
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dwbg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessDWBG7F3ARequest DWBG7F3A API处理方法 - 行为数据查询
|
||||
func ProcessDWBG7F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.DWBG7F3AReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,使用xingwei服务的正确字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
"phoneNumber": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1101695406546284544"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
// 查空情况,返回特定的查空错误
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
// 数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
// 系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
4622
internal/domains/api/services/processors/dwbg/dwbg8b4d_processor.go
Normal file
4622
internal/domains/api/services/processors/dwbg/dwbg8b4d_processor.go
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
11
internal/domains/api/services/processors/errors.go
Normal file
11
internal/domains/api/services/processors/errors.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package processors
|
||||
|
||||
import "errors"
|
||||
|
||||
// 处理器相关错误类型
|
||||
var (
|
||||
ErrDatasource = errors.New("数据源异常")
|
||||
ErrSystem = errors.New("系统异常")
|
||||
ErrInvalidParam = errors.New("参数校验不正确")
|
||||
ErrNotFound = errors.New("查询为空")
|
||||
)
|
||||
91
internal/domains/api/services/processors/errors_test.go
Normal file
91
internal/domains/api/services/processors/errors_test.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package processors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestErrorsJoin_Is(t *testing.T) {
|
||||
// 创建一个参数验证错误
|
||||
originalErr := errors.New("字段验证失败")
|
||||
joinedErr := errors.Join(ErrInvalidParam, originalErr)
|
||||
|
||||
// 测试 errors.Is 是否能正确识别错误类型
|
||||
if !errors.Is(joinedErr, ErrInvalidParam) {
|
||||
t.Errorf("errors.Is(joinedErr, ErrInvalidParam) 应该返回 true")
|
||||
}
|
||||
|
||||
if errors.Is(joinedErr, ErrSystem) {
|
||||
t.Errorf("errors.Is(joinedErr, ErrSystem) 应该返回 false")
|
||||
}
|
||||
|
||||
// 测试错误消息
|
||||
expectedMsg := "参数校验不正确\n字段验证失败"
|
||||
if joinedErr.Error() != expectedMsg {
|
||||
t.Errorf("错误消息不匹配,期望: %s, 实际: %s", expectedMsg, joinedErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsJoin_Unwrap(t *testing.T) {
|
||||
originalErr := errors.New("原始错误")
|
||||
joinedErr := errors.Join(ErrSystem, originalErr)
|
||||
|
||||
// 测试 Unwrap - errors.Join 的 Unwrap 行为
|
||||
// errors.Join 的 Unwrap 可能返回 nil 或者第一个错误,这取决于实现
|
||||
// 我们主要关心 errors.Is 是否能正确工作
|
||||
if !errors.Is(joinedErr, ErrSystem) {
|
||||
t.Errorf("errors.Is(joinedErr, ErrSystem) 应该返回 true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsJoin_MultipleErrors(t *testing.T) {
|
||||
err1 := errors.New("错误1")
|
||||
err2 := errors.New("错误2")
|
||||
joinedErr := errors.Join(ErrNotFound, err1, err2)
|
||||
|
||||
// 测试 errors.Is 识别多个错误类型
|
||||
if !errors.Is(joinedErr, ErrNotFound) {
|
||||
t.Errorf("errors.Is(joinedErr, ErrNotFound) 应该返回 true")
|
||||
}
|
||||
|
||||
// 测试错误消息
|
||||
expectedMsg := "查询为空\n错误1\n错误2"
|
||||
if joinedErr.Error() != expectedMsg {
|
||||
t.Errorf("错误消息不匹配,期望: %s, 实际: %s", expectedMsg, joinedErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsJoin_RealWorldScenario(t *testing.T) {
|
||||
// 模拟真实的处理器错误场景
|
||||
validationErr := errors.New("手机号格式不正确")
|
||||
processorErr := errors.Join(ErrInvalidParam, validationErr)
|
||||
|
||||
// 在应用服务层,现在应该可以正确识别错误类型
|
||||
if !errors.Is(processorErr, ErrInvalidParam) {
|
||||
t.Errorf("应用服务层应该能够识别 ErrInvalidParam")
|
||||
}
|
||||
|
||||
// 错误消息应该包含两种信息
|
||||
errorMsg := processorErr.Error()
|
||||
if !contains(errorMsg, "参数校验不正确") {
|
||||
t.Errorf("错误消息应该包含错误类型: %s", errorMsg)
|
||||
}
|
||||
if !contains(errorMsg, "手机号格式不正确") {
|
||||
t.Errorf("错误消息应该包含原始错误: %s", errorMsg)
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数:检查字符串是否包含子字符串
|
||||
func contains(s, substr string) bool {
|
||||
return len(s) >= len(substr) && (s == substr ||
|
||||
(len(s) > len(substr) && (s[:len(substr)] == substr ||
|
||||
s[len(s)-len(substr):] == substr ||
|
||||
func() bool {
|
||||
for i := 1; i <= len(s)-len(substr); i++ {
|
||||
if s[i:i+len(substr)] == substr {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}())))
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/yushan"
|
||||
)
|
||||
|
||||
// ProcessFLXG0687Request FLXG0687 API处理方法
|
||||
func ProcessFLXG0687Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG0687Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"keyWord": paramsDto.IDCard,
|
||||
"type": 3,
|
||||
}
|
||||
|
||||
respBytes, err := deps.YushanService.CallAPI(ctx, "RIS031", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, yushan.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG0V3Bequest FLXG0V3B API处理方法
|
||||
func ProcessFLXG0V3Bequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG0V3BReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id_card": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G34BJ03", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// ProcessFLXG0V4BRequest FLXG0V4B API处理方法(身份证排空入口,身份证身份证身份证身份证身份证)
|
||||
func ProcessFLXG0V4BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG0V4BReq
|
||||
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)
|
||||
}
|
||||
// 去掉司法案件案件去掉身份证号码
|
||||
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" {
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
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)
|
||||
}
|
||||
if deps.CallContext.ContractCode == "" {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空"))
|
||||
}
|
||||
encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idcard": encryptedIDCard,
|
||||
"auth_authorizeFileCode": encryptedAuthAuthorizeFileCode,
|
||||
"inquired_auth": fmt.Sprintf("authed:%s", paramsDto.AuthDate),
|
||||
},
|
||||
}
|
||||
log.Println("reqData", reqData)
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G22SC01", reqData)
|
||||
if err != nil {
|
||||
// 数据源错误
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
// 如果有返回内容,优先解析返回内容
|
||||
if respBytes != nil {
|
||||
parsed, parseErr := ParseJsonResponse(respBytes)
|
||||
if parseErr == nil {
|
||||
// 通过gjson获取指定路径的数据
|
||||
contentResult := gjson.GetBytes(parsed, "G22SC0101.G22SC0102.content")
|
||||
if contentResult.Exists() {
|
||||
return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
return parsed, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
// 解析失败,返回原始内容和系统错误
|
||||
return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr)
|
||||
}
|
||||
// 没有返回内容,直接返回数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
// 其他系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse
|
||||
parsed, parseErr := ParseJsonResponse(respBytes)
|
||||
if parseErr != nil {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr)
|
||||
}
|
||||
|
||||
// 通过gjson获取指定路径的数据
|
||||
contentResult := gjson.GetBytes(parsed, "G22SC0101.G22SC0102.content")
|
||||
if contentResult.Exists() {
|
||||
return []byte(contentResult.Raw), nil
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Content 数据内容
|
||||
type FLXG0V4BResponse struct {
|
||||
Sxbzxr Sxbzxr `json:"sxbzxr"` // 失信被执行人
|
||||
Entout Entout `json:"entout"` // 涉诉信息
|
||||
Xgbzxr Xgbzxr `json:"xgbzxr"` // 限高被执行人
|
||||
}
|
||||
|
||||
// Sxbzxr 失信被执行人
|
||||
type Sxbzxr struct {
|
||||
Msg string `json:"msg"` // 备注信息
|
||||
Data SxbzxrData `json:"data"` // 数据结果
|
||||
}
|
||||
|
||||
// SxbzxrData 失信被执行人数据
|
||||
type SxbzxrData struct {
|
||||
Sxbzxr []SxbzxrItem `json:"sxbzxr"` // 失信被执行人列表
|
||||
}
|
||||
|
||||
// SxbzxrItem 失信被执行人项
|
||||
type SxbzxrItem struct {
|
||||
Yw string `json:"yw"` // 生效法律文书确定的义务
|
||||
PjjeGj int `json:"pjje_gj"` // 判决金额_估计
|
||||
Xwqx string `json:"xwqx"` // 失信被执行人行为具体情形
|
||||
ID string `json:"id"` // 标识
|
||||
Zxfy string `json:"zxfy"` // 执行法院
|
||||
Ah string `json:"ah"` // 案号
|
||||
Zxyjwh string `json:"zxyjwh"` // 执行依据文号
|
||||
Lxqk string `json:"lxqk"` // 被执行人的履行情况
|
||||
Zxyjdw string `json:"zxyjdw"` // 出执行依据单位
|
||||
Fbrq string `json:"fbrq"` // 发布时间(日期)
|
||||
Xb string `json:"xb"` // 性别
|
||||
Larq string `json:"larq"` // 立案日期
|
||||
Sf string `json:"sf"` // 省份
|
||||
}
|
||||
|
||||
// Entout 涉诉信息
|
||||
type Entout struct {
|
||||
Msg string `json:"msg"` // 备注信息
|
||||
Data EntoutData `json:"data"` // 数据结果
|
||||
}
|
||||
|
||||
// EntoutData 涉诉信息数据
|
||||
type EntoutData struct {
|
||||
Administrative Administrative `json:"administrative"` // 行政案件
|
||||
Implement Implement `json:"implement"` // 执行案件
|
||||
Count Count `json:"count"` // 统计
|
||||
Preservation Preservation `json:"preservation"` // 案件类型(非诉保全审查)
|
||||
Crc int `json:"crc"` // 当事人变更码
|
||||
Civil Civil `json:"civil"` // 民事案件
|
||||
Criminal Criminal `json:"criminal"` // 刑事案件
|
||||
CasesTree CasesTree `json:"cases_tree"` // 串联树
|
||||
Bankrupt Bankrupt `json:"bankrupt"` // 强制清算与破产案件
|
||||
}
|
||||
|
||||
// Administrative 行政案件
|
||||
type Administrative struct {
|
||||
Cases []AdministrativeCase `json:"cases"` // 案件
|
||||
Count Count `json:"count"` // 统计
|
||||
}
|
||||
|
||||
// AdministrativeCase 行政案件项
|
||||
type AdministrativeCase struct {
|
||||
NjabdjeGjLevel int `json:"n_jabdje_gj_level"` // 结案标的金额估计等级
|
||||
NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级
|
||||
CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号
|
||||
Njafs string `json:"n_jafs"` // 结案方式
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
Djarq string `json:"d_jarq"` // 结案时间
|
||||
CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果
|
||||
Nqsbdje int `json:"n_qsbdje"` // 起诉标的金额
|
||||
Ncrc int `json:"n_crc"` // 案件变更码
|
||||
Cssdy string `json:"c_ssdy"` // 所属地域
|
||||
Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段
|
||||
Njaay string `json:"n_jaay"` // 结案案由
|
||||
Najlx string `json:"n_ajlx"` // 案件类型
|
||||
CahYs string `json:"c_ah_ys"` // 原审案号
|
||||
NlaayTree string `json:"n_laay_tree"` // 立案案由详细
|
||||
NjabdjeLevel int `json:"n_jabdje_level"` // 结案标的金额等级
|
||||
Nlaay string `json:"n_laay"` // 立案案由
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
Njbfy string `json:"n_jbfy"` // 经办法院
|
||||
CgkwsID string `json:"c_gkws_id"` // 公开文书ID
|
||||
NjabdjeGj int `json:"n_jabdje_gj"` // 结案标的金额估计
|
||||
NpjVictory string `json:"n_pj_victory"` // 胜诉估计
|
||||
CgkwsDsr string `json:"c_gkws_dsr"` // 当事人
|
||||
Nslcx string `json:"n_slcx"` // 审理程序
|
||||
NqsbdjeLevel int `json:"n_qsbdje_level"` // 起诉标的金额等级
|
||||
CID string `json:"c_id"` // 案件唯一ID
|
||||
NssdwYs string `json:"n_ssdw_ys"` // 一审诉讼地位
|
||||
Cslfsxx string `json:"c_slfsxx"` // 审理方式信息
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人
|
||||
Dlarq string `json:"d_larq"` // 立案时间
|
||||
NjaayTree string `json:"n_jaay_tree"` // 结案案由详细
|
||||
CahHx string `json:"c_ah_hx"` // 后续案号
|
||||
Njabdje int `json:"n_jabdje"` // 结案标的金额
|
||||
}
|
||||
|
||||
// Implement 执行案件
|
||||
type Implement struct {
|
||||
Cases []ImplementCase `json:"cases"` // 案件
|
||||
Count Count `json:"count"` // 统计
|
||||
}
|
||||
|
||||
// ImplementCase 执行案件项
|
||||
type ImplementCase struct {
|
||||
Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人
|
||||
Cssdy string `json:"c_ssdy"` // 所属地域
|
||||
NjabdjeGj int `json:"n_jabdje_gj"` // 结案标的金额估计
|
||||
Ncrc int `json:"n_crc"` // 案件变更码
|
||||
Nlaay string `json:"n_laay"` // 立案案由
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
Nsqzxbdje int `json:"n_sqzxbdje"` // 申请执行标的金额
|
||||
CahYs string `json:"c_ah_ys"` // 原审案号
|
||||
CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果
|
||||
Njafs string `json:"n_jafs"` // 结案方式
|
||||
Njaay string `json:"n_jaay"` // 结案案由
|
||||
NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级
|
||||
CID string `json:"c_id"` // 案件唯一ID
|
||||
Njabdje int `json:"n_jabdje"` // 结案标的金额
|
||||
Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段
|
||||
Dlarq string `json:"d_larq"` // 立案时间
|
||||
Najlx string `json:"n_ajlx"` // 案件类型
|
||||
Nsjdwje int `json:"n_sjdwje"` // 实际到位金额
|
||||
CgkwsID string `json:"c_gkws_id"` // 公开文书ID
|
||||
CahHx string `json:"c_ah_hx"` // 后续案号
|
||||
Nwzxje int `json:"n_wzxje"` // 未执行金额
|
||||
Djarq string `json:"d_jarq"` // 结案时间
|
||||
CgkwsDsr string `json:"c_gkws_dsr"` // 当事人
|
||||
Njbfy string `json:"n_jbfy"` // 经办法院
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
}
|
||||
|
||||
// Preservation 案件类型(非诉保全审查)
|
||||
type Preservation struct {
|
||||
Cases []PreservationCase `json:"cases"` // 案件
|
||||
Count Count `json:"count"` // 统计
|
||||
}
|
||||
|
||||
// PreservationCase 非诉保全审查案件项
|
||||
type PreservationCase struct {
|
||||
NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
Ncrc int `json:"n_crc"` // 案件变更码
|
||||
Cssdy string `json:"c_ssdy"` // 所属地域
|
||||
Dlarq string `json:"d_larq"` // 立案时间
|
||||
CgkwsID string `json:"c_gkws_id"` // 公开文书ID
|
||||
CahYs string `json:"c_ah_ys"` // 原审案号
|
||||
Nsqbqse int `json:"n_sqbqse"` // 申请保全数额
|
||||
Djarq string `json:"d_jarq"` // 结案时间
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
CgkwsDsr string `json:"c_gkws_dsr"` // 当事人
|
||||
CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果
|
||||
Njbfy string `json:"n_jbfy"` // 经办法院
|
||||
Njafs string `json:"n_jafs"` // 结案方式
|
||||
Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人
|
||||
Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段
|
||||
Najlx string `json:"n_ajlx"` // 案件类型
|
||||
CID string `json:"c_id"` // 案件唯一ID
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
NsqbqseLevel int `json:"n_sqbqse_level"` // 申请保全数额等级
|
||||
CahHx string `json:"c_ah_hx"` // 后续案号
|
||||
Csqbqbdw string `json:"c_sqbqbdw"` // 申请保全标的物
|
||||
CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号
|
||||
}
|
||||
|
||||
// Civil 民事案件
|
||||
type Civil struct {
|
||||
Cases []CivilCase `json:"cases"` // 案件
|
||||
Count Count `json:"count"` // 统计
|
||||
}
|
||||
|
||||
// CivilCase 民事案件项
|
||||
type CivilCase struct {
|
||||
NjabdjeLevel int `json:"n_jabdje_level"` // 结案标的金额等级
|
||||
Nslcx string `json:"n_slcx"` // 审理程序
|
||||
NjabdjeGjLevel int `json:"n_jabdje_gj_level"` // 结案标的金额估计等级
|
||||
Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段
|
||||
Njafs string `json:"n_jafs"` // 结案方式
|
||||
CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果
|
||||
Cslfsxx string `json:"c_slfsxx"` // 审理方式信息
|
||||
Nlaay string `json:"n_laay"` // 立案案由
|
||||
CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
NssdwYs string `json:"n_ssdw_ys"` // 一审诉讼地位
|
||||
NlaayTag string `json:"n_laay_tag"` // 立案案由标签
|
||||
NqsbdjeLevel int `json:"n_qsbdje_level"` // 起诉标的金额等级
|
||||
Ncrc int `json:"n_crc"` // 案件变更码
|
||||
CahHx string `json:"c_ah_hx"` // 后续案号
|
||||
NqsbdjeGjLevel int `json:"n_qsbdje_gj_level"` // 起诉标的金额估计等级
|
||||
Njbfy string `json:"n_jbfy"` // 经办法院
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
Njabdje int `json:"n_jabdje"` // 结案标的金额
|
||||
NjabdjeGj int `json:"n_jabdje_gj"` // 结案标的金额估计
|
||||
NqsbdjeGj int `json:"n_qsbdje_gj"` // 起诉标的金额估计
|
||||
NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级
|
||||
Cssdy string `json:"c_ssdy"` // 所属地域
|
||||
Dlarq string `json:"d_larq"` // 立案时间
|
||||
CgkwsID string `json:"c_gkws_id"` // 公开文书ID
|
||||
NpjVictory string `json:"n_pj_victory"` // 胜诉估计
|
||||
CgkwsDsr string `json:"c_gkws_dsr"` // 当事人
|
||||
Djarq string `json:"d_jarq"` // 结案时间
|
||||
Njaay string `json:"n_jaay"` // 结案案由
|
||||
NlaayTree string `json:"n_laay_tree"` // 立案案由详细
|
||||
Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人
|
||||
CahYs string `json:"c_ah_ys"` // 原审案号
|
||||
Nqsbdje int `json:"n_qsbdje"` // 起诉标的金额
|
||||
NjaayTree string `json:"n_jaay_tree"` // 结案案由详细
|
||||
Najlx string `json:"n_ajlx"` // 案件类型
|
||||
CID string `json:"c_id"` // 案件唯一ID
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
}
|
||||
|
||||
// Criminal 刑事案件
|
||||
type Criminal struct {
|
||||
Cases []CriminalCase `json:"cases"` // 案件
|
||||
Count Count `json:"count"` // 统计
|
||||
}
|
||||
|
||||
// CriminalCase 刑事案件项
|
||||
type CriminalCase struct {
|
||||
CgkwsDsr string `json:"c_gkws_dsr"` // 当事人
|
||||
NpcpcjeLevel int `json:"n_pcpcje_level"` // 判处赔偿金额等级
|
||||
Nbqqpcje int `json:"n_bqqpcje"` // 被请求赔偿金额
|
||||
NpcpcjeGjLevel int `json:"n_pcpcje_gj_level"` // 判处赔偿金额估计等级
|
||||
Dlarq string `json:"d_larq"` // 立案时间
|
||||
Djarq string `json:"d_jarq"` // 结案时间
|
||||
CahHx string `json:"c_ah_hx"` // 后续案号
|
||||
Njafs string `json:"n_jafs"` // 结案方式
|
||||
NjaayTag string `json:"n_jaay_tag"` // 结案案由标签
|
||||
Njbfy string `json:"n_jbfy"` // 经办法院
|
||||
NlaayTag string `json:"n_laay_tag"` // 立案案由标签
|
||||
Ndzzm string `json:"n_dzzm"` // 定罪罪名
|
||||
NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级
|
||||
NlaayTree string `json:"n_laay_tree"` // 立案案由详细
|
||||
NccxzxjeLevel int `json:"n_ccxzxje_level"` // 财产刑执行金额等级
|
||||
Ncrc int `json:"n_crc"` // 案件变更码
|
||||
Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人
|
||||
NccxzxjeGjLevel int `json:"n_ccxzxje_gj_level"` // 财产刑执行金额估计等级
|
||||
Nfzje int `json:"n_fzje"` // 犯罪金额
|
||||
CgkwsID string `json:"c_gkws_id"` // 公开文书ID
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
Cssdy string `json:"c_ssdy"` // 所属地域
|
||||
Npcpcje int `json:"n_pcpcje"` // 判处赔偿金额
|
||||
CahYs string `json:"c_ah_ys"` // 原审案号
|
||||
Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段
|
||||
CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号
|
||||
CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果
|
||||
Cslfsxx string `json:"c_slfsxx"` // 审理方式信息
|
||||
NpcpcjeGj int `json:"n_pcpcje_gj"` // 判处赔偿金额估计
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
Nlaay string `json:"n_laay"` // 立案案由
|
||||
Njaay string `json:"n_jaay"` // 结案案由
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
NdzzmTree string `json:"n_dzzm_tree"` // 定罪罪名树
|
||||
NjaayTree string `json:"n_jaay_tree"` // 结案案由详细
|
||||
Npcjg string `json:"n_pcjg"` // 判处结果
|
||||
CID string `json:"c_id"` // 案件唯一ID
|
||||
NssdwYs string `json:"n_ssdw_ys"` // 一审诉讼地位
|
||||
Nccxzxje int `json:"n_ccxzxje"` // 财产刑执行金额
|
||||
NfzjeLevel int `json:"n_fzje_level"` // 犯罪金额等级
|
||||
Nslcx string `json:"n_slcx"` // 审理程序
|
||||
Najlx string `json:"n_ajlx"` // 案件类型
|
||||
NbqqpcjeLevel int `json:"n_bqqpcje_level"` // 被请求赔偿金额等级
|
||||
NccxzxjeGj int `json:"n_ccxzxje_gj"` // 财产刑执行金额估计
|
||||
}
|
||||
|
||||
// CasesTree 串联树
|
||||
type CasesTree struct {
|
||||
Administrative []CasesTreeItem `json:"administrative"` // 行政案件
|
||||
Criminal []CasesTreeItem `json:"criminal"` // 刑事案件
|
||||
Civil []CasesTreeItem `json:"civil"` // 民事案件
|
||||
}
|
||||
|
||||
// CasesTreeItem 串联树项
|
||||
type CasesTreeItem struct {
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
CaseType int `json:"case_type"` // 案件类型
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
StageType int `json:"stage_type"` // 审理阶段类型
|
||||
Next *CasesTreeItem `json:"next"` // 下一个案件
|
||||
}
|
||||
|
||||
// Bankrupt 强制清算与破产案件
|
||||
type Bankrupt struct {
|
||||
Cases []BankruptCase `json:"cases"` // 案件
|
||||
Count Count `json:"count"` // 统计
|
||||
}
|
||||
|
||||
// BankruptCase 强制清算与破产案件项
|
||||
type BankruptCase struct {
|
||||
Cdsrxx []Dsrxx `json:"c_dsrxx"` // 当事人
|
||||
CgkwsID string `json:"c_gkws_id"` // 公开文书ID
|
||||
Najbs string `json:"n_ajbs"` // 案件标识
|
||||
NjbfyCj string `json:"n_jbfy_cj"` // 法院所属层级
|
||||
CgkwsDsr string `json:"c_gkws_dsr"` // 当事人
|
||||
CID string `json:"c_id"` // 案件唯一ID
|
||||
Dlarq string `json:"d_larq"` // 立案时间
|
||||
Djarq string `json:"d_jarq"` // 结案时间
|
||||
Najlx string `json:"n_ajlx"` // 案件类型
|
||||
CgkwsGlah string `json:"c_gkws_glah"` // 相关案件号
|
||||
Njbfy string `json:"n_jbfy"` // 经办法院
|
||||
Najjzjd string `json:"n_ajjzjd"` // 案件进展阶段
|
||||
CgkwsPjjg string `json:"c_gkws_pjjg"` // 判决结果
|
||||
Cssdy string `json:"c_ssdy"` // 所属地域
|
||||
Ncrc int `json:"n_crc"` // 案件变更码
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
Njafs string `json:"n_jafs"` // 结案方式
|
||||
Cah string `json:"c_ah"` // 案号
|
||||
}
|
||||
|
||||
// Dsrxx 当事人
|
||||
type Dsrxx struct {
|
||||
Nssdw string `json:"n_ssdw"` // 诉讼地位
|
||||
CMc string `json:"c_mc"` // 名称
|
||||
Ndsrlx string `json:"n_dsrlx"` // 当事人类型
|
||||
}
|
||||
|
||||
// Count 统计
|
||||
type Count struct {
|
||||
MoneyYuangao int `json:"money_yuangao"` // 原告金额
|
||||
AreaStat string `json:"area_stat"` // 涉案地点分布
|
||||
CountJieBeigao int `json:"count_jie_beigao"` // 被告已结案总数
|
||||
CountTotal int `json:"count_total"` // 案件总数
|
||||
MoneyWeiYuangao int `json:"money_wei_yuangao"` // 原告未结案金额
|
||||
CountWeiTotal int `json:"count_wei_total"` // 未结案总数
|
||||
MoneyWeiBeigao int `json:"money_wei_beigao"` // 被告未结案金额
|
||||
CountOther int `json:"count_other"` // 第三人总数
|
||||
MoneyBeigao int `json:"money_beigao"` // 被告金额
|
||||
CountYuangao int `json:"count_yuangao"` // 原告总数
|
||||
MoneyJieOther int `json:"money_jie_other"` // 第三人已结案金额
|
||||
MoneyTotal int `json:"money_total"` // 涉案总金额
|
||||
MoneyWeiTotal int `json:"money_wei_total"` // 未结案金额
|
||||
CountWeiYuangao int `json:"count_wei_yuangao"` // 原告未结案总数
|
||||
AyStat string `json:"ay_stat"` // 涉案案由分布
|
||||
CountBeigao int `json:"count_beigao"` // 被告总数
|
||||
MoneyJieYuangao int `json:"money_jie_yuangao"` // 原告已结金额
|
||||
JafsStat string `json:"jafs_stat"` // 结案方式分布
|
||||
MoneyJieBeigao int `json:"money_jie_beigao"` // 被告已结案金额
|
||||
CountWeiBeigao int `json:"count_wei_beigao"` // 被告未结案总数
|
||||
CountJieOther int `json:"count_jie_other"` // 第三人已结案总数
|
||||
CountJieTotal int `json:"count_jie_total"` // 已结案总数
|
||||
CountWeiOther int `json:"count_wei_other"` // 第三人未结案总数
|
||||
MoneyOther int `json:"money_other"` // 第三人金额
|
||||
CountJieYuangao int `json:"count_jie_yuangao"` // 原告已结案总数
|
||||
MoneyJieTotal int `json:"money_jie_total"` // 已结案金额
|
||||
MoneyWeiOther int `json:"money_wei_other"` // 第三人未结案金额
|
||||
MoneyWeiPercent float64 `json:"money_wei_percent"` // 未结案金额百分比
|
||||
LarqStat string `json:"larq_stat"` // 涉案时间分布
|
||||
}
|
||||
|
||||
// Xgbzxr 限高被执行人
|
||||
type Xgbzxr struct {
|
||||
Msg string `json:"msg"` // 备注信息
|
||||
Data XgbzxrData `json:"data"` // 数据结果
|
||||
}
|
||||
|
||||
// XgbzxrData 限高被执行人数据
|
||||
type XgbzxrData struct {
|
||||
Xgbzxr []XgbzxrItem `json:"xgbzxr"` // 限高被执行人列表
|
||||
}
|
||||
|
||||
// XgbzxrItem 限高被执行人项
|
||||
type XgbzxrItem struct {
|
||||
Ah string `json:"ah"` // 案号
|
||||
ID string `json:"id"` // 标识
|
||||
Zxfy string `json:"zxfy"` // 执行法院
|
||||
Fbrq string `json:"fbrq"` // 发布时间
|
||||
}
|
||||
|
||||
// ParseWestResponse 解析西部返回的响应数据(获取data字段后解析)
|
||||
// westResp: 西部返回的原始响应
|
||||
// Returns: 解析后的数据字节数组
|
||||
func ParseWestResponse(westResp []byte) ([]byte, error) {
|
||||
dataResult := gjson.GetBytes(westResp, "data")
|
||||
if !dataResult.Exists() {
|
||||
return nil, errors.New("data not found")
|
||||
}
|
||||
return ParseJsonResponse([]byte(dataResult.Raw))
|
||||
}
|
||||
|
||||
// ParseJsonResponse 直接解析JSON响应数据
|
||||
// jsonResp: JSON响应数据
|
||||
// Returns: 解析后的数据字节数组
|
||||
func ParseJsonResponse(jsonResp []byte) ([]byte, error) {
|
||||
parseResult, err := RecursiveParse(string(jsonResp))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultResp, marshalErr := json.Marshal(parseResult)
|
||||
if marshalErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resultResp, nil
|
||||
}
|
||||
|
||||
// RecursiveParse 递归解析JSON数据
|
||||
func RecursiveParse(data interface{}) (interface{}, error) {
|
||||
switch v := data.(type) {
|
||||
case string:
|
||||
var parsed interface{}
|
||||
if err := json.Unmarshal([]byte(v), &parsed); err == nil {
|
||||
return RecursiveParse(parsed)
|
||||
}
|
||||
return v, nil
|
||||
case map[string]interface{}:
|
||||
for key, val := range v {
|
||||
parsed, err := RecursiveParse(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v[key] = parsed
|
||||
}
|
||||
return v, nil
|
||||
case []interface{}:
|
||||
for i, item := range v {
|
||||
parsed, err := RecursiveParse(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
v[i] = parsed
|
||||
}
|
||||
return v, nil
|
||||
default:
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG162ARequest FLXG162A API处理方法
|
||||
func ProcessFLXG162ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG162AReq
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id": encryptedIDCard,
|
||||
"cell": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G32BJ05", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXG2E8FRequest FLXG2E8F API处理方法 - 司法核验报告
|
||||
func ProcessFLXG2E8FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG2E8FReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"accessoryUrl": paramsDto.AuthorizationURL,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI101", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXG3A9BRequest FLXG3A9B API处理方法 - 法院被执行人限高版
|
||||
func ProcessFLXG3A9BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG3A9BReq
|
||||
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)
|
||||
}
|
||||
if paramsDto.IDCard == "410482198504029333" {
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI045", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG3D56Request FLXG3D56 API处理方法
|
||||
func ProcessFLXG3D56Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG3D56Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id": encryptedIDCard,
|
||||
"cell": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
// 只有当 TimeRange 不为空时才加密和传参
|
||||
if paramsDto.TimeRange != "" {
|
||||
encryptedTimeRange, err := deps.WestDexService.Encrypt(paramsDto.TimeRange)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData["data"].(map[string]interface{})["time_range"] = encryptedTimeRange
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G26BJ05", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG54F5Request FLXG54F5 API处理方法
|
||||
func ProcessFLXG54F5Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG54F5Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"mobile": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx,"G03HZ01", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG5876Request FLXG5876 易诉人识别API处理方法
|
||||
func ProcessFLXG5876Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG5876Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"phone": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G03XM02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXG5A3BRequest FLXG5A3B API处理方法 - 个人司法涉诉
|
||||
func ProcessFLXG5A3BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG5A3BReq
|
||||
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)
|
||||
}
|
||||
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" {
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI006", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// ProcessFLXG5B2ERequest FLXG5B2E API处理方法
|
||||
func ProcessFLXG5B2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG5B2EReq
|
||||
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)
|
||||
}
|
||||
if deps.CallContext.ContractCode == "" {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空"))
|
||||
}
|
||||
encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idcard": encryptedIDCard,
|
||||
"auth_authorizeFileCode": encryptedAuthAuthorizeFileCode,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G36SC01", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
// 如果有返回内容,优先解析返回内容
|
||||
if respBytes != nil {
|
||||
parsed, parseErr := ParseJsonResponse(respBytes)
|
||||
if parseErr == nil {
|
||||
// 通过gjson获取指定路径的数据
|
||||
contentResult := gjson.GetBytes(parsed, "G36SC0101.G36SC0102.content")
|
||||
if contentResult.Exists() {
|
||||
return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
return parsed, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
// 解析失败,返回原始内容和系统错误
|
||||
return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr)
|
||||
}
|
||||
// 没有返回内容,直接返回数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse
|
||||
parsed, parseErr := ParseJsonResponse(respBytes)
|
||||
if parseErr != nil {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr)
|
||||
}
|
||||
|
||||
// 通过gjson获取指定路径的数据
|
||||
contentResult := gjson.GetBytes(parsed, "G36SC0101.G36SC0102.content")
|
||||
if contentResult.Exists() {
|
||||
return []byte(contentResult.Raw), nil
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG75FERequest FLXG75FE API处理方法
|
||||
func ProcessFLXG75FERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG75FEReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
"mobile": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx,"FLXG75FE", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessFLXG7E8FRequest FLXG7E8F API处理方法 - 个人司法数据查询
|
||||
func ProcessFLXG7E8FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG7E8FReq
|
||||
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)
|
||||
}
|
||||
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" {
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
// 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
"phoneNumber": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1101695378264092672"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// ProcessFLXG8A3FRequest FLXG8A3F API处理方法
|
||||
func ProcessFLXG8A3FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG8A3FReq
|
||||
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)
|
||||
}
|
||||
if deps.CallContext.ContractCode == "" {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, errors.New("合同编号不能为空"))
|
||||
}
|
||||
encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(deps.CallContext.ContractCode)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idcard": encryptedIDCard,
|
||||
"auth_authorizeFileCode": encryptedAuthAuthorizeFileCode,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G37SC01", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
// 如果有返回内容,优先解析返回内容
|
||||
if respBytes != nil {
|
||||
parsed, parseErr := ParseJsonResponse(respBytes)
|
||||
if parseErr == nil {
|
||||
// 通过gjson获取指定路径的数据
|
||||
contentResult := gjson.GetBytes(parsed, "G37SC0101.G37SC0102.content")
|
||||
if contentResult.Exists() {
|
||||
return []byte(contentResult.Raw), errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
return parsed, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
// 解析失败,返回原始内容和系统错误
|
||||
return respBytes, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr)
|
||||
}
|
||||
// 没有返回内容,直接返回数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
// 正常返回 - 不管有没有deps.Options.Json都进行ParseJsonResponse
|
||||
parsed, parseErr := ParseJsonResponse(respBytes)
|
||||
if parseErr != nil {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, parseErr)
|
||||
}
|
||||
|
||||
// 通过gjson获取指定路径的数据
|
||||
contentResult := gjson.GetBytes(parsed, "G37SC0101.G37SC0102.content")
|
||||
if contentResult.Exists() {
|
||||
return []byte(contentResult.Raw), nil
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXG8B4DRequest FLXG8B4D API处理方法 - 涉赌涉诈风险评估
|
||||
func ProcessFLXG8B4DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG8B4DReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 三选一校验:MobileNo、IDCard、BankCard 必须且只能有一个
|
||||
var fieldCount int
|
||||
var selectedField string
|
||||
var selectedValue string
|
||||
|
||||
if paramsDto.MobileNo != "" {
|
||||
fieldCount++
|
||||
selectedField = "mobile_no"
|
||||
selectedValue = paramsDto.MobileNo
|
||||
}
|
||||
if paramsDto.IDCard != "" {
|
||||
fieldCount++
|
||||
selectedField = "id_card"
|
||||
selectedValue = paramsDto.IDCard
|
||||
}
|
||||
if paramsDto.BankCard != "" {
|
||||
fieldCount++
|
||||
selectedField = "bank_card"
|
||||
selectedValue = paramsDto.BankCard
|
||||
}
|
||||
|
||||
if fieldCount == 0 {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("必须提供手机号、身份证号或银行卡号中的其中一个"))
|
||||
}
|
||||
if fieldCount > 1 {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, errors.New("只能提供手机号、身份证号或银行卡号中的一个,不能同时提供多个"))
|
||||
}
|
||||
|
||||
// 只对选中的字段进行加密
|
||||
var encryptedValue string
|
||||
var err error
|
||||
switch selectedField {
|
||||
case "mobile_no":
|
||||
encryptedValue, err = deps.ZhichaService.Encrypt(selectedValue)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
case "id_card":
|
||||
encryptedValue, err = deps.ZhichaService.Encrypt(selectedValue)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
case "bank_card":
|
||||
encryptedValue, err = deps.ZhichaService.Encrypt(selectedValue)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 构建请求数据,根据选中的字段类型设置对应的参数
|
||||
reqData := map[string]interface{}{
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
switch selectedField {
|
||||
case "mobile_no":
|
||||
reqData["phone"] = encryptedValue
|
||||
case "id_card":
|
||||
reqData["idCard"] = encryptedValue
|
||||
case "bank_card":
|
||||
reqData["name"] = encryptedValue
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI027", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG9687Request FLXG9687 API处理方法
|
||||
func ProcessFLXG9687Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG9687Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id": encryptedIDCard,
|
||||
"cell": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G31BJ05", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXG970FRequest FLXG970F 风险人员核验API处理方法
|
||||
func ProcessFLXG970FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG970FReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"cardNo": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "WEST00028", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXG9C1DRequest FLXG9C1D API处理方法 - 法院信息详情高级版
|
||||
func ProcessFLXG9C1DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG9C1DReq
|
||||
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)
|
||||
}
|
||||
if paramsDto.IDCard == "410482198504029333" {
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI007", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/yushan"
|
||||
)
|
||||
|
||||
// ProcessFLXGBC21Request FLXGbc21 API处理方法
|
||||
func ProcessFLXGBC21Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGBC21Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"mobile": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
respBytes, err := deps.YushanService.CallAPI(ctx, "MOB032", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, yushan.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXGC9D1Request FLXGC9D1 API处理方法
|
||||
func ProcessFLXGC9D1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGC9D1Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id": encryptedIDCard,
|
||||
"cell": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G30BJ05", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXGCA3DRequest FLXGCA3D API处理方法
|
||||
func ProcessFLXGCA3DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGCA3DReq
|
||||
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)
|
||||
}
|
||||
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" {
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id_card": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G22BJ03", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
if respBytes != nil {
|
||||
return respBytes, nil
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXGDEA8Request FLXGDEA8 API处理方法
|
||||
func ProcessFLXGDEA8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGDEA8Req
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI028", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXGDEA9Request FLXGDEA9 API处理方法
|
||||
func ProcessFLXGDEA9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGDEA9Req
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" {
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI005", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessFLXGDEC7Request FLXGDEC7 API处理方法
|
||||
func ProcessFLXGDEC7Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGDEC7Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"id_card": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G23BJ03", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
)
|
||||
|
||||
// ProcessFLXGDJG3Request FLXGDJG3 董监高司法综合信息核验 API 处理方法(使用数据宝服务示例)
|
||||
func ProcessFLXGDJG3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGDJG3Req
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建数据宝入参(sign 外的业务参数可按需 AES 加密后作为 bodyData)
|
||||
reqParams := map[string]interface{}{
|
||||
"key": "1cce582f0a6f3ca40de80f1bea9b9698",
|
||||
"idcard": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197
|
||||
apiPath := "/communication/personal/10166"
|
||||
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
|
||||
if err != nil {
|
||||
if errors.Is(err, shujubao.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, shujubao.ErrQueryEmpty) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 解析响应中的 JSON 字符串(使用 qyglb4c0 中的 RecursiveParse)
|
||||
parsedResp, err := RecursiveParse(data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
respBytes, err := json.Marshal(parsedResp)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXGK5D2Request FLXGK5D2 API处理方法 - 法院被执行人高级版
|
||||
func ProcessFLXGK5D2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXGK5D2Req
|
||||
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)
|
||||
}
|
||||
if paramsDto.IDCard == "410482198504029333" {
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI046", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ0B03Request IVYZ0B03 API处理方法
|
||||
func ProcessIVYZ0B03Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ0B03Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"phone": encryptedMobileNo,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G17BJ02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/jiguang"
|
||||
)
|
||||
|
||||
// ProcessIVYZ0S0DRequest IVYZ0S0D API处理方法 - 劳动仲裁信息查询(个人版)
|
||||
func ProcessIVYZ0S0DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ0S0DReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求参数
|
||||
reqData := map[string]interface{}{
|
||||
"id": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 调用极光API
|
||||
respBytes, err := deps.JiguangService.CallAPI(ctx, "labor-arbitration-information", "labor-arbitration-information", reqData)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 极光服务已经返回了 data 字段的 JSON,直接返回即可
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
)
|
||||
|
||||
// ProcessIVYZ18HYRequest IVYZ18HY 婚姻状况核验V2(单人) API 处理方法(使用数据宝服务示例)
|
||||
func ProcessIVYZ18HYRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ18HYReq
|
||||
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)
|
||||
}
|
||||
|
||||
fixedData := map[string]interface{}{"msg": "请联系商务咨询"}
|
||||
fixedRespBytes, err := json.Marshal(fixedData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return fixedRespBytes, nil
|
||||
|
||||
authDate := ""
|
||||
if len(paramsDto.AuthDate) >= 8 {
|
||||
authDate = paramsDto.AuthDate[len(paramsDto.AuthDate)-8:]
|
||||
}
|
||||
reqParams := map[string]interface{}{
|
||||
"key": "",
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
"maritalType": paramsDto.MaritalType,
|
||||
"authcode": paramsDto.AuthAuthorizeFileBase64,
|
||||
"authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode,
|
||||
"authDate": authDate,
|
||||
}
|
||||
|
||||
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197
|
||||
apiPath := "/communication/personal/10333"
|
||||
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
|
||||
if err != nil {
|
||||
|
||||
if errors.Is(err, shujubao.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, shujubao.ErrQueryEmpty) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
respBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ1C9DRequest IVYZ1C9D API处理方法
|
||||
func ProcessIVYZ1C9DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ1C9DReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"xm": encryptedName,
|
||||
"sfzh": encryptedIDCard,
|
||||
"yearNum": paramsDto.Years,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G38SC02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/jiguang"
|
||||
)
|
||||
|
||||
// ProcessIVYZ1J7HRequest IVYZ1J7H API处理方法 - 行驶证核查v2
|
||||
func ProcessIVYZ1J7HRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ1J7HReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求参数
|
||||
reqData := map[string]interface{}{
|
||||
"plate": paramsDto.PlateNo,
|
||||
"plateType": paramsDto.CarPlateType,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 调用极光API
|
||||
respBytes, err := deps.JiguangService.CallAPI(ctx, "vehicle-driving-license-v2", "vehicle/driving-license-v2", reqData)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 极光服务已经返回了 data 字段的 JSON,直接返回即可
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
)
|
||||
|
||||
// ProcessIVYZ2125Request IVYZ2125 API处理方法
|
||||
func ProcessIVYZ2125Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("服务已停用"))
|
||||
// var paramsDto dto.IVYZ2125Req
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// reqData := map[string]interface{}{
|
||||
// "name": paramsDto.Name,
|
||||
// "idCard": paramsDto.IDCard,
|
||||
// "mobile": paramsDto.Mobile,
|
||||
// }
|
||||
|
||||
// respBytes, err := deps.WestDexService.CallAPI(ctx, "IVYZ2125", reqData)
|
||||
// if err != nil {
|
||||
// if errors.Is(err, westdex.ErrDatasource) {
|
||||
// return nil, errors.Join(processors.ErrDatasource, err)
|
||||
// } else {
|
||||
// return nil, errors.Join(processors.ErrSystem, err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
)
|
||||
|
||||
// ProcessIVYZ28HYRequest IVYZ28HY 婚姻状况核验单人) API 处理方法(使用数据宝服务示例)
|
||||
func ProcessIVYZ28HYRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ28HYReq
|
||||
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)
|
||||
}
|
||||
|
||||
fixedData := map[string]interface{}{"msg": "请联系商务咨询"}
|
||||
fixedRespBytes, err := json.Marshal(fixedData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return fixedRespBytes, nil
|
||||
|
||||
reqParams := map[string]interface{}{
|
||||
"key": "",
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197
|
||||
apiPath := "/communication/personal/10149"
|
||||
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
|
||||
if err != nil {
|
||||
if errors.Is(err, shujubao.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, shujubao.ErrQueryEmpty) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
respBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ivyz2a8bShumaiResp 数脉 /v4/id_card/check 返回格式
|
||||
type ivyz2a8bShumaiResp struct {
|
||||
Result float64 `json:"result"`
|
||||
OrderNo string `json:"order_no"`
|
||||
Desc string `json:"desc"`
|
||||
Sex string `json:"sex"`
|
||||
Birthday string `json:"birthday"` // yyyyMMdd
|
||||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
// ProcessIVYZ2A8BRequest IVYZ2A8B API处理方法 - 身份二要素认证政务版 数脉内部替换
|
||||
func ProcessIVYZ2A8BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ2A8BReq
|
||||
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)
|
||||
}
|
||||
reqFormData := map[string]interface{}{
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx)
|
||||
|
||||
// 先尝试使用政务接口(app_id2 和 app_secret2)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true)
|
||||
if err != nil {
|
||||
// 使用实时接口(app_id 和 app_secret)重试
|
||||
respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
|
||||
// 如果重试后仍然失败,或者原本就是查无记录错误,返回错误
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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 {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将数脉返回的新格式映射为原有 API 输出格式
|
||||
oldFormat, err := mapIVYZ2A8BShumaiToOld(respBytes)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return json.Marshal(oldFormat)
|
||||
}
|
||||
|
||||
func mapIVYZ2A8BShumaiToOld(respBytes []byte) (map[string]interface{}, error) {
|
||||
var r ivyz2a8bShumaiResp
|
||||
if err := json.Unmarshal(respBytes, &r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// final_auth_result: "0"=一致,"1"=不一致/无记录;按 result:0-一致,1-不一致,2-无记录(预留)
|
||||
finalAuth := "1"
|
||||
switch int(r.Result) {
|
||||
case 0:
|
||||
finalAuth = "0"
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"final_auth_result": finalAuth,
|
||||
"birthday": formatBirthdayOld(r.Birthday),
|
||||
"address": r.Address,
|
||||
"constellation": constellationFromBirthday(r.Birthday),
|
||||
"gender": r.Sex,
|
||||
"age": ageFromBirthday(r.Birthday),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func formatBirthdayOld(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if len(s) != 8 {
|
||||
return s
|
||||
}
|
||||
for _, c := range s {
|
||||
if c < '0' || c > '9' {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return s[0:4] + "年" + s[4:6] + "月" + s[6:8] + "日"
|
||||
}
|
||||
|
||||
func constellationFromBirthday(s string) string {
|
||||
if len(s) != 8 {
|
||||
return ""
|
||||
}
|
||||
month, _ := strconv.Atoi(s[4:6])
|
||||
day, _ := strconv.Atoi(s[6:8])
|
||||
if month < 1 || month > 12 || day < 1 || day > 31 {
|
||||
return ""
|
||||
}
|
||||
switch {
|
||||
case (month == 12 && day >= 22) || (month == 1 && day <= 19):
|
||||
return "魔羯座"
|
||||
case (month == 1 && day >= 20) || (month == 2 && day <= 18):
|
||||
return "水瓶座"
|
||||
case (month == 2 && day >= 19) || (month == 3 && day <= 20):
|
||||
return "双鱼座"
|
||||
case (month == 3 && day >= 21) || (month == 4 && day <= 19):
|
||||
return "白羊座"
|
||||
case (month == 4 && day >= 20) || (month == 5 && day <= 20):
|
||||
return "金牛座"
|
||||
case (month == 5 && day >= 21) || (month == 6 && day <= 21):
|
||||
return "双子座"
|
||||
case (month == 6 && day >= 22) || (month == 7 && day <= 22):
|
||||
return "巨蟹座"
|
||||
case (month == 7 && day >= 23) || (month == 8 && day <= 22):
|
||||
return "狮子座"
|
||||
case (month == 8 && day >= 23) || (month == 9 && day <= 22):
|
||||
return "处女座"
|
||||
case (month == 9 && day >= 23) || (month == 10 && day <= 23):
|
||||
return "天秤座"
|
||||
case (month == 10 && day >= 24) || (month == 11 && day <= 22):
|
||||
return "天蝎座"
|
||||
case (month == 11 && day >= 23) || (month == 12 && day <= 21):
|
||||
return "射手座"
|
||||
default:
|
||||
return "魔羯座"
|
||||
}
|
||||
}
|
||||
|
||||
func ageFromBirthday(s string) string {
|
||||
if len(s) < 4 {
|
||||
return ""
|
||||
}
|
||||
y, err := strconv.Atoi(s[0:4])
|
||||
if err != nil || y <= 0 {
|
||||
return ""
|
||||
}
|
||||
age := time.Now().Year() - y
|
||||
if age < 0 {
|
||||
age = 0
|
||||
}
|
||||
return strconv.Itoa(age)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ2B2TRequest IVYZ2B2T API处理方法 能力资质核验(学历)
|
||||
func ProcessIVYZ2B2TRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
|
||||
var paramsDto dto.IVYZ2B2TReq
|
||||
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)
|
||||
}
|
||||
encryptedQueryReasonId, err := deps.WestDexService.Encrypt(strconv.FormatInt(paramsDto.QueryReasonId, 10))
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"idCard": encryptedIDCard,
|
||||
"name": encryptedName,
|
||||
"queryReasonId": encryptedQueryReasonId,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G11JX01", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ2C1PRequest IVYZ2C1P API处理方法 - 风控黑名单
|
||||
func ProcessIVYZ2C1PRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ2C1PReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI037", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ2MN6Request IVYZ2MN6 API处理方法
|
||||
func ProcessIVYZ2MN6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ2MN6Req
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI1004", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ385ERequest IVYZ385E API处理方法
|
||||
func ProcessIVYZ385ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ385EReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"xm": encryptedName,
|
||||
"gmsfzhm": encryptedIDCard,
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "WEST00020", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
)
|
||||
|
||||
// ProcessIVYZ38SRRequest IVYZ38SR 婚姻状态核验(双人) API 处理方法(使用数据宝服务示例)
|
||||
func ProcessIVYZ38SRRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ38SRReq
|
||||
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)
|
||||
}
|
||||
|
||||
fixedData := map[string]interface{}{"msg": "请联系商务咨询"}
|
||||
fixedRespBytes, err := json.Marshal(fixedData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return fixedRespBytes, nil
|
||||
|
||||
reqParams := map[string]interface{}{
|
||||
"key": "",
|
||||
"name": paramsDto.ManName,
|
||||
"idcard": paramsDto.ManIDCard,
|
||||
"woman_name": paramsDto.WomanName,
|
||||
"woman_idcard": paramsDto.WomanIDCard,
|
||||
}
|
||||
|
||||
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197
|
||||
apiPath := "/communication/personal/10148"
|
||||
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
|
||||
if err != nil {
|
||||
if errors.Is(err, shujubao.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, shujubao.ErrQueryEmpty) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
respBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZ3A7FRequest IVYZ3A7F API处理方法 - 行为数据查询
|
||||
func ProcessIVYZ3A7FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ3A7FReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,使用xingwei服务的正确字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1104648854749245440"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
// 查空情况,返回特定的查空错误
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
// 数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
// 系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/muzi"
|
||||
)
|
||||
|
||||
// ProcessIVYZ3P9MRequest IVYZ3P9M API处理方法 - 学历查询实时版
|
||||
func ProcessIVYZ3P9MRequest_2(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ3P9MReq
|
||||
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.MuziService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedCertCode, err := deps.MuziService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 处理 returnType 参数,默认为 "1"
|
||||
returnType := paramsDto.ReturnType
|
||||
if returnType == "" {
|
||||
returnType = "1"
|
||||
}
|
||||
paramSign := map[string]interface{}{
|
||||
"returnType": returnType,
|
||||
"realName": encryptedName,
|
||||
"certCode": encryptedCertCode,
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"realName": encryptedName,
|
||||
"certCode": encryptedCertCode,
|
||||
"returnType": returnType,
|
||||
}
|
||||
|
||||
respData, err := deps.MuziService.CallAPI(ctx, "PC0041", "/academic", reqData, paramSign)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, muzi.ErrDatasource):
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
case errors.Is(err, muzi.ErrSystem):
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
default:
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respData, nil
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ3P9MRequest IVYZ3P9M API处理方法 - 学历查询实时版
|
||||
func ProcessIVYZ3P9MRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ3P9MReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": "1",
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI1004", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
out, err := mapZCI1004ToIVYZ3P9M(respData, paramsDto.Name, paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
type zci1004Item struct {
|
||||
EndDate string `json:"endDate"`
|
||||
EducationLevel string `json:"educationLevel"`
|
||||
LearningForm string `json:"learningForm"`
|
||||
}
|
||||
|
||||
type ivyz3p9mItem struct {
|
||||
GraduationDate string `json:"graduationDate"`
|
||||
StudentName string `json:"studentName"`
|
||||
EducationLevel string `json:"educationLevel"`
|
||||
LearningForm string `json:"learningForm"`
|
||||
IDNumber string `json:"idNumber"`
|
||||
}
|
||||
|
||||
func mapZCI1004ToIVYZ3P9M(respData interface{}, name, idCard string) ([]ivyz3p9mItem, error) {
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var source []zci1004Item
|
||||
if err := json.Unmarshal(respBytes, &source); err != nil {
|
||||
var wrapped struct {
|
||||
Data []zci1004Item `json:"data"`
|
||||
}
|
||||
if err2 := json.Unmarshal(respBytes, &wrapped); err2 != nil {
|
||||
return nil, err
|
||||
}
|
||||
source = wrapped.Data
|
||||
}
|
||||
|
||||
out := make([]ivyz3p9mItem, 0, len(source))
|
||||
for _, it := range source {
|
||||
out = append(out, ivyz3p9mItem{
|
||||
GraduationDate: normalizeDateDigits(it.EndDate),
|
||||
StudentName: name,
|
||||
EducationLevel: mapEducationLevelToCode(it.EducationLevel),
|
||||
LearningForm: mapLearningFormToCode(it.LearningForm),
|
||||
IDNumber: idCard,
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func mapEducationLevelToCode(level string) string {
|
||||
v := normalizeText(level)
|
||||
switch {
|
||||
case strings.Contains(v, "第二学士"):
|
||||
return "5"
|
||||
case strings.Contains(v, "博士"):
|
||||
return "4"
|
||||
case strings.Contains(v, "硕士"):
|
||||
return "3"
|
||||
case strings.Contains(v, "本科"):
|
||||
return "2"
|
||||
case strings.Contains(v, "专科"), strings.Contains(v, "大专"):
|
||||
return "1"
|
||||
default:
|
||||
return "99"
|
||||
}
|
||||
}
|
||||
|
||||
func mapLearningFormToCode(form string) string {
|
||||
v := normalizeText(form)
|
||||
switch {
|
||||
case strings.Contains(v, "脱产"):
|
||||
return "1"
|
||||
case strings.Contains(v, "普通全日制"):
|
||||
return "2"
|
||||
case strings.Contains(v, "全日制"):
|
||||
return "3"
|
||||
case strings.Contains(v, "开放教育"), strings.Contains(v, "开放大学"):
|
||||
return "4"
|
||||
case strings.Contains(v, "夜大学"), strings.Contains(v, "夜大"):
|
||||
return "5"
|
||||
case strings.Contains(v, "函授"):
|
||||
return "6"
|
||||
case strings.Contains(v, "网络教育"), strings.Contains(v, "网教"), strings.Contains(v, "远程教育"):
|
||||
return "7"
|
||||
case strings.Contains(v, "非全日制"):
|
||||
return "8"
|
||||
case strings.Contains(v, "业余"):
|
||||
return "9"
|
||||
case strings.Contains(v, "自学考试"), strings.Contains(v, "自考"):
|
||||
// 自考在既有枚举中无直对应,兼容并入“业余”
|
||||
return "9"
|
||||
default:
|
||||
return "99"
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeDateDigits(s string) string {
|
||||
trimmed := strings.TrimSpace(s)
|
||||
if trimmed == "" {
|
||||
return ""
|
||||
}
|
||||
var b strings.Builder
|
||||
for _, ch := range trimmed {
|
||||
if ch >= '0' && ch <= '9' {
|
||||
b.WriteRune(ch)
|
||||
}
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func normalizeText(s string) string {
|
||||
v := strings.TrimSpace(strings.ToLower(s))
|
||||
v = strings.ReplaceAll(v, " ", "")
|
||||
v = strings.ReplaceAll(v, "-", "")
|
||||
v = strings.ReplaceAll(v, "_", "")
|
||||
return v
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
)
|
||||
|
||||
// ProcessIVYZ48SRRequest IVYZ48SR 婚姻状态核验V2(双人) API 处理方法(使用数据宝服务示例)
|
||||
func ProcessIVYZ48SRRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ48SRReq
|
||||
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)
|
||||
}
|
||||
|
||||
fixedData := map[string]interface{}{"msg": "请联系商务咨询"}
|
||||
fixedRespBytes, err := json.Marshal(fixedData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return fixedRespBytes, nil
|
||||
|
||||
reqParams := map[string]interface{}{
|
||||
"key": "",
|
||||
"name": paramsDto.ManName,
|
||||
"idcard": paramsDto.ManIDCard,
|
||||
"woman_name": paramsDto.WomanName,
|
||||
"woman_idcard": paramsDto.WomanIDCard,
|
||||
"marital_type": paramsDto.MaritalType,
|
||||
"auth_authorize_file_code": paramsDto.AuthAuthorizeFileCode,
|
||||
}
|
||||
|
||||
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197
|
||||
apiPath := "/communication/personal/10332"
|
||||
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
|
||||
if err != nil {
|
||||
if errors.Is(err, shujubao.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, shujubao.ErrQueryEmpty) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
respBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// ProcessIVYZ4E8BRequest IVYZ4E8B API处理方法
|
||||
func ProcessIVYZ4E8BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ4E8BReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idNo": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G09GZ02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 解析响应,提取data字段中的hyzk
|
||||
var respMap map[string]interface{}
|
||||
if err := json.Unmarshal(respBytes, &respMap); err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
dataStr, ok := respMap["data"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: data字段格式错误", processors.ErrDatasource)
|
||||
}
|
||||
|
||||
// 使用gjson解析data字符串
|
||||
hyzk := ""
|
||||
{
|
||||
result := gjson.Get(dataStr, "hyzk")
|
||||
if !result.Exists() {
|
||||
return nil, fmt.Errorf("%s: data中缺少hyzk字段", processors.ErrDatasource)
|
||||
}
|
||||
hyzk = result.String()
|
||||
}
|
||||
|
||||
// 返回格式为 {"status": hyzk}
|
||||
resp := map[string]interface{}{
|
||||
"status": hyzk,
|
||||
}
|
||||
finalBytes, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return finalBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ5733Request IVYZ5733 API处理方法
|
||||
func ProcessIVYZ5733Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ5733Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idNo": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G09GZ02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 解析新源响应数据
|
||||
var newResp struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := json.Unmarshal(respBytes, &newResp); err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 转换状态码
|
||||
var statusCode string
|
||||
switch newResp.Status {
|
||||
case "结婚":
|
||||
statusCode = "IA"
|
||||
case "离婚":
|
||||
statusCode = "IB"
|
||||
case "未查得":
|
||||
statusCode = "INR"
|
||||
default:
|
||||
statusCode = "INR"
|
||||
}
|
||||
|
||||
// 构建旧格式响应
|
||||
oldResp := map[string]interface{}{
|
||||
"code": "0",
|
||||
"data": map[string]interface{}{
|
||||
"data": statusCode + ":匹配不成功",
|
||||
},
|
||||
"seqNo": "",
|
||||
"message": "成功",
|
||||
}
|
||||
|
||||
// 返回旧格式响应
|
||||
return json.Marshal(oldResp)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ5A9ORequest IVYZ5A9O API处理方法 全国⾃然⼈⻛险评估评分模型
|
||||
func ProcessIVYZ5A9ORequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
|
||||
var paramsDto dto.IVYZ5A9OReq
|
||||
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)
|
||||
}
|
||||
encryptedAuthAuthorizeFileCode, err := deps.WestDexService.Encrypt(paramsDto.AuthAuthorizeFileCode)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"idcard": encryptedIDCard,
|
||||
"name": encryptedName,
|
||||
"auth_authorizeFileCode": encryptedAuthAuthorizeFileCode,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G01SC01", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ5E22Request API处理方法 - 双人婚姻评估查询
|
||||
func ProcessIVYZ5E22Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ5E22Req
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedManName, err := deps.ZhichaService.Encrypt(paramsDto.ManName)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedManIDCard, err := deps.ZhichaService.Encrypt(paramsDto.ManIDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
encryptedWomanName, err := deps.ZhichaService.Encrypt(paramsDto.WomanName)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
encryptedWomanIDCard, err := deps.ZhichaService.Encrypt(paramsDto.WomanIDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"nameMan": encryptedManName,
|
||||
"idCardMan": encryptedManIDCard,
|
||||
"nameWoman": encryptedWomanName,
|
||||
"idCardWoman": encryptedWomanIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI042", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ5E3FRequest IVYZ5E3F API处理方法 - 婚姻评估查询
|
||||
func ProcessIVYZ5E3FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ5E3FReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI029", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZ6G7HRequest IVYZ6G7H API处理方法 - 个人婚姻状况查询v2
|
||||
func ProcessIVYZ6G7HRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ6G7HReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1104646268587536384"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZ6M8PRequest IVYZ6M8P 职业资格证书API处理方法
|
||||
func ProcessIVYZ6M8PRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ6M8PReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1147725836315455488"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ7C9DRequest IVYZ7C9D API处理方法 - 人脸识别
|
||||
func ProcessIVYZ7C9DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ7C9DReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
"returnUrl": paramsDto.ReturnURL,
|
||||
"orderId": paramsDto.UniqueID,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI013", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// ProcessIVYZ7F2ARequest IVYZ7F2A API处理方法
|
||||
func ProcessIVYZ7F2ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ7F2AReq
|
||||
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)
|
||||
}
|
||||
|
||||
encryptedManName, err := deps.WestDexService.Encrypt(paramsDto.ManName)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedManIDCard, err := deps.WestDexService.Encrypt(paramsDto.ManIDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedWomanName, err := deps.WestDexService.Encrypt(paramsDto.WomanName)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedWomanIDCard, err := deps.WestDexService.Encrypt(paramsDto.WomanIDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"manName": encryptedManName,
|
||||
"manIdcard": encryptedManIDCard,
|
||||
"womanName": encryptedWomanName,
|
||||
"womanIdcard": encryptedWomanIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G10GZ02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
var respMap map[string]interface{}
|
||||
if err := json.Unmarshal(respBytes, &respMap); err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
dataStr, ok := respMap["data"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: data字段格式错误", processors.ErrDatasource)
|
||||
}
|
||||
|
||||
// 使用gjson解析data字符串
|
||||
hyzk := ""
|
||||
{
|
||||
result := gjson.Get(dataStr, "hyzk")
|
||||
if !result.Exists() {
|
||||
return nil, fmt.Errorf("%s: data中缺少hyzk字段", processors.ErrDatasource)
|
||||
}
|
||||
hyzk = result.String()
|
||||
}
|
||||
|
||||
// 返回格式为 {"status": hyzk}
|
||||
resp := map[string]interface{}{
|
||||
"status": hyzk,
|
||||
}
|
||||
finalBytes, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return finalBytes, nil
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ7F3ARequest IVYZ7F3A API处理方法 - 学历信息查询B
|
||||
func ProcessIVYZ7F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ7F3AReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI035", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessIVYZ81NCRequest IVYZ81NC API处理方法
|
||||
func ProcessIVYZ81NCRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ81NCReq
|
||||
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.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": "1", // 默认值
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI029", 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 解析响应数据,期望格式为 {"state": "1"}
|
||||
var stateResp struct {
|
||||
State string `json:"state"`
|
||||
RegTime string `json:"regTime"`
|
||||
}
|
||||
|
||||
// 将 respData 转换为 JSON 字节再解析
|
||||
respDataBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(respDataBytes, &stateResp); err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 根据 state 值转换为 81nc 格式
|
||||
var opType, opTypeDesc string
|
||||
switch stateResp.State {
|
||||
case "1": // 已婚
|
||||
opType = "IA"
|
||||
opTypeDesc = "结婚"
|
||||
case "2": // 未婚/未在民政局登记
|
||||
opType = "INR"
|
||||
opTypeDesc = "匹配不成功"
|
||||
case "3": // 离异
|
||||
opType = "IB"
|
||||
opTypeDesc = "离婚"
|
||||
default:
|
||||
opType = "INR"
|
||||
opTypeDesc = "匹配不成功"
|
||||
}
|
||||
|
||||
// 构建 81nc 格式响应
|
||||
result := map[string]interface{}{
|
||||
"code": "0",
|
||||
"data": map[string]interface{}{
|
||||
"op_date": stateResp.RegTime,
|
||||
"op_type": opType,
|
||||
"op_type_desc": opTypeDesc,
|
||||
},
|
||||
"message": "成功",
|
||||
"seqNo": "",
|
||||
}
|
||||
|
||||
// 返回 81nc 格式响应
|
||||
return json.Marshal(result)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZ8I9JRequest IVYZ8I9J API处理方法 - 互联网行为推测
|
||||
func ProcessIVYZ8I9JRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ8I9JReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,将项目规范的字段名转换为 XingweiService 需要的字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
"phoneNumber": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1074522823015198720"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ9363Request IVYZ9363 API处理方法
|
||||
func ProcessIVYZ9363Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ9363Req
|
||||
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)
|
||||
}
|
||||
// 新增:身份证一致性校验
|
||||
if strings.EqualFold(strings.TrimSpace(paramsDto.ManIDCard), strings.TrimSpace(paramsDto.WomanIDCard)) {
|
||||
return nil, errors.Join(processors.ErrInvalidParam, errors.New("请正确填写身份信息"))
|
||||
}
|
||||
|
||||
encryptedManName, err := deps.WestDexService.Encrypt(paramsDto.ManName)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedManIDCard, err := deps.WestDexService.Encrypt(paramsDto.ManIDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedWomanName, err := deps.WestDexService.Encrypt(paramsDto.WomanName)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedWomanIDCard, err := deps.WestDexService.Encrypt(paramsDto.WomanIDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name_man": encryptedManName,
|
||||
"idcard_man": encryptedManIDCard,
|
||||
"name_woman": encryptedWomanName,
|
||||
"idcard_woman": encryptedWomanIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G10XM02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZ9A2BRequest IVYZ9A2B API处理方法
|
||||
func ProcessIVYZ9A2BRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ9A2BReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"name_value": encryptedName,
|
||||
"id_card_value": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G11BJ06", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZ9D2ERequest IVYZ9D2E API处理方法 - 行为数据查询
|
||||
func ProcessIVYZ9D2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ9D2EReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,使用xingwei服务的正确字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
"scenario": paramsDto.UseScenario,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1104648845446279168"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
// 查空情况,返回特定的查空错误
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
// 数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
// 系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/jiguang"
|
||||
)
|
||||
|
||||
// ProcessIVYZ9H2MRequest IVYZ9H2M API处理方法 - 极光个人婚姻查询(V2版)
|
||||
func ProcessIVYZ9H2MRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ9H2MReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求参数
|
||||
reqData := map[string]interface{}{
|
||||
"id_no": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 调用极光API
|
||||
// apiCode: marriage-single-v2 (用于请求头)
|
||||
// apiPath: marriage/single-v2 (用于URL路径)
|
||||
respBytes, err := deps.JiguangService.CallAPI(ctx, "marriage-single-v2", "marriage/single-v2", reqData)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// 极光服务已经返回了 data 字段的 JSON,直接返回即可
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// 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{}{
|
||||
"data": map[string]interface{}{
|
||||
"timeStamp": timestamp,
|
||||
"customNumber": customNumber,
|
||||
"xM": encryptedName,
|
||||
"gMSFZHM": encryptedIDCard,
|
||||
"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)
|
||||
}
|
||||
}
|
||||
|
||||
// 使用gjson提取authResult字段
|
||||
// 尝试多个可能的路径
|
||||
var authResult string
|
||||
paths := []string{
|
||||
"WEST00037.WEST00038.authResult",
|
||||
"WEST00036.WEST00037.WEST00038.authResult",
|
||||
"authResult",
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
result := gjson.GetBytes(respBytes, path)
|
||||
if result.Exists() {
|
||||
authResult = result.String()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 如果找不到authResult,返回ErrDatasource
|
||||
if authResult == "" {
|
||||
return nil, errors.Join(processors.ErrDatasource, errors.New("响应中未找到authResult字段"))
|
||||
}
|
||||
|
||||
// 构建返回格式 {result: XXXX}
|
||||
response := map[string]interface{}{
|
||||
"result": authResult,
|
||||
}
|
||||
|
||||
responseBytes, err := json.Marshal(response)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return responseBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ProcessIVYZ9K7FRequest IVYZ9K7F 身份证实名认证即时版 API处理方法
|
||||
func ProcessIVYZ9K7FRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ9K7FReq
|
||||
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)
|
||||
}
|
||||
reqFormData := map[string]interface{}{
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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 {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ProcessIVYZA1B3Request IVYZA1B3 公安三要素人脸识别API处理方法
|
||||
func ProcessIVYZA1B3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZA1B3Req
|
||||
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)
|
||||
}
|
||||
reqFormData := map[string]interface{}{
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
"image": paramsDto.PhotoData,
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/face_id_card/compare" // 接口路径,根据数脉文档填写(如 v4/xxx)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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 {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
)
|
||||
|
||||
// ProcessIVYZADEERequest IVYZADEE API处理方法
|
||||
func ProcessIVYZADEERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("服务已停用"))
|
||||
// var paramsDto dto.IVYZADEEReq
|
||||
// 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)
|
||||
// }
|
||||
|
||||
// reqData := map[string]interface{}{
|
||||
// "name": paramsDto.Name,
|
||||
// "idCard": paramsDto.IDCard,
|
||||
// "mobile": paramsDto.Mobile,
|
||||
// }
|
||||
|
||||
// respBytes, err := deps.WestDexService.CallAPI(ctx, "IVYZADEE", reqData)
|
||||
// if err != nil {
|
||||
// if errors.Is(err, westdex.ErrDatasource) {
|
||||
// return nil, errors.Join(processors.ErrDatasource, err)
|
||||
// } else {
|
||||
// return nil, errors.Join(processors.ErrSystem, err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZBPQ2Request IVYZBPQ2 人脸比对V2API处理方法
|
||||
func ProcessIVYZBPQ2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZBPQ2Req
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,使用xingwei服务的正确字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
"image": paramsDto.PhotoData,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1104321425593790464"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
// 查空情况,返回特定的查空错误
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
// 数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
// 系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ProcessIVYZFIC1Request IVYZFIC1 人脸身份证比对 API 处理方法(数脉)
|
||||
func ProcessIVYZFIC1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZFIC1Req
|
||||
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)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(paramsDto.PhotoData) == "" && strings.TrimSpace(paramsDto.ImageUrl) == "" {
|
||||
return nil, errors.Join(processors.ErrInvalidParam, errors.New("image和url至少传一个"))
|
||||
}
|
||||
|
||||
reqFormData := map[string]interface{}{
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
"image": paramsDto.PhotoData,
|
||||
"url": paramsDto.ImageUrl,
|
||||
}
|
||||
|
||||
apiPath := "/v4/face_id_card/compare"
|
||||
|
||||
// 先尝试政务接口,再回退实时接口
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true)
|
||||
if err != nil {
|
||||
respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/westdex"
|
||||
)
|
||||
|
||||
// ProcessIVYZGZ08Request IVYZGZ08 API处理方法
|
||||
func ProcessIVYZGZ08Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZGZ08Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"xm": encryptedName,
|
||||
"gmsfzhm": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G08SC02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ProcessIVYZN2P8Request IVYZN2P8 身份证实名认证政务版 API处理方法
|
||||
func ProcessIVYZN2P8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZ9K7FReq
|
||||
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)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idcard": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/id_card/check"
|
||||
|
||||
// 先尝试使用政务接口(app_id2 和 app_secret2)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqData, true)
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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)
|
||||
}
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
|
||||
// respBytes, err := deps.AlicloudService.CallAPI("api-mall/api/id_card/check", reqData)
|
||||
// if err != nil {
|
||||
// if errors.Is(err, alicloud.ErrDatasource) {
|
||||
// return nil, errors.Join(processors.ErrDatasource, err)
|
||||
// }
|
||||
// return nil, errors.Join(processors.ErrSystem, err)
|
||||
// }
|
||||
|
||||
// return respBytes, nil
|
||||
// // 对齐 yysybe08test 的原始响应结构,取 data 字段映射为 ivyzn2p8 返回
|
||||
// var aliyunData struct {
|
||||
// Code int `json:"code"`
|
||||
// Data struct {
|
||||
// Birthday string `json:"birthday"`
|
||||
// Result interface{} `json:"result"`
|
||||
// Address string `json:"address"`
|
||||
// OrderNo string `json:"orderNo"`
|
||||
// Sex string `json:"sex"`
|
||||
// Desc string `json:"desc"`
|
||||
// } `json:"data"`
|
||||
// Result interface{} `json:"result"`
|
||||
// Desc string `json:"desc"`
|
||||
// }
|
||||
// if err := json.Unmarshal(respBytes, &aliyunData); err != nil {
|
||||
// return nil, errors.Join(processors.ErrSystem, err)
|
||||
// }
|
||||
|
||||
// rawResult := aliyunData.Result
|
||||
// rawDesc := aliyunData.Desc
|
||||
// if aliyunData.Code == 200 {
|
||||
// rawResult = aliyunData.Data.Result
|
||||
// rawDesc = aliyunData.Data.Desc
|
||||
// }
|
||||
|
||||
// response := map[string]interface{}{
|
||||
// "result": normalizeResult(rawResult),
|
||||
// "order_no": aliyunData.Data.OrderNo,
|
||||
// "desc": rawDesc,
|
||||
// "sex": aliyunData.Data.Sex,
|
||||
// "birthday": aliyunData.Data.Birthday,
|
||||
// "address": aliyunData.Data.Address,
|
||||
// }
|
||||
// return json.Marshal(response)
|
||||
// }
|
||||
|
||||
// func normalizeResult(v interface{}) int {
|
||||
// switch r := v.(type) {
|
||||
// case float64:
|
||||
// return int(r)
|
||||
// case int:
|
||||
// return r
|
||||
// case int32:
|
||||
// return int(r)
|
||||
// case int64:
|
||||
// return int(r)
|
||||
// case json.Number:
|
||||
// n, err := r.Int64()
|
||||
// if err == nil {
|
||||
// return int(n)
|
||||
// }
|
||||
// case string:
|
||||
// s := strings.TrimSpace(r)
|
||||
// if s == "" {
|
||||
// return 1
|
||||
// }
|
||||
// n, err := strconv.Atoi(s)
|
||||
// if err == nil {
|
||||
// return n
|
||||
// }
|
||||
// }
|
||||
// // 默认按不一致处理
|
||||
// return 1
|
||||
// }
|
||||
@@ -0,0 +1,48 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shujubao"
|
||||
)
|
||||
|
||||
// ProcessIVYZOCR1Request IVYZOCR1 身份证OCR API 处理方法(使用数据宝服务示例)
|
||||
func ProcessIVYZOCR1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZOCR1Req
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建数据宝入参:姓名、身份证、手机号、银行卡号(sign 外的业务参数可按需 AES 加密后作为 bodyData)
|
||||
reqParams := map[string]interface{}{
|
||||
"key": "8782f2a32463f75b53096323461df735",
|
||||
"imageId": paramsDto.PhotoData,
|
||||
}
|
||||
|
||||
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 personal/197
|
||||
apiPath := "/trade/user/1985"
|
||||
data, err := deps.ShujubaoService.CallAPI(ctx, apiPath, reqParams)
|
||||
if err != nil {
|
||||
if errors.Is(err, shujubao.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, shujubao.ErrQueryEmpty) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
respBytes, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ProcessIVYZOCR2Request IVYZOCR2 OCR识别API处理方法数卖
|
||||
func ProcessIVYZOCR2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZOCR1Req
|
||||
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)
|
||||
}
|
||||
|
||||
if paramsDto.PhotoData == "" && paramsDto.ImageUrl == "" {
|
||||
return nil, errors.Join(processors.ErrInvalidParam, errors.New("photo_data or image_url is required"))
|
||||
}
|
||||
|
||||
// 2选1:有值的用对应 key,空则用另一个
|
||||
reqFormData := make(map[string]interface{})
|
||||
if paramsDto.PhotoData != "" {
|
||||
reqFormData["image"] = paramsDto.PhotoData
|
||||
} else {
|
||||
reqFormData["url"] = paramsDto.ImageUrl
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/idcard/ocr" // 接口路径,根据数脉文档填写(如 v4/xxx)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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 {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
)
|
||||
|
||||
// ProcessIVYZP2Q6Request IVYZP2Q6 API处理方法 - 身份认证二要素
|
||||
func ProcessIVYZP2Q6Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZP2Q6Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqFormData := map[string]interface{}{
|
||||
"idcard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx)
|
||||
|
||||
// 先尝试使用政务接口(app_id2 和 app_secret2)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true)
|
||||
if err != nil {
|
||||
// 使用实时接口(app_id 和 app_secret)重试
|
||||
respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
|
||||
// 如果重试后仍然失败,返回错误
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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 {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 数据源返回 result(0-一致/1-不一致/2-无记录),映射为 state(1-匹配/2-不匹配/3-异常情况)
|
||||
var dsResp struct {
|
||||
Result int `json:"result"` // 0-一致 1-不一致 2-无记录(预留)
|
||||
}
|
||||
if err := json.Unmarshal(respBytes, &dsResp); err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
state := resultToState(dsResp.Result)
|
||||
|
||||
out := map[string]interface{}{
|
||||
"errMsg": "",
|
||||
"state": state,
|
||||
}
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
// resultToState 将数据源 result 映射为接口 state:1-匹配 2-不匹配 3-异常情况
|
||||
func resultToState(result int) int {
|
||||
switch result {
|
||||
case 0: // 一致 → 匹配
|
||||
return 1
|
||||
case 1: // 不一致 → 不匹配
|
||||
return 2
|
||||
case 2: // 无记录(预留) → 异常情况
|
||||
return 3
|
||||
default:
|
||||
return 3 // 未知/异常 → 异常情况
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/xingwei"
|
||||
)
|
||||
|
||||
// ProcessIVYZSFELRequest IVYZSFEL 全国自然人人像三要素核验_V1API处理方法
|
||||
func ProcessIVYZSFELRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZSFELReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 构建请求数据,使用xingwei服务的正确字段名
|
||||
reqData := map[string]interface{}{
|
||||
"name": paramsDto.Name,
|
||||
"idCardNum": paramsDto.IDCard,
|
||||
"photo": paramsDto.PhotoData,
|
||||
"authAuthorizeFileCode": paramsDto.AuthAuthorizeFileCode,
|
||||
}
|
||||
|
||||
// 调用行为数据API,使用指定的project_id
|
||||
projectID := "CDJ-1068350101927161856"
|
||||
respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, xingwei.ErrNotFound) {
|
||||
// 查空情况,返回特定的查空错误
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else if errors.Is(err, xingwei.ErrDatasource) {
|
||||
// 数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else if errors.Is(err, xingwei.ErrSystem) {
|
||||
// 系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
} else {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package ivyz
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"hyapi-server/internal/domains/api/dto"
|
||||
"hyapi-server/internal/domains/api/services/processors"
|
||||
"hyapi-server/internal/infrastructure/external/shumai"
|
||||
"hyapi-server/internal/shared/logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// ProcessIVYZX5Q2Request IVYZX5Q2 活体识别步骤二API处理方法
|
||||
func ProcessIVYZX5Q2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.IVYZX5Q2Req
|
||||
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)
|
||||
}
|
||||
|
||||
reqFormData := map[string]interface{}{
|
||||
"token": paramsDto.Token,
|
||||
}
|
||||
|
||||
// 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
|
||||
apiPath := "/v4/liveness/h5/v4/result" // 接口路径,根据数脉文档填写(如 v4/xxx)
|
||||
respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData)
|
||||
if err != nil {
|
||||
if errors.Is(err, shumai.ErrNotFound) {
|
||||
// 查无记录情况
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
} else 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 {
|
||||
// 其他未知错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
// result==2 时手动抛出错误(不通过/无记录,不返回正常响应)
|
||||
var body struct {
|
||||
Result int `json:"result"`
|
||||
}
|
||||
if err := json.Unmarshal(respBytes, &body); err == nil && body.Result == 2 {
|
||||
log := logger.GetGlobalLogger()
|
||||
log.Warn("IVYZX5Q2 活体检测 result=2 无记录或不通过,返回错误",
|
||||
zap.Int("result", body.Result),
|
||||
zap.ByteString("response", respBytes))
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("活体检测 result=2 无记录或不通过"))
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user