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(), } }