提交 79e83209 authored 作者: 屈传平's avatar 屈传平

慧聪

上级 e2306a22
package hcw
import (
"bytes"
"context"
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/gogf/gf/encoding/gjson"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/util/gconv"
"io"
"strconv"
"time"
)
var server *Config
const pkgName = "hcw"
type Config struct {
AppId string
AppSecret string
ApiUrl string
}
func New(req *Config) {
server = req
return
}
const (
secretKey = "b828a6aa972bcbe5e1e52ce4f24c467f" // 必须32字节
)
type EncryptedResponse struct {
Data []byte `json:"data"`
Timestamp int64 `json:"timestamp"`
Signature string `json:"signature"`
}
func EncryptWithSignature(data interface{}) (string, error) {
// 生成时间戳
timestamp := time.Now().Unix()
// 序列化原始数据
jsonData, err := json.Marshal(data)
if err != nil {
return "", fmt.Errorf("JSON序列化失败: %v", err)
}
// 生成签名字符串
signatureString := string(jsonData) + strconv.FormatInt(timestamp, 10)
// 计算HMAC-SHA256签名
signature := calculateHMAC([]byte(secretKey), signatureString)
// 构建加密数据结构
encryptedData := &EncryptedResponse{
Data: jsonData,
Timestamp: timestamp,
Signature: signature,
}
// 序列化为JSON
encryptedJSON, err := json.Marshal(encryptedData)
if err != nil {
return "", fmt.Errorf("加密数据序列化失败: %v", err)
}
// AES加密
block, err := aes.NewCipher([]byte(secretKey))
if err != nil {
return "", fmt.Errorf("创建加密器失败: %v", err)
}
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", fmt.Errorf("生成IV失败: %v", err)
}
// PKCS#7填充
paddedData := pkcs7Pad(encryptedJSON, aes.BlockSize)
// 执行加密
ciphertext := make([]byte, len(paddedData))
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, paddedData)
// 拼接IV和密文
encryptedBytes := append(iv, ciphertext...)
// Base64编码
return base64.StdEncoding.EncodeToString(encryptedBytes), nil
}
func calculateHMAC(key []byte, data string) string {
h := hmac.New(sha256.New, key)
h.Write([]byte(data))
return fmt.Sprintf("%x", h.Sum(nil))
}
// PKCS#7填充函数
func pkcs7Pad(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padtext...)
}
func post(ctx context.Context, method string, req interface{}) (res string, err error) {
Start := gtime.TimestampMilli()
reqMap := gconv.Map(req)
param := gjson.New(reqMap)
signature, err := EncryptWithSignature(reqMap)
if nil != err {
return
}
Url := server.ApiUrl
Request := g.Client()
Request.SetHeader("Content-Type", "text/xml; charset=utf-8")
Request.SetHeader("Format", "json")
Request.SetHeader("signature", signature)
resp, err := Request.Timeout(time.Second*10).Post(Url, param.MustToJsonString())
defer func() {
_ = resp.Close()
ctx = context.WithValue(ctx, "Method", "POST")
ctx = context.WithValue(ctx, "URI", Url)
if err != nil {
g.Log().Ctx(ctx).Cat(pkgName).Cat("error").Infof("参数【%v】错误【%v】响应时间【%v ms】", param.MustToJsonString(), err.Error(), gtime.TimestampMilli()-Start)
} else {
g.Log().Ctx(ctx).Cat(pkgName).Infof("参数【%v】响应【%v】响应时间【%v ms】", param.MustToJsonString(), res, gtime.TimestampMilli()-Start)
}
}()
res = resp.ReadAllString()
return
}
func get(ctx context.Context, method string, req interface{}) (res string, err error) {
Start := gtime.TimestampMilli()
reqMap := gconv.Map(req)
param := gjson.New(reqMap)
signature, err := EncryptWithSignature(reqMap)
if nil != err {
return
}
Url := server.ApiUrl
Request := g.Client()
Request.SetHeader("Content-Type", "text/xml; charset=utf-8")
Request.SetHeader("Format", "json")
Request.SetHeader("signature", signature)
resp, err := Request.Timeout(time.Second*10).Get(Url, param.MustToJsonString())
defer func() {
_ = resp.Close()
ctx = context.WithValue(ctx, "Method", "POST")
ctx = context.WithValue(ctx, "URI", Url)
if err != nil {
g.Log().Ctx(ctx).Cat(pkgName).Cat("error").Infof("参数【%v】错误【%v】响应时间【%v ms】", param.MustToJsonString(), err.Error(), gtime.TimestampMilli()-Start)
} else {
g.Log().Ctx(ctx).Cat(pkgName).Infof("参数【%v】响应【%v】响应时间【%v ms】", param.MustToJsonString(), res, gtime.TimestampMilli()-Start)
}
}()
res = resp.ReadAllString()
return
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论