new
This commit is contained in:
62
internal/infrastructure/external/xingwei/xingwei_factory.go
vendored
Normal file
62
internal/infrastructure/external/xingwei/xingwei_factory.go
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package xingwei
|
||||
|
||||
import (
|
||||
"tyapi-server/internal/config"
|
||||
"tyapi-server/internal/shared/external_logger"
|
||||
)
|
||||
|
||||
// NewXingweiServiceWithConfig 使用配置创建行为数据服务
|
||||
func NewXingweiServiceWithConfig(cfg *config.Config) (*XingweiService, error) {
|
||||
// 将配置类型转换为通用外部服务日志配置
|
||||
loggingConfig := external_logger.ExternalServiceLoggingConfig{
|
||||
Enabled: cfg.Xingwei.Logging.Enabled,
|
||||
LogDir: cfg.Xingwei.Logging.LogDir,
|
||||
ServiceName: "xingwei",
|
||||
UseDaily: cfg.Xingwei.Logging.UseDaily,
|
||||
EnableLevelSeparation: cfg.Xingwei.Logging.EnableLevelSeparation,
|
||||
LevelConfigs: make(map[string]external_logger.ExternalServiceLevelFileConfig),
|
||||
}
|
||||
|
||||
// 转换级别配置
|
||||
for key, value := range cfg.Xingwei.Logging.LevelConfigs {
|
||||
loggingConfig.LevelConfigs[key] = external_logger.ExternalServiceLevelFileConfig{
|
||||
MaxSize: value.MaxSize,
|
||||
MaxBackups: value.MaxBackups,
|
||||
MaxAge: value.MaxAge,
|
||||
Compress: value.Compress,
|
||||
}
|
||||
}
|
||||
|
||||
// 创建通用外部服务日志器
|
||||
logger, err := external_logger.NewExternalServiceLogger(loggingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建行为数据服务
|
||||
service := NewXingweiService(
|
||||
cfg.Xingwei.URL,
|
||||
cfg.Xingwei.ApiID,
|
||||
cfg.Xingwei.ApiKey,
|
||||
logger,
|
||||
)
|
||||
|
||||
return service, nil
|
||||
}
|
||||
|
||||
// NewXingweiServiceWithLogging 使用自定义日志配置创建行为数据服务
|
||||
func NewXingweiServiceWithLogging(url, apiID, apiKey string, loggingConfig external_logger.ExternalServiceLoggingConfig) (*XingweiService, error) {
|
||||
// 设置服务名称
|
||||
loggingConfig.ServiceName = "xingwei"
|
||||
|
||||
// 创建通用外部服务日志器
|
||||
logger, err := external_logger.NewExternalServiceLogger(loggingConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建行为数据服务
|
||||
service := NewXingweiService(url, apiID, apiKey, logger)
|
||||
|
||||
return service, nil
|
||||
}
|
||||
279
internal/infrastructure/external/xingwei/xingwei_service.go
vendored
Normal file
279
internal/infrastructure/external/xingwei/xingwei_service.go
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
package xingwei
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"tyapi-server/internal/shared/external_logger"
|
||||
)
|
||||
|
||||
// 行为数据API状态码常量
|
||||
const (
|
||||
CodeSuccess = 200 // 操作成功
|
||||
CodeSystemError = 500 // 系统内部错误
|
||||
CodeMerchantError = 3001 // 商家相关报错(商家不存在、商家被禁用、商家余额不足)
|
||||
CodeAccountExpired = 3002 // 账户已过期
|
||||
CodeIPWhitelistMissing = 3003 // 未添加ip白名单
|
||||
CodeUnauthorized = 3004 // 未授权调用该接口
|
||||
CodeProductIDError = 4001 // 产品id错误
|
||||
CodeInterfaceDisabled = 4002 // 接口被停用
|
||||
CodeQueryException = 5001 // 接口查询异常,请联系技术人员
|
||||
CodeNotFound = 6000 // 未查询到结果
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDatasource = errors.New("数据源异常")
|
||||
ErrSystem = errors.New("系统异常")
|
||||
ErrNotFound = errors.New("未查询到结果")
|
||||
|
||||
// 请求ID计数器,确保唯一性
|
||||
requestIDCounter int64
|
||||
)
|
||||
|
||||
// XingweiResponse 行为数据API响应结构
|
||||
type XingweiResponse struct {
|
||||
Msg string `json:"msg"`
|
||||
Code int `json:"code"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
// XingweiErrorCode 行为数据错误码定义
|
||||
type XingweiErrorCode struct {
|
||||
Code int
|
||||
Message string
|
||||
}
|
||||
|
||||
// 行为数据错误码映射
|
||||
var XingweiErrorCodes = map[int]XingweiErrorCode{
|
||||
CodeSuccess: {Code: CodeSuccess, Message: "操作成功"},
|
||||
CodeSystemError: {Code: CodeSystemError, Message: "系统内部错误"},
|
||||
CodeMerchantError: {Code: CodeMerchantError, Message: "商家相关报错(商家不存在、商家被禁用、商家余额不足)"},
|
||||
CodeAccountExpired: {Code: CodeAccountExpired, Message: "账户已过期"},
|
||||
CodeIPWhitelistMissing: {Code: CodeIPWhitelistMissing, Message: "未添加ip白名单"},
|
||||
CodeUnauthorized: {Code: CodeUnauthorized, Message: "未授权调用该接口"},
|
||||
CodeProductIDError: {Code: CodeProductIDError, Message: "产品id错误"},
|
||||
CodeInterfaceDisabled: {Code: CodeInterfaceDisabled, Message: "接口被停用"},
|
||||
CodeQueryException: {Code: CodeQueryException, Message: "接口查询异常,请联系技术人员"},
|
||||
CodeNotFound: {Code: CodeNotFound, Message: "未查询到结果"},
|
||||
}
|
||||
|
||||
// GetXingweiErrorMessage 根据错误码获取错误消息
|
||||
func GetXingweiErrorMessage(code int) string {
|
||||
if errorCode, exists := XingweiErrorCodes[code]; exists {
|
||||
return errorCode.Message
|
||||
}
|
||||
return fmt.Sprintf("未知错误码: %d", code)
|
||||
}
|
||||
|
||||
type XingweiConfig struct {
|
||||
URL string
|
||||
ApiID string
|
||||
ApiKey string
|
||||
}
|
||||
|
||||
type XingweiService struct {
|
||||
config XingweiConfig
|
||||
logger *external_logger.ExternalServiceLogger
|
||||
}
|
||||
|
||||
// NewXingweiService 是一个构造函数,用于初始化 XingweiService
|
||||
func NewXingweiService(url, apiID, apiKey string, logger *external_logger.ExternalServiceLogger) *XingweiService {
|
||||
return &XingweiService{
|
||||
config: XingweiConfig{
|
||||
URL: url,
|
||||
ApiID: apiID,
|
||||
ApiKey: apiKey,
|
||||
},
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// generateRequestID 生成请求ID
|
||||
func (x *XingweiService) generateRequestID() string {
|
||||
timestamp := time.Now().UnixNano()
|
||||
// 使用原子计数器确保唯一性
|
||||
counter := atomic.AddInt64(&requestIDCounter, 1)
|
||||
hash := md5.Sum([]byte(fmt.Sprintf("%d_%d_%s", timestamp, counter, x.config.ApiID)))
|
||||
return fmt.Sprintf("xingwei_%x", hash[:8])
|
||||
}
|
||||
|
||||
// createSign 创建签名:使用MD5算法将apiId、timestamp、apiKey字符串拼接生成sign
|
||||
// 参考Java示例:DigestUtils.md5Hex(apiId + timestamp + apiKey)
|
||||
func (x *XingweiService) createSign(timestamp int64) string {
|
||||
signStr := x.config.ApiID + strconv.FormatInt(timestamp, 10) + x.config.ApiKey
|
||||
hash := md5.Sum([]byte(signStr))
|
||||
return fmt.Sprintf("%x", hash)
|
||||
}
|
||||
|
||||
// CallAPI 调用行为数据的 API
|
||||
func (x *XingweiService) CallAPI(ctx context.Context, projectID string, params map[string]interface{}) (resp []byte, err error) {
|
||||
startTime := time.Now()
|
||||
requestID := x.generateRequestID()
|
||||
timestamp := time.Now().UnixMilli()
|
||||
|
||||
// 从ctx中获取transactionId
|
||||
var transactionID string
|
||||
if ctxTransactionID, ok := ctx.Value("transaction_id").(string); ok {
|
||||
transactionID = ctxTransactionID
|
||||
}
|
||||
|
||||
// 记录请求日志
|
||||
if x.logger != nil {
|
||||
x.logger.LogRequest(requestID, transactionID, "xingwei_api", x.config.URL, params)
|
||||
}
|
||||
|
||||
// 将请求参数转换为JSON
|
||||
jsonData, marshalErr := json.Marshal(params)
|
||||
if marshalErr != nil {
|
||||
err = errors.Join(ErrSystem, marshalErr)
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建HTTP POST请求
|
||||
req, newRequestErr := http.NewRequestWithContext(ctx, "POST", x.config.URL, bytes.NewBuffer(jsonData))
|
||||
if newRequestErr != nil {
|
||||
err = errors.Join(ErrSystem, newRequestErr)
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置请求头
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("timestamp", strconv.FormatInt(timestamp, 10))
|
||||
req.Header.Set("sign", x.createSign(timestamp))
|
||||
req.Header.Set("API-ID", x.config.ApiID)
|
||||
req.Header.Set("project_id", projectID)
|
||||
|
||||
// 创建HTTP客户端
|
||||
client := &http.Client{
|
||||
Timeout: 20 * time.Second,
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
httpResp, clientDoErr := client.Do(req)
|
||||
if clientDoErr != nil {
|
||||
err = errors.Join(ErrSystem, clientDoErr)
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
defer func(Body io.ReadCloser) {
|
||||
closeErr := Body.Close()
|
||||
if closeErr != nil {
|
||||
// 记录关闭错误
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", errors.Join(ErrSystem, fmt.Errorf("关闭响应体失败: %w", closeErr)), params)
|
||||
}
|
||||
}
|
||||
}(httpResp.Body)
|
||||
|
||||
// 计算请求耗时
|
||||
duration := time.Since(startTime)
|
||||
|
||||
// 读取响应体
|
||||
bodyBytes, ReadErr := io.ReadAll(httpResp.Body)
|
||||
if ReadErr != nil {
|
||||
err = errors.Join(ErrSystem, ReadErr)
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 记录响应日志
|
||||
if x.logger != nil {
|
||||
x.logger.LogResponse(requestID, transactionID, "xingwei_api", httpResp.StatusCode, bodyBytes, duration)
|
||||
}
|
||||
|
||||
// 检查HTTP状态码
|
||||
if httpResp.StatusCode != http.StatusOK {
|
||||
err = errors.Join(ErrSystem, fmt.Errorf("行为数据请求失败,状态码: %d", httpResp.StatusCode))
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 解析响应结构
|
||||
var xingweiResp XingweiResponse
|
||||
if err := json.Unmarshal(bodyBytes, &xingweiResp); err != nil {
|
||||
err = errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err))
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查业务状态码
|
||||
switch xingweiResp.Code {
|
||||
case CodeSuccess:
|
||||
// 成功响应,返回data字段
|
||||
if xingweiResp.Data == nil {
|
||||
return []byte("{}"), nil
|
||||
}
|
||||
|
||||
// 将data转换为JSON字节
|
||||
dataBytes, err := json.Marshal(xingweiResp.Data)
|
||||
if err != nil {
|
||||
err = errors.Join(ErrSystem, fmt.Errorf("data字段序列化失败: %w", err))
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api", err, params)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dataBytes, nil
|
||||
|
||||
case CodeNotFound:
|
||||
// 未查询到结果,返回查空错误
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api",
|
||||
errors.Join(ErrNotFound, fmt.Errorf("未查询到结果")), params)
|
||||
}
|
||||
return nil, errors.Join(ErrNotFound, fmt.Errorf("未查询到结果"))
|
||||
|
||||
case CodeSystemError:
|
||||
// 系统内部错误
|
||||
errorMsg := GetXingweiErrorMessage(xingweiResp.Code)
|
||||
systemErr := fmt.Errorf("行为数据系统错误[%d]: %s", xingweiResp.Code, errorMsg)
|
||||
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api",
|
||||
errors.Join(ErrSystem, systemErr), params)
|
||||
}
|
||||
|
||||
return nil, errors.Join(ErrSystem, systemErr)
|
||||
|
||||
default:
|
||||
// 其他业务错误
|
||||
errorMsg := GetXingweiErrorMessage(xingweiResp.Code)
|
||||
businessErr := fmt.Errorf("行为数据业务错误[%d]: %s", xingweiResp.Code, errorMsg)
|
||||
|
||||
if x.logger != nil {
|
||||
x.logger.LogError(requestID, transactionID, "xingwei_api",
|
||||
errors.Join(ErrDatasource, businessErr), params)
|
||||
}
|
||||
|
||||
return nil, errors.Join(ErrDatasource, businessErr)
|
||||
}
|
||||
}
|
||||
|
||||
// GetConfig 获取配置信息
|
||||
func (x *XingweiService) GetConfig() XingweiConfig {
|
||||
return x.config
|
||||
}
|
||||
241
internal/infrastructure/external/xingwei/xingwei_test.go
vendored
Normal file
241
internal/infrastructure/external/xingwei/xingwei_test.go
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
package xingwei
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestXingweiService_CreateSign(t *testing.T) {
|
||||
// 创建测试配置 - 使用nil logger来避免日志问题
|
||||
service := NewXingweiService(
|
||||
"https://sjztyh.chengdaoji.cn/dataCenterManageApi/manage/interface/doc/api/handle",
|
||||
"test_api_id",
|
||||
"test_api_key",
|
||||
nil, // 使用nil logger
|
||||
)
|
||||
|
||||
// 测试签名生成
|
||||
timestamp := int64(1743474772049)
|
||||
sign := service.createSign(timestamp)
|
||||
|
||||
// 验证签名不为空
|
||||
if sign == "" {
|
||||
t.Error("签名不能为空")
|
||||
}
|
||||
|
||||
// 验证签名长度(MD5应该是32位十六进制字符串)
|
||||
if len(sign) != 32 {
|
||||
t.Errorf("签名长度应该是32位,实际是%d位", len(sign))
|
||||
}
|
||||
|
||||
t.Logf("生成的签名: %s", sign)
|
||||
}
|
||||
|
||||
func TestXingweiService_CallAPI(t *testing.T) {
|
||||
// 创建测试配置 - 使用nil logger来避免日志问题
|
||||
service := NewXingweiService(
|
||||
"https://sjztyh.chengdaoji.cn/dataCenterManageApi/manage/interface/doc/api/handle",
|
||||
"test_api_id",
|
||||
"test_api_key",
|
||||
nil, // 使用nil logger
|
||||
)
|
||||
|
||||
// 创建测试上下文
|
||||
ctx := context.Background()
|
||||
|
||||
// 测试参数
|
||||
projectID := "test_project_id"
|
||||
params := map[string]interface{}{
|
||||
"test_param": "test_value",
|
||||
}
|
||||
|
||||
// 注意:这个测试会实际发送HTTP请求,所以可能会失败
|
||||
// 在实际使用中,应该使用mock或者测试服务器
|
||||
resp, err := service.CallAPI(ctx, projectID, params)
|
||||
|
||||
// 由于这是真实的外部API调用,我们主要测试错误处理
|
||||
if err != nil {
|
||||
t.Logf("预期的错误(真实API调用): %v", err)
|
||||
} else {
|
||||
t.Logf("API调用成功,响应长度: %d", len(resp))
|
||||
}
|
||||
}
|
||||
|
||||
func TestXingweiService_GenerateRequestID(t *testing.T) {
|
||||
// 创建测试配置 - 使用nil logger来避免日志问题
|
||||
service := NewXingweiService(
|
||||
"https://sjztyh.chengdaoji.cn/dataCenterManageApi/manage/interface/doc/api/handle",
|
||||
"test_api_id",
|
||||
"test_api_key",
|
||||
nil, // 使用nil logger
|
||||
)
|
||||
|
||||
// 测试请求ID生成
|
||||
requestID1 := service.generateRequestID()
|
||||
requestID2 := service.generateRequestID()
|
||||
|
||||
// 验证请求ID不为空
|
||||
if requestID1 == "" || requestID2 == "" {
|
||||
t.Error("请求ID不能为空")
|
||||
}
|
||||
|
||||
// 验证请求ID应该以xingwei_开头
|
||||
if len(requestID1) < 8 || requestID1[:8] != "xingwei_" {
|
||||
t.Error("请求ID应该以xingwei_开头")
|
||||
}
|
||||
|
||||
// 验证两次生成的请求ID应该不同
|
||||
if requestID1 == requestID2 {
|
||||
t.Error("两次生成的请求ID应该不同")
|
||||
}
|
||||
|
||||
t.Logf("请求ID1: %s", requestID1)
|
||||
t.Logf("请求ID2: %s", requestID2)
|
||||
}
|
||||
|
||||
func TestGetXingweiErrorMessage(t *testing.T) {
|
||||
// 测试已知错误码(使用常量)
|
||||
testCases := []struct {
|
||||
code int
|
||||
expected string
|
||||
}{
|
||||
{CodeSuccess, "操作成功"},
|
||||
{CodeSystemError, "系统内部错误"},
|
||||
{CodeMerchantError, "商家相关报错(商家不存在、商家被禁用、商家余额不足)"},
|
||||
{CodeAccountExpired, "账户已过期"},
|
||||
{CodeIPWhitelistMissing, "未添加ip白名单"},
|
||||
{CodeUnauthorized, "未授权调用该接口"},
|
||||
{CodeProductIDError, "产品id错误"},
|
||||
{CodeInterfaceDisabled, "接口被停用"},
|
||||
{CodeQueryException, "接口查询异常,请联系技术人员"},
|
||||
{CodeNotFound, "未查询到结果"},
|
||||
{9999, "未知错误码: 9999"}, // 测试未知错误码
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
result := GetXingweiErrorMessage(tc.code)
|
||||
if result != tc.expected {
|
||||
t.Errorf("错误码 %d 的消息不正确,期望: %s, 实际: %s", tc.code, tc.expected, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestXingweiResponseParsing(t *testing.T) {
|
||||
// 测试响应结构解析
|
||||
testCases := []struct {
|
||||
name string
|
||||
response string
|
||||
expectedCode int
|
||||
}{
|
||||
{
|
||||
name: "成功响应",
|
||||
response: `{"msg": "操作成功", "code": 200, "data": {"result": "test"}}`,
|
||||
expectedCode: CodeSuccess,
|
||||
},
|
||||
{
|
||||
name: "商家错误",
|
||||
response: `{"msg": "商家相关报错", "code": 3001, "data": null}`,
|
||||
expectedCode: CodeMerchantError,
|
||||
},
|
||||
{
|
||||
name: "未查询到结果",
|
||||
response: `{"msg": "未查询到结果", "code": 6000, "data": null}`,
|
||||
expectedCode: CodeNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var resp XingweiResponse
|
||||
err := json.Unmarshal([]byte(tc.response), &resp)
|
||||
if err != nil {
|
||||
t.Errorf("解析响应失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if resp.Code != tc.expectedCode {
|
||||
t.Errorf("错误码不匹配,期望: %d, 实际: %d", tc.expectedCode, resp.Code)
|
||||
}
|
||||
|
||||
// 测试错误消息获取
|
||||
errorMsg := GetXingweiErrorMessage(resp.Code)
|
||||
if errorMsg == "" {
|
||||
t.Errorf("无法获取错误码 %d 的消息", resp.Code)
|
||||
}
|
||||
|
||||
t.Logf("响应: %+v, 错误消息: %s", resp, errorMsg)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestXingweiErrorHandling 测试错误处理逻辑
|
||||
func TestXingweiErrorHandling(t *testing.T) {
|
||||
// 注意:这个测试主要验证常量定义和错误消息,不需要实际的服务实例
|
||||
|
||||
// 测试查空错误
|
||||
t.Run("NotFound错误", func(t *testing.T) {
|
||||
// 模拟返回查空响应
|
||||
response := `{"msg": "未查询到结果", "code": 6000, "data": null}`
|
||||
var xingweiResp XingweiResponse
|
||||
err := json.Unmarshal([]byte(response), &xingweiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证状态码
|
||||
if xingweiResp.Code != CodeNotFound {
|
||||
t.Errorf("期望状态码 %d, 实际 %d", CodeNotFound, xingweiResp.Code)
|
||||
}
|
||||
|
||||
// 验证错误消息
|
||||
errorMsg := GetXingweiErrorMessage(xingweiResp.Code)
|
||||
if errorMsg != "未查询到结果" {
|
||||
t.Errorf("期望错误消息 '未查询到结果', 实际 '%s'", errorMsg)
|
||||
}
|
||||
|
||||
t.Logf("查空错误测试通过: 状态码=%d, 消息=%s", xingweiResp.Code, errorMsg)
|
||||
})
|
||||
|
||||
// 测试系统错误
|
||||
t.Run("SystemError错误", func(t *testing.T) {
|
||||
response := `{"msg": "系统内部错误", "code": 500, "data": null}`
|
||||
var xingweiResp XingweiResponse
|
||||
err := json.Unmarshal([]byte(response), &xingweiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
if xingweiResp.Code != CodeSystemError {
|
||||
t.Errorf("期望状态码 %d, 实际 %d", CodeSystemError, xingweiResp.Code)
|
||||
}
|
||||
|
||||
errorMsg := GetXingweiErrorMessage(xingweiResp.Code)
|
||||
if errorMsg != "系统内部错误" {
|
||||
t.Errorf("期望错误消息 '系统内部错误', 实际 '%s'", errorMsg)
|
||||
}
|
||||
|
||||
t.Logf("系统错误测试通过: 状态码=%d, 消息=%s", xingweiResp.Code, errorMsg)
|
||||
})
|
||||
|
||||
// 测试成功响应
|
||||
t.Run("Success响应", func(t *testing.T) {
|
||||
response := `{"msg": "操作成功", "code": 200, "data": {"result": "test"}}`
|
||||
var xingweiResp XingweiResponse
|
||||
err := json.Unmarshal([]byte(response), &xingweiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
if xingweiResp.Code != CodeSuccess {
|
||||
t.Errorf("期望状态码 %d, 实际 %d", CodeSuccess, xingweiResp.Code)
|
||||
}
|
||||
|
||||
errorMsg := GetXingweiErrorMessage(xingweiResp.Code)
|
||||
if errorMsg != "操作成功" {
|
||||
t.Errorf("期望错误消息 '操作成功', 实际 '%s'", errorMsg)
|
||||
}
|
||||
|
||||
t.Logf("成功响应测试通过: 状态码=%d, 消息=%s", xingweiResp.Code, errorMsg)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user