237 lines
6.4 KiB
Go
237 lines
6.4 KiB
Go
package lakala
|
||
|
||
import (
|
||
"bytes"
|
||
"crypto"
|
||
"crypto/rand"
|
||
"crypto/rsa"
|
||
"crypto/sha256"
|
||
"crypto/x509"
|
||
"encoding/base64"
|
||
"encoding/json"
|
||
"encoding/pem"
|
||
"fmt"
|
||
"git.rosy.net.cn/baseapi/utils"
|
||
"github.com/tjfoc/gmsm/sm4"
|
||
"io"
|
||
"io/ioutil"
|
||
"math/big"
|
||
"mime/multipart"
|
||
"net/http"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// IncomingToken 进件api,token获取
|
||
func (a *API) IncomingToken() (comingToken string, expiresIn int64, err error) {
|
||
result, err := a.AccessAPI(IncomingUrlTest, TokenActive, http.MethodPost, "", map[string]interface{}{
|
||
"grant_type": "client_credentials",
|
||
"client_id": a.clientId,
|
||
"client_secret": a.clientSecret,
|
||
})
|
||
if err != nil {
|
||
return "", 0, err
|
||
}
|
||
expiresIn, err = utils.TryInterface2Int64(result["expires_in"])
|
||
if err != nil {
|
||
return "", 0, err
|
||
}
|
||
a.incomingToken = result["access_token"].(string)
|
||
a.incomingExpire = time.Now().Unix() + expiresIn
|
||
return a.incomingToken, a.incomingExpire, nil
|
||
}
|
||
|
||
// ModifiedToken 更新token获取
|
||
func (a *API) ModifiedToken(userName string, password string) (modifiedToken string, modifiedExpire int64, err error) {
|
||
result, err := a.AccessAPI(IncomingUrlTest, TokenActive, http.MethodPost, "", map[string]interface{}{
|
||
"grant_type": "password",
|
||
"username": userName,
|
||
"password": password,
|
||
})
|
||
|
||
if err != nil {
|
||
return "", 0, err
|
||
}
|
||
modifiedExpire, err = utils.TryInterface2Int64(result["expires_in"])
|
||
if err != nil {
|
||
return "", 0, err
|
||
}
|
||
a.modifiedToken = result["access_token"].(string)
|
||
a.modifiedExpire = time.Now().Unix() + modifiedExpire
|
||
return a.modifiedToken, a.modifiedExpire, nil
|
||
}
|
||
|
||
// FileUpload 文件上传下载 filePath:文件url,由于controller:swagger不支持文件类型
|
||
func (a *API) FileUpload(filePath, imgType, sourcechnl, isOcr string) (*UploadImgResp, error) {
|
||
client := &http.Client{}
|
||
// 获取问价
|
||
resp, err := client.Get(filePath)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
imgData, _ := ioutil.ReadAll(resp.Body)
|
||
defer resp.Body.Close()
|
||
|
||
// 创建一个缓冲区来构建 multipart 请求
|
||
body := &bytes.Buffer{}
|
||
writer := multipart.NewWriter(body)
|
||
|
||
// 添加文件到 multipart 请求
|
||
part, err := writer.CreateFormFile("file", filePath)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
_, err = io.Copy(part, strings.NewReader(string(imgData)))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 添加其他表单字段
|
||
writer.WriteField("imgType", imgType)
|
||
writer.WriteField("sourcechnl", sourcechnl)
|
||
writer.WriteField("isOcr", isOcr)
|
||
|
||
// 关闭 writer
|
||
err = writer.Close()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 创建 HTTP 请求
|
||
req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s", BaseTestUrl, FileUpload), body)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 设置 Content-Type 头
|
||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||
req.Header.Set("Authorization", fmt.Sprintf("bearer %s", a.incomingToken))
|
||
|
||
// 发送请求
|
||
resp, err = client.Do(req)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 读取响应
|
||
data, err := ioutil.ReadAll(resp.Body)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
img := &UploadImgResp{}
|
||
json.Unmarshal(data, img)
|
||
|
||
return img, err
|
||
}
|
||
|
||
type UploadImgResp struct {
|
||
BatchNo interface{} `json:"batchNo"` // 批量号
|
||
Status string `json:"status"` // 00 成功, 01 正在处理中, 02 失败
|
||
Url string `json:"url"` // 拉卡拉文件地址
|
||
ShowUrl string `json:"showUrl"` // 拉卡拉文件url
|
||
Result interface{} `json:"result"` //
|
||
}
|
||
|
||
// signParamRSA 支付签名
|
||
func (a *API) signParamRSA(params map[string]interface{}, RSAPrivate string) (sig string, err error) {
|
||
block, _ := pem.Decode([]byte(RSAPrivate))
|
||
private, err := x509.ParsePKCS8PrivateKey(block.Bytes)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
// 签名参数
|
||
body, err := json.Marshal(params)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
//bodyData := base64.StdEncoding.EncodeToString(body)
|
||
nonceStr := GenerateSecureRandomString(12)
|
||
timeStamp := utils.Int64ToStr(time.Now().Unix())
|
||
context := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", a.appID, a.serialNo, timeStamp, nonceStr, string(body))
|
||
|
||
// 进行rsa加密签名
|
||
hashed := sha256.Sum256([]byte(context))
|
||
signedData, err := rsa.SignPKCS1v15(rand.Reader, private.(*rsa.PrivateKey), crypto.SHA256, hashed[:])
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
signData := base64.StdEncoding.EncodeToString(signedData)
|
||
authorization := fmt.Sprintf(`LKLAPI-SHA256withRSA appid="%s",serial_no="%s",timestamp="%s",nonce_str="%s",signature="%s"`, a.appID, a.serialNo, timeStamp, nonceStr, signData)
|
||
return authorization, nil
|
||
}
|
||
|
||
// GenerateSecureRandomString 获取随机字符串
|
||
func GenerateSecureRandomString(length int) string {
|
||
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||
bytes := make([]byte, length)
|
||
charSetSize := big.NewInt(int64(len(charset)))
|
||
for i := range bytes {
|
||
num, _ := rand.Int(rand.Reader, charSetSize)
|
||
bytes[i] = charset[num.Int64()]
|
||
}
|
||
return string(bytes)
|
||
}
|
||
|
||
func GetOrderNumber(length int) string {
|
||
charset := "0123456789"
|
||
bytes := make([]byte, length)
|
||
charSetSize := big.NewInt(int64(len(charset)))
|
||
for i := range bytes {
|
||
num, _ := rand.Int(rand.Reader, charSetSize)
|
||
bytes[i] = charset[num.Int64()]
|
||
}
|
||
|
||
return utils.Time2TimeStrByFormat(time.Now(), TimeFormat) + string(bytes)
|
||
}
|
||
|
||
func SM4ECBEncrypt(plaintext, key []byte) ([]byte, error) {
|
||
if len(key) != sm4.BlockSize {
|
||
return nil, fmt.Errorf("SM4 密钥长度必须为 %d 字节", sm4.BlockSize)
|
||
}
|
||
// 补位处理 (PKCS5Padding)
|
||
paddedText := PKCS5Padding(plaintext, sm4.BlockSize)
|
||
|
||
// ECB 模式加密
|
||
ciphertext := make([]byte, len(paddedText))
|
||
for i := 0; i < len(paddedText); i += sm4.BlockSize {
|
||
block := paddedText[i : i+sm4.BlockSize]
|
||
encryptedBlock, err := sm4.Sm4Ecb(key, block, true) // true 表示加密
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
copy(ciphertext[i:], encryptedBlock)
|
||
}
|
||
|
||
return ciphertext, nil
|
||
}
|
||
|
||
// PKCS5Padding 填充(与 PKCS7Padding 对于 128位分组等价)
|
||
func PKCS5Padding(data []byte, blockSize int) []byte {
|
||
padding := blockSize - len(data)%blockSize
|
||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||
return append(data, padtext...)
|
||
}
|
||
|
||
type CallBackResult struct {
|
||
Code string `json:"code"`
|
||
Message string `json:"message"`
|
||
}
|
||
|
||
// CallBackResultInfo 失败回调返回
|
||
func CallBackResultInfo(err error) *CallBackResult {
|
||
if err == nil {
|
||
return &CallBackResult{
|
||
Code: "SUCCESS",
|
||
Message: "执行成功",
|
||
}
|
||
}
|
||
return &CallBackResult{
|
||
Code: "400",
|
||
Message: err.Error(),
|
||
}
|
||
}
|