Files
tyapi-server/internal/infrastructure/external/alicloud/alicloud_service.go
2026-03-21 18:36:42 +08:00

143 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package alicloud
import (
"crypto/md5"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
"tyapi-server/internal/shared/external_logger"
)
var (
ErrDatasource = errors.New("数据源异常")
ErrSystem = errors.New("系统异常")
)
// AlicloudConfig 阿里云配置
type AlicloudConfig struct {
Host string
AppCode string
}
// AlicloudService 阿里云服务
type AlicloudService struct {
config AlicloudConfig
logger *external_logger.ExternalServiceLogger
}
// NewAlicloudService 创建阿里云服务实例
func NewAlicloudService(host, appCode string, logger ...*external_logger.ExternalServiceLogger) *AlicloudService {
var serviceLogger *external_logger.ExternalServiceLogger
if len(logger) > 0 {
serviceLogger = logger[0]
}
return &AlicloudService{
config: AlicloudConfig{
Host: host,
AppCode: appCode,
},
logger: serviceLogger,
}
}
// generateRequestID 生成请求ID
func (a *AlicloudService) generateRequestID() string {
timestamp := time.Now().UnixNano()
hash := md5.Sum([]byte(fmt.Sprintf("%d_%s", timestamp, a.config.Host)))
return fmt.Sprintf("alicloud_%x", hash[:8])
}
// 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) {
startTime := time.Now()
requestID := a.generateRequestID()
transactionID := ""
// 构建请求URL
reqURL := a.config.Host + "/" + path
// 记录请求日志
if a.logger != nil {
a.logger.LogRequest(requestID, transactionID, path, reqURL)
}
// 构建请求参数
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 {
if a.logger != nil {
a.logger.LogError(requestID, transactionID, path, errors.Join(ErrSystem, err), params)
}
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)
// 发送请求超时时间设置为60秒
client := &http.Client{
Timeout: 60 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
// 检查是否是超时错误
isTimeout := false
if netErr, ok := err.(interface{ Timeout() bool }); ok && netErr.Timeout() {
isTimeout = true
} else if errStr := err.Error();
errStr == "context deadline exceeded" ||
errStr == "timeout" ||
errStr == "Client.Timeout exceeded" ||
errStr == "net/http: request canceled" {
isTimeout = true
}
if isTimeout {
if a.logger != nil {
a.logger.LogError(requestID, transactionID, path, errors.Join(ErrDatasource, fmt.Errorf("API请求超时: %s", err.Error())), params)
}
return nil, fmt.Errorf("%w: API请求超时: %s", ErrDatasource, err.Error())
}
if a.logger != nil {
a.logger.LogError(requestID, transactionID, path, errors.Join(ErrSystem, err), params)
}
return nil, fmt.Errorf("%w: %s", ErrSystem, err.Error())
}
defer resp.Body.Close()
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
if a.logger != nil {
a.logger.LogError(requestID, transactionID, path, errors.Join(ErrSystem, err), params)
}
return nil, fmt.Errorf("%w: %s", ErrSystem, err.Error())
}
// 记录响应日志(不记录具体响应数据)
if a.logger != nil {
duration := time.Since(startTime)
a.logger.LogResponse(requestID, transactionID, path, resp.StatusCode, duration)
}
// 直接返回原始响应body让调用方自己处理
return body, nil
}
// GetConfig 获取配置信息
func (a *AlicloudService) GetConfig() AlicloudConfig {
return a.config
}