This repository has been archived by the owner on Jun 1, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbase.go.old
147 lines (128 loc) · 3.48 KB
/
base.go.old
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package xiaohongshu
import (
"encoding/json"
"errors"
"fmt"
"github.com/fatih/structs"
"io"
"net/http"
"net/url"
"reflect"
"strconv"
"strings"
"time"
"github.com/mitchellh/mapstructure"
)
// HeaderMap 用于包装请求数据
type HeaderMap map[string]string
// GatewayURL 地址
const GatewayURL = "https://ark.xiaohongshu.com"
// SortKeyList 公共参数排序后的字段列表,签名时用到
// https://school.xiaohongshu.com/open/quick-start/sign.html
// 公共参数为app-key和timestamp
var SortKeyList = []string{
"app-key",
"timestamp",
}
// BaseApp 应用的基础配置
type BaseApp struct {
Key string
Secret string
gatewayURL string
}
// NewBaseApp 实例化基础应用
func NewBaseApp(k, s string) *BaseApp {
return &BaseApp{Key: k, Secret: s, gatewayURL: GatewayURL}
}
// SetGatewayURL 重置地址
func (b *BaseApp) SetGatewayURL(u string) *BaseApp {
b.gatewayURL = u
return b
}
type BaseResp struct {
Data interface{} `json:"data"`
ErrorCode int `json:"error_code"`
ErrorMsg string `json:"error_msg"`
Success bool `json:"success"`
}
func (b *BaseApp) request(heads HeaderMap, method, urlStr string, rsp interface{}, body io.Reader) error {
req, err := http.NewRequest(method, urlStr, body)
if err != nil {
return err
}
// https://school.xiaohongshu.com/open/quick-start/system-parameter.html
req.Header.Add("timestamp", heads["timestamp"])
req.Header.Add("app-key", heads["app-key"])
req.Header.Add("sign", heads["sign"])
// content-type为application/json;charset=utf-8
req.Header.Add("Content-Type", "application/json")
req.Header.Add("charset", "utf-8")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
var ret BaseResp
if err := json.NewDecoder(resp.Body).Decode(&ret); err != nil {
return err
}
if ret.ErrorCode != 0 || ret.ErrorMsg != "success" {
return fmt.Errorf("response error %d %s", ret.ErrorCode, ret.ErrorMsg)
}
if rsp == nil {
return nil
}
if ret.Data == nil {
return errors.New("response error data is nil")
}
if reflect.TypeOf(rsp).Elem().Kind() == reflect.Interface {
rd := reflect.ValueOf(ret.Data)
reflect.ValueOf(rsp).Elem().Set(rd)
return nil
}
return mapstructure.Decode(ret.Data, rsp)
}
func (b *BaseApp) headerMap() HeaderMap {
return HeaderMap{
"app-key": b.Key,
"timestamp": strconv.FormatInt(time.Now().Unix(), 10),
"sign": "",
}
}
func (b *BaseApp) Put(urlStr string, req, rsp interface{}) error {
headers := b.headerMap()
headers["sign"] = Sign(headers, b.Secret, urlStr)
d, err := json.Marshal(req)
if err != nil {
return err
}
body := strings.NewReader(string(d))
return b.request(headers, "PUT", b.gatewayURL+urlStr, rsp, body)
}
func (b *BaseApp) Post(urlStr string, req, rsp interface{}) error {
headers := b.headerMap()
headers["sign"] = Sign(headers, b.Secret, urlStr)
d, err := json.Marshal(req)
if err != nil {
return err
}
body := strings.NewReader(string(d))
return b.request(headers, "POST", b.gatewayURL+urlStr, rsp, body)
}
// Get 执行请求
func (b *BaseApp) Get(urlStr string, req, rsp interface{}) error {
headers := b.headerMap()
var queryStr string
if req != nil {
query := url.Values{}
r := structs.Map(req)
for k, v := range r {
vv := fmt.Sprint(v)
query.Add(k, vv)
SortKeyList = append(SortKeyList, k)
headers[k] = vv
}
queryStr = "?" + query.Encode()
}
headers["sign"] = Sign(headers, b.Secret, urlStr)
return b.request(headers, "GET", b.gatewayURL+urlStr+queryStr, rsp, nil)
}