From 65b11655aa322966f1113c9203dce822327f958d 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 14:06:01 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=A2=9E=E5=8A=A0=E3=80=91=E6=8B=BC?= =?UTF-8?q?=E5=A4=9A=E5=A4=9A=E8=81=94=E7=9B=9F=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 + README.md | 2 +- service/ddk/Ddk.go | 187 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 service/ddk/Ddk.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ab7538b3..c2238bff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,5 @@ +## v0.0.5 / 2021-05-29 +- 增加拼多多联盟服务 + ## v0.0.4 / 2021-05-29 - 优化 diff --git a/README.md b/README.md index bd8a9c4a..d7ad3044 100644 --- a/README.md +++ b/README.md @@ -23,5 +23,5 @@ go get gitee.com/dtapps/GoLibrary ``` ```Importing - get github.com/dtapps/GoLibrary +go get github.com/dtapps/GoLibrary ``` diff --git a/service/ddk/Ddk.go b/service/ddk/Ddk.go new file mode 100644 index 00000000..486fb970 --- /dev/null +++ b/service/ddk/Ddk.go @@ -0,0 +1,187 @@ +package ddk + +import ( + "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 ( + ErrTypeIsNil = errors.New("类型为Nil") + ErrTypeUnknown = errors.New("未处理到的数据类型") +) + +var ( + // ClientId 应用Key + ClientId string + // ClientSecret 秘密 + ClientSecret string + // Router 环境请求地址 + Router = "https://gw-api.pinduoduo.com/api/router" + // 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["type"] = 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 ClientId == "" { + return errors.New("ClientId 不能为空") + } + if ClientSecret == "" { + return errors.New("ClientSecret 不能为空") + } + 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["client_id"] = ClientId + p["data_type"] = "JSON" + p["version"] = "v1" + // 设置签名 + 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(ClientSecret) + for _, k := range keys { + query.WriteString(k) + query.WriteString(interfaceToString(params[k])) + } + query.WriteString(ClientSecret) + // 使用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(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) +}