From efaaea0d40751f43f70ef0ecb9ff833346e5890d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=85=89=E6=98=A5?= Date: Sat, 29 May 2021 02:10:47 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E6=B7=98?= =?UTF-8?q?=E5=AE=9D=E5=AE=A2=E3=80=81=E4=BA=AC=E4=B8=9C=E8=81=94=E7=9B=9F?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 21 ++++ README.md | 12 ++- excepyion/service/errors.go | 8 ++ helper/uuid/uuid.go | 4 +- helper/uuid/uuid_test.go | 13 +++ service/jdk/Jdk.go | 183 ++++++++++++++++++++++++++++++++++ service/tbk/Tbk.go | 190 ++++++++++++++++++++++++++++++++++++ 7 files changed, 426 insertions(+), 5 deletions(-) create mode 100644 LICENSE create mode 100644 excepyion/service/errors.go create mode 100644 helper/uuid/uuid_test.go create mode 100644 service/jdk/Jdk.go create mode 100644 service/tbk/Tbk.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..34366fbe --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 李光春 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 1dc431bc..8228a204 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,16 @@ 📦 Golang扩展包 +[![Build Status](https://secure.travis-ci.com/dtapps/GoLibrary.png?branch=master)](http://travis-ci.org/dtapps/GoLibrary) +[![GoDoc](https://godoc.org/github.com/dtapps/GoLibrary?status.svg)](https://godoc.org/github.com/dtapps/GoLibrary) +[![GoDoc](https://godoc.org/gitee.com/dtapps/GoLibrary?status.svg)](https://godoc.org/gitee.com/dtapps/GoLibrary) +[![GitHub release](https://img.shields.io/github/release/dtapps/GoLibrary.svg)](https://github.com/dtapps/GoLibrary/releases/latest) + ### 安装 -```text +```Importing go get gitee.com/dtapps/GoLibrary ``` -### 安装 -```text -go get github.com/dtapps/GoLibrary +```Importing + get github.com/dtapps/GoLibrary ``` diff --git a/excepyion/service/errors.go b/excepyion/service/errors.go new file mode 100644 index 00000000..3e60bc8b --- /dev/null +++ b/excepyion/service/errors.go @@ -0,0 +1,8 @@ +package service + +import "errors" + +var ( + ErrTypeIsNil = errors.New("类型为Nil") + ErrTypeUnknown = errors.New("未处理到的数据类型") +) diff --git a/helper/uuid/uuid.go b/helper/uuid/uuid.go index 083faae6..4c07cb09 100644 --- a/helper/uuid/uuid.go +++ b/helper/uuid/uuid.go @@ -1,6 +1,8 @@ package uuid -import "github.com/google/uuid" +import ( + "github.com/google/uuid" +) func GenUUID() string { u, _ := uuid.NewRandom() diff --git a/helper/uuid/uuid_test.go b/helper/uuid/uuid_test.go new file mode 100644 index 00000000..e185b08f --- /dev/null +++ b/helper/uuid/uuid_test.go @@ -0,0 +1,13 @@ +package uuid_test + +import ( + "GoLibrary/helper/uuid" + "fmt" + "testing" +) + +func TestName(t *testing.T) { + genUUID := uuid.GenUUID() + fmt.Println("Hello World") + fmt.Println(genUUID) +} diff --git a/service/jdk/Jdk.go b/service/jdk/Jdk.go new file mode 100644 index 00000000..6da98dc6 --- /dev/null +++ b/service/jdk/Jdk.go @@ -0,0 +1,183 @@ +package jdk + +import ( + "GoLibrary/excepyion/service" + "bytes" + "crypto/md5" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "github.com/bitly/go-simplejson" + "github.com/nilorg/sdk/convert" + "io" + "io/ioutil" + "net/http" + "net/url" + "sort" + "strings" + "time" +) + +var ( + // AppKey 应用Key + AppKey string + // SecretKey 秘密 + SecretKey string + // Router 环境请求地址 + Router = "https://api.jd.com/routerjson" + // Timeout ... + Timeout time.Duration +) + +// Parameter 参数 +type Parameter map[string]interface{} + +// copyParameter 复制参数 +func copyParameter(srcParams Parameter) Parameter { + newParams := make(Parameter) + for key, value := range srcParams { + newParams[key] = value + } + return newParams +} + +// execute 执行API接口 +func execute(param Parameter) (bytes []byte, err error) { + err = checkConfig() + if err != nil { + return + } + + var req *http.Request + req, err = http.NewRequest("POST", Router, strings.NewReader(param.getRequestData())) + if err != nil { + return + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8") + httpClient := &http.Client{} + httpClient.Timeout = Timeout + var response *http.Response + response, err = httpClient.Do(req) + if err != nil { + return + } + + if response.StatusCode != 200 { + err = fmt.Errorf("请求错误:%d", response.StatusCode) + return + } + defer response.Body.Close() + bytes, err = ioutil.ReadAll(response.Body) + return +} + +// Execute 执行API接口 +func Execute(method string, param Parameter) (res *simplejson.Json, err error) { + param["method"] = method + param.setRequestData() + + var bodyBytes []byte + bodyBytes, err = execute(param) + if err != nil { + return + } + + return bytesToResult(bodyBytes) +} + +func bytesToResult(bytes []byte) (res *simplejson.Json, err error) { + res, err = simplejson.NewJson(bytes) + if err != nil { + return + } + + if responseError, ok := res.CheckGet("error_response"); ok { + if subMsg, subOk := responseError.CheckGet("sub_msg"); subOk { + err = errors.New(subMsg.MustString()) + } else { + err = errors.New(responseError.Get("msg").MustString()) + } + res = nil + } + return +} + +// 检查配置 +func checkConfig() error { + if AppKey == "" { + return errors.New("AppKey 不能为空") + } + if SecretKey == "" { + return errors.New("SecretKey 不能为空") + } + if Router == "" { + return errors.New("Router 不能为空") + } + return nil +} + +func (p Parameter) setRequestData() { + hh, _ := time.ParseDuration("8h") + loc := time.Now().UTC().Add(hh) + p["app_key"] = AppKey + p["timestamp"] = loc.Format("2006-01-02 15:04:05") + p["format"] = "json" + p["v"] = "1.0" + p["sign_method"] = "md5" + // 设置签名 + p["sign"] = getSign(p) +} + +// 获取请求数据 +func (p Parameter) getRequestData() string { + // 公共参数 + args := url.Values{} + // 请求参数 + for key, val := range p { + args.Set(key, interfaceToString(val)) + } + return args.Encode() +} + +// 获取签名 +func getSign(params Parameter) string { + // 获取Key + keys := []string{} + for k := range params { + keys = append(keys, k) + } + // 排序asc + sort.Strings(keys) + // 把所有参数名和参数值串在一起 + query := bytes.NewBufferString(SecretKey) + for _, k := range keys { + query.WriteString(k) + query.WriteString(interfaceToString(params[k])) + } + query.WriteString(SecretKey) + // 使用MD5加密 + h := md5.New() + io.Copy(h, query) + // 把二进制转化为大写的十六进制 + return strings.ToUpper(hex.EncodeToString(h.Sum(nil))) +} + +func interfaceToString(src interface{}) string { + if src == nil { + panic(service.ErrTypeIsNil) + } + switch src.(type) { + case string: + return src.(string) + case int, int8, int32, int64: + case uint8, uint16, uint32, uint64: + case float32, float64: + return convert.ToString(src) + } + data, err := json.Marshal(src) + if err != nil { + panic(err) + } + return string(data) +} diff --git a/service/tbk/Tbk.go b/service/tbk/Tbk.go new file mode 100644 index 00000000..9af1dc87 --- /dev/null +++ b/service/tbk/Tbk.go @@ -0,0 +1,190 @@ +package tbk + +import ( + "GoLibrary/excepyion/service" + "bytes" + "crypto/md5" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "github.com/bitly/go-simplejson" + "github.com/nilorg/sdk/convert" + "io" + "io/ioutil" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" +) + +var ( + // AppKey 应用Key + AppKey string + // AppSecret 秘密 + AppSecret string + // Router 环境请求地址 + Router = "https://eco.taobao.com/router/rest" + // Session 用户登录授权成功后,TOP颁发给应用的授权信息。当此API的标签上注明:“需要授权”,则此参数必传;“不需要授权”,则此参数不需要传;“可选授权”,则此参数为可选 + Session string + // Timeout ... + Timeout time.Duration +) + +// Parameter 参数 +type Parameter map[string]interface{} + +// copyParameter 复制参数 +func copyParameter(srcParams Parameter) Parameter { + newParams := make(Parameter) + for key, value := range srcParams { + newParams[key] = value + } + return newParams +} + +// execute 执行API接口 +func execute(param Parameter) (bytes []byte, err error) { + err = checkConfig() + if err != nil { + return + } + + var req *http.Request + req, err = http.NewRequest("POST", Router, strings.NewReader(param.getRequestData())) + if err != nil { + return + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8") + httpClient := &http.Client{} + httpClient.Timeout = Timeout + var response *http.Response + response, err = httpClient.Do(req) + if err != nil { + return + } + + if response.StatusCode != 200 { + err = fmt.Errorf("请求错误:%d", response.StatusCode) + return + } + defer response.Body.Close() + bytes, err = ioutil.ReadAll(response.Body) + return +} + +// Execute 执行API接口 +func Execute(method string, param Parameter) (res *simplejson.Json, err error) { + param["method"] = method + param.setRequestData() + + var bodyBytes []byte + bodyBytes, err = execute(param) + if err != nil { + return + } + + return bytesToResult(bodyBytes) +} + +func bytesToResult(bytes []byte) (res *simplejson.Json, err error) { + res, err = simplejson.NewJson(bytes) + if err != nil { + return + } + + if responseError, ok := res.CheckGet("error_response"); ok { + if subMsg, subOk := responseError.CheckGet("sub_msg"); subOk { + err = errors.New(subMsg.MustString()) + } else { + err = errors.New(responseError.Get("msg").MustString()) + } + res = nil + } + return +} + +// 检查配置 +func checkConfig() error { + if AppKey == "" { + return errors.New("AppKey 不能为空") + } + if AppSecret == "" { + return errors.New("AppSecret 不能为空") + } + if Router == "" { + return errors.New("Router 不能为空") + } + return nil +} + +func (p Parameter) setRequestData() { + hh, _ := time.ParseDuration("8h") + loc := time.Now().UTC().Add(hh) + p["timestamp"] = strconv.FormatInt(loc.Unix(), 10) + p["format"] = "json" + p["app_key"] = AppKey + p["v"] = "2.0" + p["sign_method"] = "md5" + p["partner_id"] = "Nilorg" + if Session != "" { + p["session"] = Session + } + // 设置签名 + p["sign"] = getSign(p) +} + +// 获取请求数据 +func (p Parameter) getRequestData() string { + // 公共参数 + args := url.Values{} + // 请求参数 + for key, val := range p { + args.Set(key, interfaceToString(val)) + } + return args.Encode() +} + +// 获取签名 +func getSign(params Parameter) string { + // 获取Key + keys := []string{} + for k := range params { + keys = append(keys, k) + } + // 排序asc + sort.Strings(keys) + // 把所有参数名和参数值串在一起 + query := bytes.NewBufferString(AppSecret) + for _, k := range keys { + query.WriteString(k) + query.WriteString(interfaceToString(params[k])) + } + query.WriteString(AppSecret) + // 使用MD5加密 + h := md5.New() + io.Copy(h, query) + // 把二进制转化为大写的十六进制 + return strings.ToUpper(hex.EncodeToString(h.Sum(nil))) +} + +func interfaceToString(src interface{}) string { + if src == nil { + panic(service.ErrTypeIsNil) + } + switch src.(type) { + case string: + return src.(string) + case int, int8, int32, int64: + case uint8, uint16, uint32, uint64: + case float32, float64: + return convert.ToString(src) + } + data, err := json.Marshal(src) + if err != nil { + panic(err) + } + return string(data) +}