接入阿里云二要素
This commit is contained in:
@@ -212,3 +212,10 @@ alipay:
|
|||||||
tianyancha:
|
tianyancha:
|
||||||
base_url: http://open.api.tianyancha.com/services
|
base_url: http://open.api.tianyancha.com/services
|
||||||
api_key: e6a43dc9-786e-4a16-bb12-392b8201d8e2
|
api_key: e6a43dc9-786e-4a16-bb12-392b8201d8e2
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# ☁️ 阿里云配置
|
||||||
|
# ===========================================
|
||||||
|
alicloud:
|
||||||
|
host: "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
app_code: "d55b58829efb41c8aa8e86769cba4844"
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type Config struct {
|
|||||||
AliPay AliPayConfig `mapstructure:"alipay"`
|
AliPay AliPayConfig `mapstructure:"alipay"`
|
||||||
Yushan YushanConfig `mapstructure:"yushan"`
|
Yushan YushanConfig `mapstructure:"yushan"`
|
||||||
TianYanCha TianYanChaConfig `mapstructure:"tianyancha"`
|
TianYanCha TianYanChaConfig `mapstructure:"tianyancha"`
|
||||||
|
Alicloud AlicloudConfig `mapstructure:"alicloud"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerConfig HTTP服务器配置
|
// ServerConfig HTTP服务器配置
|
||||||
@@ -329,6 +330,11 @@ type TianYanChaConfig struct {
|
|||||||
APIKey string `mapstructure:"api_key"`
|
APIKey string `mapstructure:"api_key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AlicloudConfig struct {
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
AppCode string `mapstructure:"app_code"`
|
||||||
|
}
|
||||||
|
|
||||||
// DomainConfig 域名配置
|
// DomainConfig 域名配置
|
||||||
type DomainConfig struct {
|
type DomainConfig struct {
|
||||||
API string `mapstructure:"api"` // API域名
|
API string `mapstructure:"api"` // API域名
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import (
|
|||||||
finance_repo "tyapi-server/internal/infrastructure/database/repositories/finance"
|
finance_repo "tyapi-server/internal/infrastructure/database/repositories/finance"
|
||||||
product_repo "tyapi-server/internal/infrastructure/database/repositories/product"
|
product_repo "tyapi-server/internal/infrastructure/database/repositories/product"
|
||||||
infra_events "tyapi-server/internal/infrastructure/events"
|
infra_events "tyapi-server/internal/infrastructure/events"
|
||||||
|
"tyapi-server/internal/infrastructure/external/alicloud"
|
||||||
"tyapi-server/internal/infrastructure/external/email"
|
"tyapi-server/internal/infrastructure/external/email"
|
||||||
"tyapi-server/internal/infrastructure/external/ocr"
|
"tyapi-server/internal/infrastructure/external/ocr"
|
||||||
"tyapi-server/internal/infrastructure/external/sms"
|
"tyapi-server/internal/infrastructure/external/sms"
|
||||||
@@ -326,6 +327,13 @@ func NewContainer() *Container {
|
|||||||
30*time.Second, // 默认超时时间
|
30*time.Second, // 默认超时时间
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
// AlicloudService - 阿里云服务
|
||||||
|
func(cfg *config.Config) *alicloud.AlicloudService {
|
||||||
|
return alicloud.NewAlicloudService(
|
||||||
|
cfg.Alicloud.Host,
|
||||||
|
cfg.Alicloud.AppCode,
|
||||||
|
)
|
||||||
|
},
|
||||||
sharedhttp.NewGinRouter,
|
sharedhttp.NewGinRouter,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"tyapi-server/internal/domains/api/services/processors/qygl"
|
"tyapi-server/internal/domains/api/services/processors/qygl"
|
||||||
"tyapi-server/internal/domains/api/services/processors/yysy"
|
"tyapi-server/internal/domains/api/services/processors/yysy"
|
||||||
"tyapi-server/internal/domains/product/services"
|
"tyapi-server/internal/domains/product/services"
|
||||||
|
"tyapi-server/internal/infrastructure/external/alicloud"
|
||||||
"tyapi-server/internal/infrastructure/external/tianyancha"
|
"tyapi-server/internal/infrastructure/external/tianyancha"
|
||||||
"tyapi-server/internal/infrastructure/external/westdex"
|
"tyapi-server/internal/infrastructure/external/westdex"
|
||||||
"tyapi-server/internal/infrastructure/external/yushan"
|
"tyapi-server/internal/infrastructure/external/yushan"
|
||||||
@@ -32,6 +33,7 @@ type ApiRequestService struct {
|
|||||||
westDexService *westdex.WestDexService
|
westDexService *westdex.WestDexService
|
||||||
yushanService *yushan.YushanService
|
yushanService *yushan.YushanService
|
||||||
tianYanChaService *tianyancha.TianYanChaService
|
tianYanChaService *tianyancha.TianYanChaService
|
||||||
|
alicloudService *alicloud.AlicloudService
|
||||||
validator interfaces.RequestValidator
|
validator interfaces.RequestValidator
|
||||||
processorDeps *processors.ProcessorDependencies
|
processorDeps *processors.ProcessorDependencies
|
||||||
combService *comb.CombService
|
combService *comb.CombService
|
||||||
@@ -41,6 +43,7 @@ func NewApiRequestService(
|
|||||||
westDexService *westdex.WestDexService,
|
westDexService *westdex.WestDexService,
|
||||||
yushanService *yushan.YushanService,
|
yushanService *yushan.YushanService,
|
||||||
tianYanChaService *tianyancha.TianYanChaService,
|
tianYanChaService *tianyancha.TianYanChaService,
|
||||||
|
alicloudService *alicloud.AlicloudService,
|
||||||
validator interfaces.RequestValidator,
|
validator interfaces.RequestValidator,
|
||||||
productManagementService *services.ProductManagementService,
|
productManagementService *services.ProductManagementService,
|
||||||
) *ApiRequestService {
|
) *ApiRequestService {
|
||||||
@@ -48,7 +51,7 @@ func NewApiRequestService(
|
|||||||
combService := comb.NewCombService(productManagementService)
|
combService := comb.NewCombService(productManagementService)
|
||||||
|
|
||||||
// 创建处理器依赖容器
|
// 创建处理器依赖容器
|
||||||
processorDeps := processors.NewProcessorDependencies(westDexService, yushanService, tianYanChaService, validator, combService)
|
processorDeps := processors.NewProcessorDependencies(westDexService, yushanService, tianYanChaService, alicloudService, validator, combService)
|
||||||
|
|
||||||
// 统一注册所有处理器
|
// 统一注册所有处理器
|
||||||
registerAllProcessors(combService)
|
registerAllProcessors(combService)
|
||||||
@@ -57,6 +60,7 @@ func NewApiRequestService(
|
|||||||
westDexService: westDexService,
|
westDexService: westDexService,
|
||||||
yushanService: yushanService,
|
yushanService: yushanService,
|
||||||
tianYanChaService: tianYanChaService,
|
tianYanChaService: tianYanChaService,
|
||||||
|
alicloudService: alicloudService,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
processorDeps: processorDeps,
|
processorDeps: processorDeps,
|
||||||
combService: combService,
|
combService: combService,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package processors
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"tyapi-server/internal/application/api/commands"
|
"tyapi-server/internal/application/api/commands"
|
||||||
|
"tyapi-server/internal/infrastructure/external/alicloud"
|
||||||
"tyapi-server/internal/infrastructure/external/tianyancha"
|
"tyapi-server/internal/infrastructure/external/tianyancha"
|
||||||
"tyapi-server/internal/infrastructure/external/westdex"
|
"tyapi-server/internal/infrastructure/external/westdex"
|
||||||
"tyapi-server/internal/infrastructure/external/yushan"
|
"tyapi-server/internal/infrastructure/external/yushan"
|
||||||
@@ -19,6 +20,7 @@ type ProcessorDependencies struct {
|
|||||||
WestDexService *westdex.WestDexService
|
WestDexService *westdex.WestDexService
|
||||||
YushanService *yushan.YushanService
|
YushanService *yushan.YushanService
|
||||||
TianYanChaService *tianyancha.TianYanChaService
|
TianYanChaService *tianyancha.TianYanChaService
|
||||||
|
AlicloudService *alicloud.AlicloudService
|
||||||
Validator interfaces.RequestValidator
|
Validator interfaces.RequestValidator
|
||||||
CombService CombServiceInterface // Changed to interface to break import cycle
|
CombService CombServiceInterface // Changed to interface to break import cycle
|
||||||
Options *commands.ApiCallOptions // 添加Options支持
|
Options *commands.ApiCallOptions // 添加Options支持
|
||||||
@@ -29,6 +31,7 @@ func NewProcessorDependencies(
|
|||||||
westDexService *westdex.WestDexService,
|
westDexService *westdex.WestDexService,
|
||||||
yushanService *yushan.YushanService,
|
yushanService *yushan.YushanService,
|
||||||
tianYanChaService *tianyancha.TianYanChaService,
|
tianYanChaService *tianyancha.TianYanChaService,
|
||||||
|
alicloudService *alicloud.AlicloudService,
|
||||||
validator interfaces.RequestValidator,
|
validator interfaces.RequestValidator,
|
||||||
combService CombServiceInterface, // Changed to interface
|
combService CombServiceInterface, // Changed to interface
|
||||||
) *ProcessorDependencies {
|
) *ProcessorDependencies {
|
||||||
@@ -36,6 +39,7 @@ func NewProcessorDependencies(
|
|||||||
WestDexService: westDexService,
|
WestDexService: westDexService,
|
||||||
YushanService: yushanService,
|
YushanService: yushanService,
|
||||||
TianYanChaService: tianYanChaService,
|
TianYanChaService: tianYanChaService,
|
||||||
|
AlicloudService: alicloudService,
|
||||||
Validator: validator,
|
Validator: validator,
|
||||||
CombService: combService,
|
CombService: combService,
|
||||||
Options: nil, // 初始化为nil,在调用时设置
|
Options: nil, // 初始化为nil,在调用时设置
|
||||||
|
|||||||
@@ -36,9 +36,10 @@ func ProcessFLXG0V4BRequest(ctx context.Context, params []byte, deps *processors
|
|||||||
|
|
||||||
reqData := map[string]interface{}{
|
reqData := map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
"name": encryptedName,
|
"name": encryptedName,
|
||||||
"idcard": encryptedIDCard,
|
"idcard": encryptedIDCard,
|
||||||
"inquired_auth": paramsDto.AuthDate,
|
"inquired_auth": paramsDto.AuthDate,
|
||||||
|
// "auth_authorizeFileCode": paramsDto.AuthAuthorizeFileCode,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
respBytes, err := deps.WestDexService.CallAPI("G22SC01", reqData)
|
respBytes, err := deps.WestDexService.CallAPI("G22SC01", reqData)
|
||||||
|
|||||||
@@ -3,13 +3,10 @@ package qygl
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"tyapi-server/internal/domains/api/dto"
|
"tyapi-server/internal/domains/api/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/westdex"
|
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
@@ -74,58 +71,55 @@ func ProcessQYGL23T7Request(ctx context.Context, params []byte, deps *processors
|
|||||||
return createStatusResponse(1), nil
|
return createStatusResponse(1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 天眼查三要素验证通过,继续调用WestDex身份证二要素验证
|
// 天眼查三要素验证通过,继续调用阿里云身份证二要素验证
|
||||||
// 加密姓名和身份证号
|
// 构建阿里云二要素验证请求参数
|
||||||
encryptedName, err := deps.WestDexService.Encrypt(paramsDto.LegalPerson)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建WestDex身份证二要素验证请求参数(参考yysybe08_processor.go)
|
|
||||||
reqData := map[string]interface{}{
|
reqData := map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"name": paramsDto.LegalPerson,
|
||||||
"xM": encryptedName,
|
"idcard": paramsDto.IDCard,
|
||||||
"gMSFZHM": encryptedIDCard,
|
|
||||||
"customerNumber": deps.WestDexService.GetConfig().SecretId,
|
|
||||||
"timeStamp": fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用WestDex身份证二要素验证API
|
// 调用阿里云二要素验证API
|
||||||
respBytes, err := deps.WestDexService.CallAPI("layoutIdcard", reqData)
|
respBytes, err := deps.AlicloudService.CallAPI("api-mall/api/id_card/check", reqData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, westdex.ErrDatasource) {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用gjson获取resultCode
|
|
||||||
resultCode := gjson.GetBytes(respBytes, "ctidRequest.ctidAuth.resultCode")
|
|
||||||
if !resultCode.Exists() {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取resultCode的第一个字符
|
// 解析阿里云响应
|
||||||
resultCodeStr := resultCode.String()
|
var alicloudResponse struct {
|
||||||
if len(resultCodeStr) == 0 {
|
Msg string `json:"msg"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Birthday string `json:"birthday"`
|
||||||
|
Result int `json:"result"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Sex string `json:"sex"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(respBytes, &alicloudResponse); err != nil {
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
firstChar := string(resultCodeStr[0])
|
// 检查响应状态
|
||||||
if firstChar != "0" && firstChar != "5" {
|
if alicloudResponse.Code != 200 && alicloudResponse.Code != 400 {
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
return nil, fmt.Errorf("%s: %s", processors.ErrDatasource, alicloudResponse.Msg)
|
||||||
}
|
}
|
||||||
if firstChar == "0" {
|
|
||||||
return createStatusResponse(0), nil
|
// 根据阿里云响应结果返回状态
|
||||||
} else if firstChar == "5" {
|
if alicloudResponse.Code == 400 {
|
||||||
|
// 身份证号格式错误,返回状态2
|
||||||
return createStatusResponse(2), nil
|
return createStatusResponse(2), nil
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
if alicloudResponse.Data.Result == 0 {
|
||||||
|
// 验证通过,返回状态0
|
||||||
|
return createStatusResponse(0), nil
|
||||||
|
} else {
|
||||||
|
// 验证失败,返回状态2
|
||||||
|
return createStatusResponse(2), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ package yysy
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"tyapi-server/internal/domains/api/dto"
|
"tyapi-server/internal/domains/api/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/westdex"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessYYSYBE08Request YYSYBE08 API处理方法
|
// ProcessYYSYBE08Request YYSYBE08 API处理方法 - 使用阿里云二要素验证
|
||||||
func ProcessYYSYBE08Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
func ProcessYYSYBE08Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||||
var paramsDto dto.YYSYBE08Req
|
var paramsDto dto.YYSYBE08Req
|
||||||
if err := json.Unmarshal(params, ¶msDto); err != nil {
|
if err := json.Unmarshal(params, ¶msDto); err != nil {
|
||||||
@@ -23,31 +20,70 @@ func ProcessYYSYBE08Request(ctx context.Context, params []byte, deps *processors
|
|||||||
return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, err)
|
return nil, fmt.Errorf("%s: %w", processors.ErrInvalidParam, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedName, err := deps.WestDexService.Encrypt(paramsDto.Name)
|
// 调用阿里云二要素验证API
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqData := map[string]interface{}{
|
reqData := map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"name": paramsDto.Name,
|
||||||
"xM": encryptedName,
|
"idcard": paramsDto.IDCard,
|
||||||
"gMSFZHM": encryptedIDCard,
|
}
|
||||||
"customerNumber": deps.WestDexService.GetConfig().SecretId,
|
|
||||||
"timeStamp": fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond)),
|
respBytes, err := deps.AlicloudService.CallAPI("api-mall/api/id_card/check", reqData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析阿里云响应
|
||||||
|
var alicloudResponse struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Birthday string `json:"birthday"`
|
||||||
|
Result int `json:"result"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Sex string `json:"sex"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(respBytes, &alicloudResponse); err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if alicloudResponse.Code != 200 && alicloudResponse.Code != 400 {
|
||||||
|
return nil, fmt.Errorf("%s: %s", processors.ErrDatasource, alicloudResponse.Msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建返回结果
|
||||||
|
resultCode := "0XXX" // 默认成功
|
||||||
|
resultMsg := "验证通过"
|
||||||
|
verifyResult := "一致"
|
||||||
|
if alicloudResponse.Code == 400 {
|
||||||
|
resultCode = "5XXX"
|
||||||
|
resultMsg = "请输入有效的身份证号码"
|
||||||
|
verifyResult = "不一致"
|
||||||
|
} else {
|
||||||
|
if alicloudResponse.Data.Result != 0 {
|
||||||
|
// 验证失败
|
||||||
|
resultCode = "5XXX"
|
||||||
|
resultMsg = "身份证号不匹配"
|
||||||
|
verifyResult = "不一致"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 构建最终响应结构
|
||||||
|
response := map[string]interface{}{
|
||||||
|
"ctidRequest": map[string]interface{}{
|
||||||
|
"ctidAuth": map[string]interface{}{
|
||||||
|
"resultCode": resultCode,
|
||||||
|
"resultMsg": resultMsg,
|
||||||
|
"name": paramsDto.Name,
|
||||||
|
"idCard": paramsDto.IDCard,
|
||||||
|
"verifyResult": verifyResult,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
respBytes, err := deps.WestDexService.CallAPI("layoutIdcard", reqData)
|
// 返回JSON格式的响应
|
||||||
if err != nil {
|
return json.Marshal(response)
|
||||||
if !errors.Is(err, westdex.ErrDatasource) {
|
|
||||||
return nil, fmt.Errorf("%s: %w", processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return respBytes, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,158 @@
|
|||||||
|
package yysy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestYYSYBE08ResponseStructure(t *testing.T) {
|
||||||
|
// 测试响应结构构建逻辑
|
||||||
|
resultCode := "1001"
|
||||||
|
resultMsg := "验证通过"
|
||||||
|
verifyResult := "一致"
|
||||||
|
|
||||||
|
// 模拟阿里云返回result=0(一致)的情况
|
||||||
|
alicloudResult := 0
|
||||||
|
if alicloudResult == 0 {
|
||||||
|
// 验证成功
|
||||||
|
resultCode = "1001"
|
||||||
|
resultMsg = "验证通过"
|
||||||
|
verifyResult = "一致"
|
||||||
|
} else {
|
||||||
|
// 验证失败
|
||||||
|
resultCode = "1002"
|
||||||
|
resultMsg = "身份证号不匹配"
|
||||||
|
verifyResult = "不一致"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建响应结构
|
||||||
|
response := map[string]interface{}{
|
||||||
|
"ctidRequest": map[string]interface{}{
|
||||||
|
"ctidAuth": map[string]interface{}{
|
||||||
|
"resultCode": resultCode,
|
||||||
|
"resultMsg": resultMsg,
|
||||||
|
"name": "张荣宏",
|
||||||
|
"idCard": "45212220000827423X",
|
||||||
|
"verifyResult": verifyResult,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 序列化为JSON
|
||||||
|
jsonData, err := json.Marshal(response)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("JSON序列化失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证JSON结构
|
||||||
|
var parsedResponse map[string]interface{}
|
||||||
|
if err := json.Unmarshal(jsonData, &parsedResponse); err != nil {
|
||||||
|
t.Fatalf("JSON反序列化失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证字段存在
|
||||||
|
ctidRequest, exists := parsedResponse["ctidRequest"]
|
||||||
|
if !exists {
|
||||||
|
t.Fatal("响应中缺少ctidRequest字段")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctidAuth, exists := ctidRequest.(map[string]interface{})["ctidAuth"]
|
||||||
|
if !exists {
|
||||||
|
t.Fatal("响应中缺少ctidAuth字段")
|
||||||
|
}
|
||||||
|
|
||||||
|
authData := ctidAuth.(map[string]interface{})
|
||||||
|
|
||||||
|
// 验证字段值
|
||||||
|
expectedFields := map[string]string{
|
||||||
|
"resultCode": "1001",
|
||||||
|
"resultMsg": "验证通过",
|
||||||
|
"name": "张荣宏",
|
||||||
|
"idCard": "45212220000827423X",
|
||||||
|
"verifyResult": "一致",
|
||||||
|
}
|
||||||
|
|
||||||
|
for field, expectedValue := range expectedFields {
|
||||||
|
if authData[field] != expectedValue {
|
||||||
|
t.Errorf("字段%s期望值为%s,实际为%s", field, expectedValue, authData[field])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("测试成功,响应结构: %s", string(jsonData))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestYYSYBE08ResponseStructure_Failure(t *testing.T) {
|
||||||
|
// 测试验证失败的情况
|
||||||
|
resultCode := "1002"
|
||||||
|
resultMsg := "身份证号不匹配"
|
||||||
|
verifyResult := "不一致"
|
||||||
|
|
||||||
|
// 模拟阿里云返回result=1(不一致)的情况
|
||||||
|
alicloudResult := 1
|
||||||
|
if alicloudResult == 0 {
|
||||||
|
// 验证成功
|
||||||
|
resultCode = "1001"
|
||||||
|
resultMsg = "验证通过"
|
||||||
|
verifyResult = "一致"
|
||||||
|
} else {
|
||||||
|
// 验证失败
|
||||||
|
resultCode = "1002"
|
||||||
|
resultMsg = "身份证号不匹配"
|
||||||
|
verifyResult = "不一致"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建响应结构
|
||||||
|
response := map[string]interface{}{
|
||||||
|
"ctidRequest": map[string]interface{}{
|
||||||
|
"ctidAuth": map[string]interface{}{
|
||||||
|
"resultCode": resultCode,
|
||||||
|
"resultMsg": resultMsg,
|
||||||
|
"name": "张三",
|
||||||
|
"idCard": "110101199001011235",
|
||||||
|
"verifyResult": verifyResult,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 序列化为JSON
|
||||||
|
jsonData, err := json.Marshal(response)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("JSON序列化失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证JSON结构
|
||||||
|
var parsedResponse map[string]interface{}
|
||||||
|
if err := json.Unmarshal(jsonData, &parsedResponse); err != nil {
|
||||||
|
t.Fatalf("JSON反序列化失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证字段存在
|
||||||
|
ctidRequest, exists := parsedResponse["ctidRequest"]
|
||||||
|
if !exists {
|
||||||
|
t.Fatal("响应中缺少ctidRequest字段")
|
||||||
|
}
|
||||||
|
|
||||||
|
ctidAuth, exists := ctidRequest.(map[string]interface{})["ctidAuth"]
|
||||||
|
if !exists {
|
||||||
|
t.Fatal("响应中缺少ctidAuth字段")
|
||||||
|
}
|
||||||
|
|
||||||
|
authData := ctidAuth.(map[string]interface{})
|
||||||
|
|
||||||
|
// 验证字段值
|
||||||
|
expectedFields := map[string]string{
|
||||||
|
"resultCode": "1002",
|
||||||
|
"resultMsg": "身份证号不匹配",
|
||||||
|
"name": "张三",
|
||||||
|
"idCard": "110101199001011235",
|
||||||
|
"verifyResult": "不一致",
|
||||||
|
}
|
||||||
|
|
||||||
|
for field, expectedValue := range expectedFields {
|
||||||
|
if authData[field] != expectedValue {
|
||||||
|
t.Errorf("字段%s期望值为%s,实际为%s", field, expectedValue, authData[field])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("测试成功,失败响应结构: %s", string(jsonData))
|
||||||
|
}
|
||||||
@@ -2,12 +2,18 @@ package entities
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 初始化随机数种子
|
||||||
|
func init() {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
// ContractType 合同类型枚举
|
// ContractType 合同类型枚举
|
||||||
type ContractType string
|
type ContractType string
|
||||||
|
|
||||||
@@ -20,15 +26,16 @@ const (
|
|||||||
// 存储企业签署的合同信息,一个企业可以有多个合同
|
// 存储企业签署的合同信息,一个企业可以有多个合同
|
||||||
type ContractInfo struct {
|
type ContractInfo struct {
|
||||||
// 基础标识
|
// 基础标识
|
||||||
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"合同信息唯一标识"`
|
ID string `gorm:"primaryKey;type:varchar(36)" json:"id" comment:"合同信息唯一标识"`
|
||||||
EnterpriseInfoID string `gorm:"type:varchar(36);not null;index" json:"enterprise_info_id" comment:"关联企业信息ID"`
|
EnterpriseInfoID string `gorm:"type:varchar(36);not null;index" json:"enterprise_info_id" comment:"关联企业信息ID"`
|
||||||
UserID string `gorm:"type:varchar(36);not null;index" json:"user_id" comment:"关联用户ID"`
|
UserID string `gorm:"type:varchar(36);not null;index" json:"user_id" comment:"关联用户ID"`
|
||||||
|
|
||||||
// 合同基本信息
|
// 合同基本信息
|
||||||
ContractName string `gorm:"type:varchar(255);not null" json:"contract_name" comment:"合同名称"`
|
// ContractCode string `gorm:"type:varchar(255);not null" json:"contract_code" comment:"合同编号"`
|
||||||
ContractType ContractType `gorm:"type:varchar(50);not null;index" json:"contract_type" comment:"合同类型"`
|
ContractName string `gorm:"type:varchar(255);not null" json:"contract_name" comment:"合同名称"`
|
||||||
ContractFileID string `gorm:"type:varchar(100);not null" json:"contract_file_id" comment:"合同文件ID"`
|
ContractType ContractType `gorm:"type:varchar(50);not null;index" json:"contract_type" comment:"合同类型"`
|
||||||
ContractFileURL string `gorm:"type:varchar(500);not null" json:"contract_file_url" comment:"合同文件下载链接"`
|
ContractFileID string `gorm:"type:varchar(100);not null" json:"contract_file_id" comment:"合同文件ID"`
|
||||||
|
ContractFileURL string `gorm:"type:varchar(500);not null" json:"contract_file_url" comment:"合同文件下载链接"`
|
||||||
|
|
||||||
// 时间戳字段
|
// 时间戳字段
|
||||||
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"`
|
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at" comment:"创建时间"`
|
||||||
@@ -83,15 +90,19 @@ func NewContractInfo(enterpriseInfoID, userID, contractName string, contractType
|
|||||||
return nil, fmt.Errorf("无效的合同类型: %s", contractType)
|
return nil, fmt.Errorf("无效的合同类型: %s", contractType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成合同编码
|
||||||
|
// contractCode := GenerateContractCode(contractType)
|
||||||
|
|
||||||
contractInfo := &ContractInfo{
|
contractInfo := &ContractInfo{
|
||||||
ID: uuid.New().String(),
|
ID: uuid.New().String(),
|
||||||
EnterpriseInfoID: enterpriseInfoID,
|
EnterpriseInfoID: enterpriseInfoID,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
ContractName: contractName,
|
// ContractCode: contractCode,
|
||||||
ContractType: contractType,
|
ContractName: contractName,
|
||||||
ContractFileID: contractFileID,
|
ContractType: contractType,
|
||||||
ContractFileURL: contractFileURL,
|
ContractFileID: contractFileID,
|
||||||
domainEvents: make([]interface{}, 0),
|
ContractFileURL: contractFileURL,
|
||||||
|
domainEvents: make([]interface{}, 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加领域事件
|
// 添加领域事件
|
||||||
@@ -99,9 +110,10 @@ func NewContractInfo(enterpriseInfoID, userID, contractName string, contractType
|
|||||||
ContractInfoID: contractInfo.ID,
|
ContractInfoID: contractInfo.ID,
|
||||||
EnterpriseInfoID: enterpriseInfoID,
|
EnterpriseInfoID: enterpriseInfoID,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
ContractName: contractName,
|
// ContractCode: contractCode,
|
||||||
ContractType: string(contractType),
|
ContractName: contractName,
|
||||||
CreatedAt: time.Now(),
|
ContractType: string(contractType),
|
||||||
|
CreatedAt: time.Now(),
|
||||||
})
|
})
|
||||||
|
|
||||||
return contractInfo, nil
|
return contractInfo, nil
|
||||||
@@ -133,14 +145,14 @@ func (c *ContractInfo) UpdateContractInfo(contractName, contractFileID, contract
|
|||||||
|
|
||||||
// 添加领域事件
|
// 添加领域事件
|
||||||
c.addDomainEvent(&ContractInfoUpdatedEvent{
|
c.addDomainEvent(&ContractInfoUpdatedEvent{
|
||||||
ContractInfoID: c.ID,
|
ContractInfoID: c.ID,
|
||||||
EnterpriseInfoID: c.EnterpriseInfoID,
|
EnterpriseInfoID: c.EnterpriseInfoID,
|
||||||
UserID: c.UserID,
|
UserID: c.UserID,
|
||||||
OldContractName: oldContractName,
|
OldContractName: oldContractName,
|
||||||
NewContractName: contractName,
|
NewContractName: contractName,
|
||||||
OldContractFileID: oldContractFileID,
|
OldContractFileID: oldContractFileID,
|
||||||
NewContractFileID: contractFileID,
|
NewContractFileID: contractFileID,
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -186,6 +198,9 @@ func (c *ContractInfo) validateBasicFields() error {
|
|||||||
if c.UserID == "" {
|
if c.UserID == "" {
|
||||||
return fmt.Errorf("用户ID不能为空")
|
return fmt.Errorf("用户ID不能为空")
|
||||||
}
|
}
|
||||||
|
// if c.ContractCode == "" {
|
||||||
|
// return fmt.Errorf("合同编码不能为空")
|
||||||
|
// }
|
||||||
if c.ContractName == "" {
|
if c.ContractName == "" {
|
||||||
return fmt.Errorf("合同名称不能为空")
|
return fmt.Errorf("合同名称不能为空")
|
||||||
}
|
}
|
||||||
@@ -291,12 +306,13 @@ func isValidURL(url string) bool {
|
|||||||
|
|
||||||
// ContractInfoCreatedEvent 合同信息创建事件
|
// ContractInfoCreatedEvent 合同信息创建事件
|
||||||
type ContractInfoCreatedEvent struct {
|
type ContractInfoCreatedEvent struct {
|
||||||
ContractInfoID string `json:"contract_info_id"`
|
ContractInfoID string `json:"contract_info_id"`
|
||||||
EnterpriseInfoID string `json:"enterprise_info_id"`
|
EnterpriseInfoID string `json:"enterprise_info_id"`
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
ContractName string `json:"contract_name"`
|
// ContractCode string `json:"contract_code"`
|
||||||
ContractType string `json:"contract_type"`
|
ContractName string `json:"contract_name"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
ContractType string `json:"contract_type"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractInfoUpdatedEvent 合同信息更新事件
|
// ContractInfoUpdatedEvent 合同信息更新事件
|
||||||
@@ -319,4 +335,25 @@ type ContractInfoDeletedEvent struct {
|
|||||||
ContractName string `json:"contract_name"`
|
ContractName string `json:"contract_name"`
|
||||||
ContractType string `json:"contract_type"`
|
ContractType string `json:"contract_type"`
|
||||||
DeletedAt time.Time `json:"deleted_at"`
|
DeletedAt time.Time `json:"deleted_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateContractCode 生成合同编码
|
||||||
|
func GenerateContractCode(contractType ContractType) string {
|
||||||
|
prefix := "CON"
|
||||||
|
switch contractType {
|
||||||
|
case ContractTypeCooperation:
|
||||||
|
prefix += "01"
|
||||||
|
case ContractTypeReSign:
|
||||||
|
prefix += "02"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前日期,格式为YYMMDD
|
||||||
|
now := time.Now()
|
||||||
|
dateStr := now.Format("060102") // YYMMDD格式
|
||||||
|
|
||||||
|
// 生成一个随机的6位数字
|
||||||
|
randNum := fmt.Sprintf("%06d", rand.Intn(1000000))
|
||||||
|
|
||||||
|
// 格式:CON + 类型标识 + YYMMDD + 6位随机数
|
||||||
|
return fmt.Sprintf("%s%s%s", prefix, dateStr, randNum)
|
||||||
|
}
|
||||||
|
|||||||
194
internal/infrastructure/external/alicloud/README.md
vendored
Normal file
194
internal/infrastructure/external/alicloud/README.md
vendored
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
# 阿里云二要素验证服务
|
||||||
|
|
||||||
|
这个服务提供了调用阿里云身份证二要素验证API的功能,用于验证姓名和身份证号码是否匹配。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- 身份证二要素验证(姓名 + 身份证号)
|
||||||
|
- 支持详细验证结果返回
|
||||||
|
- 支持简单布尔值判断
|
||||||
|
- 错误处理和中文错误信息
|
||||||
|
|
||||||
|
## 配置说明
|
||||||
|
|
||||||
|
### 必需配置
|
||||||
|
|
||||||
|
- `Host`: 阿里云API的域名地址
|
||||||
|
- `AppCode`: 阿里云市场应用的AppCode
|
||||||
|
|
||||||
|
### 配置示例
|
||||||
|
|
||||||
|
```go
|
||||||
|
host := "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
appCode := "您的AppCode"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
### 1. 创建服务实例
|
||||||
|
|
||||||
|
```go
|
||||||
|
service := NewAlicloudService(host, appCode)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 调用API
|
||||||
|
|
||||||
|
#### 身份证二要素验证示例
|
||||||
|
|
||||||
|
```go
|
||||||
|
// 构建请求参数
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": "张三",
|
||||||
|
"idcard": "110101199001011234",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用API
|
||||||
|
responseBody, err := service.CallAPI("api-mall/api/id_card/check", params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("验证失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析完整响应结构
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Birthday string `json:"birthday"`
|
||||||
|
Result int `json:"result"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Sex string `json:"sex"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
log.Printf("响应解析失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if response.Code != 200 {
|
||||||
|
log.Printf("API返回错误: code=%d, msg=%s", response.Code, response.Msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idCardData := response.Data
|
||||||
|
|
||||||
|
// 判断验证结果
|
||||||
|
if idCardData.Result == 1 {
|
||||||
|
fmt.Println("身份证信息验证通过")
|
||||||
|
} else {
|
||||||
|
fmt.Println("身份证信息验证失败")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 通用API调用
|
||||||
|
|
||||||
|
```go
|
||||||
|
// 调用其他阿里云API
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"param1": "value1",
|
||||||
|
"param2": "value2",
|
||||||
|
}
|
||||||
|
|
||||||
|
responseBody, err := service.CallAPI("your/api/path", params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("API调用失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据具体API的响应结构进行解析
|
||||||
|
// 每个API的响应结构可能不同,需要根据API文档定义相应的结构体
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
log.Printf("响应解析失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理响应数据
|
||||||
|
fmt.Printf("响应数据: %s\n", string(responseBody))
|
||||||
|
```
|
||||||
|
|
||||||
|
## 响应格式
|
||||||
|
|
||||||
|
### 通用响应结构
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "成功",
|
||||||
|
"success": true,
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
// 具体的业务数据
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 身份证验证响应示例
|
||||||
|
|
||||||
|
#### 成功响应 (code: 200)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "成功",
|
||||||
|
"success": true,
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"birthday": "19840816",
|
||||||
|
"result": 1,
|
||||||
|
"address": "浙江省杭州市淳安县",
|
||||||
|
"orderNo": "202406271440416095174",
|
||||||
|
"sex": "男",
|
||||||
|
"desc": "不一致"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 参数错误响应 (code: 400)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "请输入有效的身份证号码",
|
||||||
|
"code": 400,
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"msg": "AppCode无效",
|
||||||
|
"success": false,
|
||||||
|
"code": 400
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 错误处理
|
||||||
|
|
||||||
|
服务定义了以下错误类型:
|
||||||
|
|
||||||
|
- `ErrDatasource`: 数据源异常
|
||||||
|
- `ErrSystem`: 系统异常
|
||||||
|
- `ErrInvalid`: 身份证信息不匹配
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 请确保您的AppCode有效且有足够的调用额度
|
||||||
|
2. 身份证号码必须是18位有效格式
|
||||||
|
3. 姓名必须是真实有效的姓名
|
||||||
|
4. 建议在生产环境中添加适当的重试机制和超时设置
|
||||||
|
5. 请遵守阿里云API的使用规范和频率限制
|
||||||
|
|
||||||
|
## 依赖
|
||||||
|
|
||||||
|
- Go 1.16+
|
||||||
|
- 标准库:`net/http`, `encoding/json`, `net/url`
|
||||||
82
internal/infrastructure/external/alicloud/alicloud_service.go
vendored
Normal file
82
internal/infrastructure/external/alicloud/alicloud_service.go
vendored
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package alicloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrDatasource = errors.New("数据源异常")
|
||||||
|
ErrSystem = errors.New("系统异常")
|
||||||
|
)
|
||||||
|
|
||||||
|
// AlicloudConfig 阿里云配置
|
||||||
|
type AlicloudConfig struct {
|
||||||
|
Host string
|
||||||
|
AppCode string
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlicloudService 阿里云服务
|
||||||
|
type AlicloudService struct {
|
||||||
|
config AlicloudConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAlicloudService 创建阿里云服务实例
|
||||||
|
func NewAlicloudService(host, appCode string) *AlicloudService {
|
||||||
|
return &AlicloudService{
|
||||||
|
config: AlicloudConfig{
|
||||||
|
Host: host,
|
||||||
|
AppCode: appCode,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallAPI 调用阿里云API的通用方法
|
||||||
|
// path: API路径(如 "api-mall/api/id_card/check")
|
||||||
|
// params: 请求参数
|
||||||
|
func (a *AlicloudService) CallAPI(path string, params map[string]interface{}) (respBytes []byte, err error) {
|
||||||
|
// 构建请求URL
|
||||||
|
reqURL := a.config.Host + "/" + path
|
||||||
|
|
||||||
|
// 构建请求参数
|
||||||
|
formData := url.Values{}
|
||||||
|
for key, value := range params {
|
||||||
|
formData.Set(key, fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建HTTP请求
|
||||||
|
req, err := http.NewRequest("POST", reqURL, strings.NewReader(formData.Encode()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrSystem, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置请求头
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
|
||||||
|
req.Header.Set("Authorization", "APPCODE "+a.config.AppCode)
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrSystem, err.Error())
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
// 读取响应体
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%w: %s", ErrSystem, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接返回原始响应body,让调用方自己处理
|
||||||
|
return body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetConfig 获取配置信息
|
||||||
|
func (a *AlicloudService) GetConfig() AlicloudConfig {
|
||||||
|
return a.config
|
||||||
|
}
|
||||||
143
internal/infrastructure/external/alicloud/alicloud_service_test.go
vendored
Normal file
143
internal/infrastructure/external/alicloud/alicloud_service_test.go
vendored
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
package alicloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRealAlicloudAPI(t *testing.T) {
|
||||||
|
// 使用真实的阿里云API配置
|
||||||
|
host := "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
appCode := "d55b58829efb41c8aa8e86769cba4844"
|
||||||
|
|
||||||
|
service := NewAlicloudService(host, appCode)
|
||||||
|
|
||||||
|
// 测试真实的身份证验证
|
||||||
|
name := "张荣宏"
|
||||||
|
idCard := "45212220000827423X"
|
||||||
|
|
||||||
|
fmt.Printf("开始测试阿里云二要素验证API...\n")
|
||||||
|
fmt.Printf("姓名: %s\n", name)
|
||||||
|
fmt.Printf("身份证: %s\n", idCard)
|
||||||
|
|
||||||
|
// 构建请求参数
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": name,
|
||||||
|
"idcard": idCard,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用真实API
|
||||||
|
responseBody, err := service.CallAPI("api-mall/api/id_card/check", params)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("API调用失败: %v", err)
|
||||||
|
fmt.Printf("错误详情: %v\n", err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打印原始响应数据
|
||||||
|
fmt.Printf("API响应成功!\n")
|
||||||
|
fmt.Printf("原始响应数据: %s\n", string(responseBody))
|
||||||
|
|
||||||
|
// 解析完整响应结构
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Birthday string `json:"birthday"`
|
||||||
|
Result int `json:"result"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Sex string `json:"sex"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
t.Logf("响应数据解析失败: %v", err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if response.Code != 200 {
|
||||||
|
t.Logf("API返回错误: code=%d, msg=%s", response.Code, response.Msg)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idCardData := response.Data
|
||||||
|
|
||||||
|
// 打印详细响应结果
|
||||||
|
fmt.Printf("验证结果: %d\n", idCardData.Result)
|
||||||
|
fmt.Printf("描述: %s\n", idCardData.Desc)
|
||||||
|
fmt.Printf("生日: %s\n", idCardData.Birthday)
|
||||||
|
fmt.Printf("性别: %s\n", idCardData.Sex)
|
||||||
|
fmt.Printf("地址: %s\n", idCardData.Address)
|
||||||
|
fmt.Printf("订单号: %s\n", idCardData.OrderNo)
|
||||||
|
|
||||||
|
// 将完整响应转换为JSON并打印
|
||||||
|
jsonResponse, _ := json.MarshalIndent(idCardData, "", " ")
|
||||||
|
fmt.Printf("完整响应JSON:\n%s\n", string(jsonResponse))
|
||||||
|
|
||||||
|
// 判断验证结果
|
||||||
|
if idCardData.Result == 1 {
|
||||||
|
fmt.Printf("验证结果: 通过\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("验证结果: 失败\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAlicloudAPIError 测试错误响应
|
||||||
|
func TestAlicloudAPIError(t *testing.T) {
|
||||||
|
// 使用真实的阿里云API配置
|
||||||
|
host := "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
appCode := "d55b58829efb41c8aa8e86769cba4844"
|
||||||
|
|
||||||
|
service := NewAlicloudService(host, appCode)
|
||||||
|
|
||||||
|
// 测试无效的身份证号码
|
||||||
|
name := "张三"
|
||||||
|
invalidIdCard := "123456789"
|
||||||
|
|
||||||
|
fmt.Printf("测试错误响应 - 无效身份证号\n")
|
||||||
|
fmt.Printf("姓名: %s\n", name)
|
||||||
|
fmt.Printf("身份证: %s\n", invalidIdCard)
|
||||||
|
|
||||||
|
// 构建请求参数
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": name,
|
||||||
|
"idcard": invalidIdCard,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用真实API
|
||||||
|
responseBody, err := service.CallAPI("api-mall/api/id_card/check", params)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("网络请求错误: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
fmt.Printf("响应解析失败: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否为错误响应
|
||||||
|
if response.Code != 200 {
|
||||||
|
fmt.Printf("预期的错误响应: code=%d, msg=%s\n", response.Code, response.Msg)
|
||||||
|
fmt.Printf("错误处理正确: API返回错误状态\n")
|
||||||
|
} else {
|
||||||
|
t.Error("期望返回错误,但实际成功")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
76
internal/infrastructure/external/alicloud/example.go
vendored
Normal file
76
internal/infrastructure/external/alicloud/example.go
vendored
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package alicloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExampleUsage 使用示例
|
||||||
|
func ExampleUsage() {
|
||||||
|
// 创建阿里云服务实例
|
||||||
|
// 请替换为您的实际配置
|
||||||
|
host := "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
appCode := "您的AppCode"
|
||||||
|
|
||||||
|
service := NewAlicloudService(host, appCode)
|
||||||
|
|
||||||
|
// 示例:验证身份证信息
|
||||||
|
name := "张三"
|
||||||
|
idCard := "110101199001011234"
|
||||||
|
|
||||||
|
// 构建请求参数
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": name,
|
||||||
|
"idcard": idCard,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用API
|
||||||
|
responseBody, err := service.CallAPI("api-mall/api/id_card/check", params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("验证失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析完整响应结构
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Birthday string `json:"birthday"`
|
||||||
|
Result int `json:"result"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Sex string `json:"sex"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
log.Printf("响应解析失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if response.Code != 200 {
|
||||||
|
log.Printf("API返回错误: code=%d, msg=%s", response.Code, response.Msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idCardData := response.Data
|
||||||
|
|
||||||
|
fmt.Printf("验证结果: %d\n", idCardData.Result)
|
||||||
|
fmt.Printf("描述: %s\n", idCardData.Desc)
|
||||||
|
fmt.Printf("生日: %s\n", idCardData.Birthday)
|
||||||
|
fmt.Printf("性别: %s\n", idCardData.Sex)
|
||||||
|
fmt.Printf("地址: %s\n", idCardData.Address)
|
||||||
|
fmt.Printf("订单号: %s\n", idCardData.OrderNo)
|
||||||
|
|
||||||
|
// 判断验证结果
|
||||||
|
if idCardData.Result == 1 {
|
||||||
|
fmt.Println("身份证信息验证通过")
|
||||||
|
} else {
|
||||||
|
fmt.Println("身份证信息验证失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
162
internal/infrastructure/external/alicloud/example_advanced.go
vendored
Normal file
162
internal/infrastructure/external/alicloud/example_advanced.go
vendored
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
package alicloud
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ExampleAdvancedUsage 高级使用示例
|
||||||
|
func ExampleAdvancedUsage() {
|
||||||
|
// 创建阿里云服务实例
|
||||||
|
host := "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
appCode := "您的AppCode"
|
||||||
|
|
||||||
|
service := NewAlicloudService(host, appCode)
|
||||||
|
|
||||||
|
// 示例1: 身份证二要素验证
|
||||||
|
fmt.Println("=== 示例1: 身份证二要素验证 ===")
|
||||||
|
exampleIdCardCheck(service)
|
||||||
|
|
||||||
|
// 示例2: 其他API调用(假设)
|
||||||
|
fmt.Println("\n=== 示例2: 其他API调用 ===")
|
||||||
|
exampleOtherAPI(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
// exampleIdCardCheck 身份证验证示例
|
||||||
|
func exampleIdCardCheck(service *AlicloudService) {
|
||||||
|
// 构建请求参数
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": "张三",
|
||||||
|
"idcard": "110101199001011234",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用API
|
||||||
|
responseBody, err := service.CallAPI("api-mall/api/id_card/check", params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("身份证验证失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析完整响应结构
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Birthday string `json:"birthday"`
|
||||||
|
Result int `json:"result"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
OrderNo string `json:"orderNo"`
|
||||||
|
Sex string `json:"sex"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
log.Printf("响应解析失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查响应状态
|
||||||
|
if response.Code != 200 {
|
||||||
|
log.Printf("API返回错误: code=%d, msg=%s", response.Code, response.Msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idCardData := response.Data
|
||||||
|
|
||||||
|
// 处理验证结果
|
||||||
|
fmt.Printf("验证结果: %d (%s)\n", idCardData.Result, idCardData.Desc)
|
||||||
|
fmt.Printf("生日: %s\n", idCardData.Birthday)
|
||||||
|
fmt.Printf("性别: %s\n", idCardData.Sex)
|
||||||
|
fmt.Printf("地址: %s\n", idCardData.Address)
|
||||||
|
fmt.Printf("订单号: %s\n", idCardData.OrderNo)
|
||||||
|
|
||||||
|
if idCardData.Result == 1 {
|
||||||
|
fmt.Println("✅ 身份证信息验证通过")
|
||||||
|
} else {
|
||||||
|
fmt.Println("❌ 身份证信息验证失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// exampleOtherAPI 其他API调用示例
|
||||||
|
func exampleOtherAPI(service *AlicloudService) {
|
||||||
|
// 假设调用其他API
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"param1": "value1",
|
||||||
|
"param2": "value2",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用API
|
||||||
|
responseBody, err := service.CallAPI("other/api/path", params)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("API调用失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据具体API的响应结构进行解析
|
||||||
|
// 这里只是示例,实际使用时需要根据API文档定义相应的结构体
|
||||||
|
fmt.Printf("API响应数据: %s\n", string(responseBody))
|
||||||
|
|
||||||
|
// 示例:解析通用响应结构
|
||||||
|
var genericData map[string]interface{}
|
||||||
|
if err := json.Unmarshal(responseBody, &genericData); err != nil {
|
||||||
|
log.Printf("响应解析失败: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("解析后的数据: %+v\n", genericData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExampleErrorHandling 错误处理示例
|
||||||
|
func ExampleErrorHandling() {
|
||||||
|
host := "https://kzidcardv1.market.alicloudapi.com"
|
||||||
|
appCode := "您的AppCode"
|
||||||
|
|
||||||
|
service := NewAlicloudService(host, appCode)
|
||||||
|
|
||||||
|
// 测试各种错误情况
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
idCard string
|
||||||
|
desc string
|
||||||
|
}{
|
||||||
|
{"张三", "123456789", "无效身份证号"},
|
||||||
|
{"", "110101199001011234", "空姓名"},
|
||||||
|
{"张三", "", "空身份证号"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
fmt.Printf("\n测试: %s\n", tc.desc)
|
||||||
|
|
||||||
|
params := map[string]interface{}{
|
||||||
|
"name": tc.name,
|
||||||
|
"idcard": tc.idCard,
|
||||||
|
}
|
||||||
|
|
||||||
|
responseBody, err := service.CallAPI("api-mall/api/id_card/check", params)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("❌ 网络请求错误: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析响应
|
||||||
|
var response struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(responseBody, &response); err != nil {
|
||||||
|
fmt.Printf("❌ 响应解析失败: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Code != 200 {
|
||||||
|
fmt.Printf("❌ 预期错误: code=%d, msg=%s\n", response.Code, response.Msg)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("⚠️ 意外成功\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user