173 lines
4.8 KiB
Go
173 lines
4.8 KiB
Go
package requestUtil
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"net/http"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
_type "xianyv/type"
|
||
"xianyv/utils/md5Util"
|
||
)
|
||
|
||
// MakeAPIRequest 通用API请求函数
|
||
func MakeAPIRequest(appId int, appSecret, domain, path string, requestData interface{}) ([]byte, error) {
|
||
// json格式化
|
||
bytesData, err := json.Marshal(requestData)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("JSON序列化错误: %v", err)
|
||
}
|
||
// 发起请求时的时间戳(秒)
|
||
timestamp := time.Now().Unix()
|
||
// 获取签名
|
||
sign := md5Util.GenSign(appId, appSecret, timestamp, bytesData)
|
||
|
||
fmt.Printf("sign: %v \n", sign)
|
||
// 请求url
|
||
url := fmt.Sprintf("%v%v?appid=%v×tamp=%v&sign=%v", domain, path, appId, timestamp, sign)
|
||
fmt.Printf("请求url: %v \n", url)
|
||
// 发起请求,使用带超时的 client 并限制可读取的响应大小,防止对端返回过大内容导致 OOM
|
||
client := &http.Client{Timeout: 30 * time.Second}
|
||
|
||
resp, err := client.Post(url, "application/json", bytes.NewReader(bytesData))
|
||
if err != nil {
|
||
req := _type.ErrResponse{
|
||
Code: 0,
|
||
Msg: fmt.Errorf("HTTP请求错误: %v", err).Error(),
|
||
Data: nil,
|
||
}
|
||
response, _ := json.Marshal(req)
|
||
return response, err
|
||
}
|
||
fmt.Printf("响应: %v \n", resp)
|
||
defer resp.Body.Close()
|
||
|
||
// 限制最大可读响应大小,例如 10MB(视实际需求调整)
|
||
const maxRespBytes = 10 * 1024 * 1024 // 10MB
|
||
limitedReader := io.LimitReader(resp.Body, maxRespBytes+1)
|
||
|
||
body, err := io.ReadAll(limitedReader)
|
||
if err != nil {
|
||
req := _type.ErrResponse{
|
||
Code: 0,
|
||
Msg: fmt.Errorf("读取响应错误: %v", err).Error(),
|
||
Data: nil,
|
||
}
|
||
response, _ := json.Marshal(req)
|
||
return response, err
|
||
}
|
||
|
||
// 如果响应超过限制,返回错误
|
||
if int64(len(body)) > 10*1024*1024 {
|
||
req := _type.ErrResponse{
|
||
Code: 0,
|
||
Msg: fmt.Errorf("响应大小超过限制: %d bytes", len(body)).Error(),
|
||
Data: nil,
|
||
}
|
||
response, _ := json.Marshal(req)
|
||
return response, fmt.Errorf("response too large: %d bytes", len(body))
|
||
}
|
||
|
||
return body, nil
|
||
}
|
||
|
||
// RequestParams 解析请求参数
|
||
func RequestParams(r *http.Request) (_type.Body, error) {
|
||
var body _type.Body
|
||
var err error
|
||
|
||
// 转换各个字段
|
||
appIdStr := r.FormValue("appId")
|
||
body.AppSecret = r.FormValue("appSecret")
|
||
body.OuterId = r.FormValue("token")
|
||
body.Token = r.FormValue("token")
|
||
apiShopIdStr := r.FormValue("apiShopId")
|
||
typePlatformStr := r.FormValue("typePlatform")
|
||
shopIdStr := r.FormValue("shopId")
|
||
body.ShopToken = r.FormValue("shopToken")
|
||
body.ShopName = r.FormValue("shopName")
|
||
provinceStr := r.FormValue("province")
|
||
cityStr := r.FormValue("city")
|
||
districtStr := r.FormValue("district")
|
||
body.TypeClass = r.FormValue("typeClass")
|
||
body.TypeGoods = r.FormValue("typeGoods")
|
||
body.CatIds = r.FormValue("catIds")
|
||
shopStr := r.FormValue("shop[]")
|
||
stuffStatusStr := r.FormValue("stuffStatus")
|
||
bookDataStr := r.FormValue("bookData[]")
|
||
body.ItemKey = r.FormValue("itemKey")
|
||
body.OuterId = r.FormValue("outerId")
|
||
|
||
// 转换数值参数
|
||
body.AppId, _ = strconv.Atoi(appIdStr)
|
||
body.ApiShopId, _ = strconv.Atoi(apiShopIdStr)
|
||
body.TypePlatform, _ = strconv.Atoi(typePlatformStr)
|
||
body.ShopId, _ = strconv.Atoi(shopIdStr)
|
||
if i, err := strconv.ParseInt(provinceStr, 10, 32); err == nil {
|
||
body.Province = int32(i)
|
||
} else {
|
||
body.Province = 0
|
||
}
|
||
if i, err := strconv.ParseInt(cityStr, 10, 32); err == nil {
|
||
body.City = int32(i)
|
||
} else {
|
||
body.City = 0
|
||
}
|
||
if i, err := strconv.ParseInt(districtStr, 10, 32); err == nil {
|
||
body.District = int32(i)
|
||
} else {
|
||
body.District = 0
|
||
}
|
||
body.StuffStatus, _ = strconv.Atoi(stuffStatusStr)
|
||
|
||
// shop非空校验,修复字符编码问题
|
||
if shopStr != "" {
|
||
|
||
// 清理可能的非法字符
|
||
shopStr = strings.TrimSpace(shopStr)
|
||
shopStr = strings.Trim(shopStr, `"'`)
|
||
|
||
// 移除BOM标记
|
||
if strings.HasPrefix(shopStr, "\uFEFF") {
|
||
shopStr = strings.TrimPrefix(shopStr, "\uFEFF")
|
||
}
|
||
|
||
err = json.Unmarshal([]byte(shopStr), &body.Shop)
|
||
if err != nil {
|
||
log.Printf("JSON格式错误,Shop: %v", err)
|
||
log.Printf("错误数据内容: %s", shopStr)
|
||
return body, fmt.Errorf("JSON格式错误,Shop: %v", err)
|
||
}
|
||
} else {
|
||
log.Println("Shop不应为空")
|
||
return body, errors.New("Shop不应为空")
|
||
}
|
||
|
||
// bookData非空校验,修复字符编码问题
|
||
if bookDataStr != "" {
|
||
|
||
bookDataStr = strings.TrimSpace(bookDataStr)
|
||
bookDataStr = strings.Trim(bookDataStr, `"'`)
|
||
|
||
if strings.HasPrefix(bookDataStr, "\uFEFF") {
|
||
bookDataStr = strings.TrimPrefix(bookDataStr, "\uFEFF")
|
||
}
|
||
|
||
err = json.Unmarshal([]byte(bookDataStr), &body.BookData)
|
||
if err != nil {
|
||
log.Printf("JSON格式错误,解析bookData: %v", err)
|
||
return body, fmt.Errorf("JSON格式错误,解析bookData: %v", err)
|
||
}
|
||
} else {
|
||
log.Printf("bookData不应为空")
|
||
return body, errors.New("bookData不应为空")
|
||
}
|
||
|
||
return body, err
|
||
}
|