-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
138 lines (125 loc) · 2.92 KB
/
client.go
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
package qcloudsms
import (
"bytes"
"crypto/sha256"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"net/url"
"time"
"github.com/pkg/errors"
)
var (
userAgent = "qcloudsms-go-sdk/1.0"
baseURL = "https://yun.tim.qq.com/v5/tlssmssvr/"
contentType = "application/json; charset=utf-8"
)
// ClientConfig to set configuration for client.
type ClientConfig struct {
initialized bool
AppID string
AppKey string
UserAgent string
}
// NewClientConfig returns instance for client config.
func NewClientConfig() *ClientConfig {
return &ClientConfig{
initialized: true,
UserAgent: userAgent,
}
}
var defaultClientConfig = &ClientConfig{
initialized: false,
UserAgent: userAgent,
}
// Client works for API Call.
type Client interface {
Post(*QRequest) (*QResponse, error)
}
type smsClient struct {
client *http.Client
config *ClientConfig
}
// NewClient returns Client interface or error.
func NewClient(conf *ClientConfig) (Client, error) {
if conf == nil {
conf = defaultClientConfig
}
if conf.initialized == false {
return nil, errors.New("Please init client configuration with NewClientConfig()")
}
if conf.AppID == "" || conf.AppKey == "" {
return nil, errors.New("App information not configure")
}
return &smsClient{
client: &http.Client{},
config: conf,
}, nil
}
// Post request to qcloud API.
func (sc *smsClient) Post(req *QRequest) (resp *QResponse, err error) {
random := fmt.Sprintf("%06d", rand.Intn(999999))
params := url.Values{}
params.Set("sdkappid", sc.config.AppID)
params.Set("random", random)
targetURL := baseURL + req.Path + "?" + params.Encode()
now := time.Now().Unix()
req.Time = now
req.Sig = sc.signature(req.Tel, random, now)
b, e := json.Marshal(req)
if e != nil {
err = errors.Wrap(e, "Client request parse")
return
}
httpReq, e := http.NewRequest("POST", targetURL, bytes.NewReader(b))
if e != nil {
err = errors.Wrap(e, "Client NewRequest")
return
}
httpReq.Header.Set("User-Agent", sc.config.UserAgent)
httpReq.Header.Set("Content-Type", contentType)
httpResp, e := sc.client.Do(httpReq)
if e != nil {
err = errors.Wrap(e, "Client post")
return
}
defer httpResp.Body.Close()
b, e = ioutil.ReadAll(httpResp.Body)
if e != nil {
err = errors.Wrap(e, "Client read")
return
}
resp = &QResponse{}
e = json.Unmarshal(b, resp)
if e != nil {
err = errors.Wrap(e, "Client json parse")
return
}
return
}
func (sc *smsClient) signature(tel interface{}, random string, now int64) string {
var mobile string
if tel != nil {
switch tel.(type) {
case Tel:
mobile = tel.(Tel).Mobile
case []Tel:
for _, t := range tel.([]Tel) {
if mobile == "" {
mobile = t.Mobile
} else {
mobile += "," + t.Mobile
}
}
default:
mobile = ""
}
}
s := fmt.Sprintf("appkey=%s&random=%s&time=%d", sc.config.AppKey, random, now)
if mobile != "" {
s += "&mobile=" + mobile
}
return fmt.Sprintf("%x", sha256.Sum256([]byte(s)))
}