blob: 43b2e87309490315a8e04e3c22fffddc61060f62 [file] [log] [blame]
Tang Cheng26b91152015-07-22 12:26:52 +08001package swservice
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +08002
3import (
4 "bytes"
5 "crypto/hmac"
6 "crypto/sha1"
Tang Chengf8716aa2015-08-19 10:20:40 +08007 "crypto/tls"
Tang Cheng26b91152015-07-22 12:26:52 +08008 "encoding/hex"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +08009 "encoding/json"
qiaoweica037fa2015-07-10 18:31:53 +080010 "errors"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080011 "fmt"
12 log "github.com/Sirupsen/logrus"
qiaoweica037fa2015-07-10 18:31:53 +080013 "io/ioutil"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080014 "net"
15 "net/http"
16 "net/url"
Tang Chengf16121a2015-07-27 13:46:14 +080017 "strconv"
Tang Chengf8716aa2015-08-19 10:20:40 +080018 "strings"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080019 "time"
20)
Tang Cheng32e32562015-07-08 17:08:03 +080021
Tang Cheng32e32562015-07-08 17:08:03 +080022type WebSession struct {
23 AppId string
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080024 TermId string
25 Appsecret string
Tang Cheng32e32562015-07-08 17:08:03 +080026 BaseUrl string
27 DefaultTimeout int
28 session_key string
Tang Cheng0b9abf12015-08-20 09:55:32 +080029 ssl_verify bool
Tang Cheng32e32562015-07-08 17:08:03 +080030}
31
Tang Chengf16121a2015-07-27 13:46:14 +080032func safe_get_json_int(value interface{}) int {
33 if value == nil {
34 return 0
35 }
36 s := fmt.Sprintf("%v", value)
37 if i, err := strconv.Atoi(s); err != nil {
38 return 0
39 } else {
40 return i
41 }
42}
43
44type ServiceResponse struct {
45 RetCode int
46 RetMsg string
47 Result map[string]interface{}
48}
49
50func NewServiceResponseFromJson(json_data interface{}) *ServiceResponse {
51 if json_data == nil {
52 return nil
53 }
54 res := &ServiceResponse{}
55 res.Result = json_data.(map[string]interface{})
56 res.RetCode = safe_get_json_int(res.Result["retcode"])
57 res.RetMsg = res.GetStrValue("retmsg")
58 return res
59}
60func (r *ServiceResponse) GetIntValue(name string) int {
61 return safe_get_json_int(r.Result[name])
62}
63
64func (r *ServiceResponse) GetStrValue(name string) string {
65 if s, ok := r.Result[name]; ok {
66 return fmt.Sprintf("%v", s)
67 } else {
68 return ""
69 }
70}
71
72func (r *ServiceResponse) GetFloatValue(name string) float64 {
73 if s, ok := r.Result[name]; ok {
74 t := fmt.Sprintf("%v", s)
75 if f, err := strconv.ParseFloat(t, 64); err != nil {
76 return 0.0
77 } else {
78 return f
79 }
80 } else {
81 return 0.0
82 }
83}
84
Tang Cheng32e32562015-07-08 17:08:03 +080085func (w *WebSession) DoGet(uri string, params map[string]string) (*http.Response, error) {
Tang Chengf8716aa2015-08-19 10:20:40 +080086 client := w.NewClient(3)
Tang Cheng32e32562015-07-08 17:08:03 +080087
88 full_url := w.BaseUrl + uri
89
90 vl := url.Values{}
Tang Cheng32e32562015-07-08 17:08:03 +080091
92 if params != nil {
93 for k, v := range params {
94 vl.Add(k, v)
95 }
96 }
Tang Cheng32e32562015-07-08 17:08:03 +080097 full_url = full_url + "?" + vl.Encode()
Tang Chengf16121a2015-07-27 13:46:14 +080098 // fmt.Printf("%v\n", full_url)
Tang Cheng32e32562015-07-08 17:08:03 +080099 return client.Get(full_url)
100}
101
102func (w *WebSession) GetTimestamp() string {
103 t := time.Now()
104 return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(),
105 t.Hour(), t.Minute(), t.Second())
106}
107
Tang Chengf16121a2015-07-27 13:46:14 +0800108func (w *WebSession) SignWithKey(key, message string) string {
109 mac := hmac.New(sha1.New, []byte(key))
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800110 mac.Write([]byte(message))
111 res := mac.Sum(nil)
Tang Cheng26b91152015-07-22 12:26:52 +0800112 return hex.EncodeToString(res)
Tang Cheng32e32562015-07-08 17:08:03 +0800113}
Tang Chengf16121a2015-07-27 13:46:14 +0800114func (w *WebSession) Sign(message string) string {
115 return w.SignWithKey(w.Appsecret, message)
116}
Tang Cheng32e32562015-07-08 17:08:03 +0800117
Tang Chengf16121a2015-07-27 13:46:14 +0800118func (w *WebSession) NewClient(timeout int) *http.Client {
Tang Chengf8716aa2015-08-19 10:20:40 +0800119 var transport http.Transport
120 if strings.HasPrefix(w.BaseUrl, "https://") {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800121 var b bool
122 if w.ssl_verify {
123 b = false
124 } else {
125 b = true
126 }
Tang Cheng91665852015-08-29 22:17:20 +0800127 transport = http.Transport{MaxIdleConnsPerHost: 0, DisableKeepAlives: true,
128 TLSClientConfig: &tls.Config{InsecureSkipVerify: b},
129 TLSHandshakeTimeout: time.Duration(timeout) * time.Second,
130 Dial: func(network, addr string) (net.Conn, error) {
131 default_timeout := time.Duration(1) * time.Second
132 return net.DialTimeout(network, addr, default_timeout)
133 }}
Tang Chengf8716aa2015-08-19 10:20:40 +0800134 } else if strings.HasPrefix(w.BaseUrl, "http://") {
Tang Cheng91665852015-08-29 22:17:20 +0800135 transport = http.Transport{MaxIdleConnsPerHost: 0, DisableKeepAlives: true,
136 Dial: func(network, addr string) (net.Conn, error) {
137 default_timeout := time.Duration(1) * time.Second
138 return net.DialTimeout(network, addr, default_timeout)
139 }}
Tang Chengf8716aa2015-08-19 10:20:40 +0800140 }
Tang Cheng91665852015-08-29 22:17:20 +0800141 return &http.Client{Transport: &transport, Timeout: time.Duration(timeout) * time.Second}
Tang Chengf16121a2015-07-27 13:46:14 +0800142}
Tang Chengf8716aa2015-08-19 10:20:40 +0800143
Tang Cheng26b91152015-07-22 12:26:52 +0800144func (w *WebSession) DoPost(uri string, param map[string]string) (*http.Response, error) {
Tang Chengf8716aa2015-08-19 10:20:40 +0800145 client := w.NewClient(3)
Tang Cheng26b91152015-07-22 12:26:52 +0800146 param["app_id"] = w.AppId
Tang Chengf8716aa2015-08-19 10:20:40 +0800147 param["term_id"] = w.TermId
Tang Cheng26b91152015-07-22 12:26:52 +0800148 param["sign_method"] = "HMAC"
149 param["session_key"] = w.session_key
Tang Cheng32e32562015-07-08 17:08:03 +0800150 ts := w.GetTimestamp()
Tang Cheng26b91152015-07-22 12:26:52 +0800151 param["timestamp"] = ts
152 param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800153
Tang Cheng32e32562015-07-08 17:08:03 +0800154 full_url := w.BaseUrl + uri
Tang Cheng26b91152015-07-22 12:26:52 +0800155 data, err := json.Marshal(param)
156 if err != nil {
157 return nil, err
158 }
159 var r *http.Response
160 r, err = client.Post(full_url, "application/json", bytes.NewReader(data))
Tang Cheng32e32562015-07-08 17:08:03 +0800161 if err != nil || r.StatusCode != 200 {
162 log.Errorf("Status=%v, err=%v", r, err)
163 }
164 return r, err
165}
166
167func (w *WebSession) Auth() error {
qiaoweica037fa2015-07-10 18:31:53 +0800168 token, err := w.getAuthToken()
169 if err != nil {
170 return err
171 }
172 err = w.getAppAccessKey(token)
173 if err != nil {
174 return err
175 }
Tang Cheng32e32562015-07-08 17:08:03 +0800176 return nil
177}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800178
Tang Cheng0b9abf12015-08-20 09:55:32 +0800179func NewSession(appid, appsecret, termid, baseurl string, timeout int, sslVerify bool) *WebSession {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800180 return &WebSession{
181 AppId: appid,
182 Appsecret: appsecret,
183 TermId: termid,
184 BaseUrl: baseurl,
185 DefaultTimeout: timeout,
Tang Cheng0b9abf12015-08-20 09:55:32 +0800186 ssl_verify: sslVerify}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800187}
188
qiaoweica037fa2015-07-10 18:31:53 +0800189func (w *WebSession) getAuthToken() (string, error) {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800190 type FormJson struct {
191 AppId string `json:"app_id"`
192 TermId string `json:"term_id"`
193 AccessToken string `json:"access_token"`
194 }
195
Tang Cheng26b91152015-07-22 12:26:52 +0800196 uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800197
198 params := make(map[string]string)
199 params["term_id"] = w.TermId
200 r, err := w.DoGet(uri, params)
201
Tang Chengf8716aa2015-08-19 10:20:40 +0800202 if err != nil {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800203 // log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
Tang Chengf8716aa2015-08-19 10:20:40 +0800204 return "", err
205 }
206 if r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800207 return "", errors.New("请求失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800208 }
209
qiaoweica037fa2015-07-10 18:31:53 +0800210 body, err := ioutil.ReadAll(r.Body)
Tang Cheng91665852015-08-29 22:17:20 +0800211 defer r.Body.Close()
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800212
qiaoweica037fa2015-07-10 18:31:53 +0800213 s := &FormJson{}
214 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800215 if err != nil {
216 log.Errorf("json unmarshal err %v", err)
qiaoweica037fa2015-07-10 18:31:53 +0800217 return "", errors.New("解析失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800218 }
qiaoweica037fa2015-07-10 18:31:53 +0800219 return s.AccessToken, nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800220}
qiaoweica037fa2015-07-10 18:31:53 +0800221func (w *WebSession) getAppAccessKey(token string) error {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800222 type FormJson struct {
qiaoweica037fa2015-07-10 18:31:53 +0800223 AppId string `json:"app_id"`
224 TermId string `json:"term_id"`
225 SessionKey string `json:"session_key"`
226 CardKey string `json:"card_key"`
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800227 }
228
Tang Cheng26b91152015-07-22 12:26:52 +0800229 uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800230
231 params := make(map[string]string)
232 params["term_id"] = w.TermId
qiaoweica037fa2015-07-10 18:31:53 +0800233 params["access_token"] = token
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800234 params["timestamp"] = w.GetTimestamp()
235 params["v"] = "1"
qiaoweica037fa2015-07-10 18:31:53 +0800236 params["sign"] = w.Sign(token + params["timestamp"])
237 params["sign_method"] = "HMAC"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800238
qiaoweica037fa2015-07-10 18:31:53 +0800239 r, err := w.DoGet(uri, params)
Tang Cheng55814742015-09-08 17:24:05 +0800240 if r != nil {
241 defer r.Body.Close()
242 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800243 if err != nil || r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800244 log.Errorf(" err = %v\n", err)
245 return err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800246 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800247
qiaoweica037fa2015-07-10 18:31:53 +0800248 body, err := ioutil.ReadAll(r.Body)
qiaoweica037fa2015-07-10 18:31:53 +0800249
250 s := &FormJson{}
251 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800252 if err != nil {
253 log.Errorf("json unmarshal err %v", err)
254 }
qiaoweica037fa2015-07-10 18:31:53 +0800255 w.session_key = s.SessionKey
256 return nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800257}
Tang Cheng26b91152015-07-22 12:26:52 +0800258
259func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) {
260 call_data := request.Serialize()
261 params := make(map[string]string)
262 params["funcdata"] = call_data
263 r, err := w.DoPost("/ecardservice/ecardapi", params)
264
Tang Cheng55814742015-09-08 17:24:05 +0800265 if r != nil {
266 defer r.Body.Close()
267 }
Tang Chengf16121a2015-07-27 13:46:14 +0800268 if err != nil {
Tang Cheng26b91152015-07-22 12:26:52 +0800269 log.Errorf(" err = %v\n", err)
270 return nil, err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800271 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800272
Tang Chengf16121a2015-07-27 13:46:14 +0800273 if r.StatusCode != 200 {
274 return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode))
275 }
276
Tang Cheng26b91152015-07-22 12:26:52 +0800277 body, err := ioutil.ReadAll(r.Body)
Tang Cheng26b91152015-07-22 12:26:52 +0800278 return NewMessageReader(body), nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800279}
Tang Chengf16121a2015-07-27 13:46:14 +0800280
281func (w *WebSession) CallService(path string, params map[string]interface{},
282 sign_field []string, timeout int) (response *ServiceResponse, err error) {
283
284 return w.CallService2(path, params, timeout, sign_field...)
285}
286
287func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int,
288 sign_field ...string) (response *ServiceResponse, err error) {
289 client := w.NewClient(timeout)
290 err = nil
291 params["app_id"] = w.AppId
292 params["term_id"] = w.TermId
293 ts := w.GetTimestamp()
294 params["timestamp"] = ts
295
296 vl := &url.Values{}
297 for k, v := range params {
298 vl.Set(k, fmt.Sprintf("%v", v))
299 }
300
301 sign_data := ""
302 for _, k := range sign_field {
303 if v, ok := params[k]; ok {
304 sign_data += fmt.Sprintf("%v", v)
305 }
306 }
307 sign_data += ts + w.session_key
308 vl.Set("sign_method", "HMAC")
309 log.Debugf("Sign: key[%v] data[%v]\n", w.session_key, sign_data)
310 vl.Set("sign", w.SignWithKey(w.Appsecret, sign_data))
311
312 full_url := w.BaseUrl + path
313 log.Debugf("CallService: %v\n", full_url)
314 var r *http.Response
315 r, err = client.Post(full_url, "application/x-www-form-urlencoded",
316 bytes.NewReader([]byte(vl.Encode())))
Tang Cheng55814742015-09-08 17:24:05 +0800317 if r != nil {
318 defer r.Body.Close()
319 }
Tang Chengf16121a2015-07-27 13:46:14 +0800320 if err != nil {
321 log.Errorf("Status=%v, err=%v", r, err)
322 return
323 }
324 if r.StatusCode != 200 {
325 log.Errorf("Request Error %v\n", r.StatusCode)
326 err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode))
327 return
328 }
329 body, err := ioutil.ReadAll(r.Body)
Tang Chengf16121a2015-07-27 13:46:14 +0800330 var s interface{}
331 err = json.Unmarshal(body, &s)
332 if err != nil {
333 log.Errorf("json unmarshal err %v", err)
334 return
335 }
336 response = NewServiceResponseFromJson(s)
337 return
338}