blob: 2195a09322daee25104032899ce6bd66869729f2 [file] [log] [blame]
Tang Cheng26b91152015-07-22 12:26:52 +08001package swservice
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +08002
3import (
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +08004 "crypto/hmac"
5 "crypto/sha1"
Tang Chengf8716aa2015-08-19 10:20:40 +08006 "crypto/tls"
Tang Cheng26b91152015-07-22 12:26:52 +08007 "encoding/hex"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +08008 "encoding/json"
qiaoweica037fa2015-07-10 18:31:53 +08009 "errors"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080010 "fmt"
qiaoweica037fa2015-07-10 18:31:53 +080011 "io/ioutil"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080012 "net"
13 "net/http"
14 "net/url"
Tang Chengf16121a2015-07-27 13:46:14 +080015 "strconv"
Tang Chengf8716aa2015-08-19 10:20:40 +080016 "strings"
Tang Cheng78513ea2015-10-28 14:32:02 +080017 "sync"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080018 "time"
Tang Chenga412d202016-01-27 09:24:53 +080019
20 log "github.com/Sirupsen/logrus"
21 "github.com/franela/goreq"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080022)
Tang Cheng32e32562015-07-08 17:08:03 +080023
Tang Cheng32e32562015-07-08 17:08:03 +080024type WebSession struct {
Tang Cheng78513ea2015-10-28 14:32:02 +080025 AppId string
26 TermId string
27 Appsecret string
28 BaseUrl string
29 DefaultTimeout int
30 session_key string
31 ssl_verify bool
32 httpConnectionPool sync.Pool
Tang Cheng32e32562015-07-08 17:08:03 +080033}
34
Tang Chengf16121a2015-07-27 13:46:14 +080035func safe_get_json_int(value interface{}) int {
36 if value == nil {
37 return 0
38 }
39 s := fmt.Sprintf("%v", value)
40 if i, err := strconv.Atoi(s); err != nil {
41 return 0
42 } else {
43 return i
44 }
45}
46
47type ServiceResponse struct {
48 RetCode int
49 RetMsg string
50 Result map[string]interface{}
51}
52
53func NewServiceResponseFromJson(json_data interface{}) *ServiceResponse {
54 if json_data == nil {
55 return nil
56 }
57 res := &ServiceResponse{}
58 res.Result = json_data.(map[string]interface{})
59 res.RetCode = safe_get_json_int(res.Result["retcode"])
60 res.RetMsg = res.GetStrValue("retmsg")
61 return res
62}
63func (r *ServiceResponse) GetIntValue(name string) int {
64 return safe_get_json_int(r.Result[name])
65}
66
67func (r *ServiceResponse) GetStrValue(name string) string {
68 if s, ok := r.Result[name]; ok {
69 return fmt.Sprintf("%v", s)
70 } else {
71 return ""
72 }
73}
74
zongqiang.zhang134f4182016-06-14 15:23:22 +080075func (r *ServiceResponse) GetInterfaceValue(name string) interface{} {
76 if s, ok := r.Result[name]; ok {
77 return s
78 } else {
79 return nil
80 }
81}
Tang Chengf16121a2015-07-27 13:46:14 +080082func (r *ServiceResponse) GetFloatValue(name string) float64 {
83 if s, ok := r.Result[name]; ok {
84 t := fmt.Sprintf("%v", s)
85 if f, err := strconv.ParseFloat(t, 64); err != nil {
86 return 0.0
87 } else {
88 return f
89 }
90 } else {
91 return 0.0
92 }
93}
94
Tang Cheng32e32562015-07-08 17:08:03 +080095func (w *WebSession) DoGet(uri string, params map[string]string) (*http.Response, error) {
Tang Cheng78513ea2015-10-28 14:32:02 +080096 transport := w.httpConnectionPool.Get().(*http.Transport)
97 defer w.httpConnectionPool.Put(transport)
98 client := &http.Client{Transport: transport, Timeout: time.Duration(3) * time.Second}
Tang Cheng32e32562015-07-08 17:08:03 +080099
100 full_url := w.BaseUrl + uri
101
102 vl := url.Values{}
Tang Cheng32e32562015-07-08 17:08:03 +0800103
104 if params != nil {
105 for k, v := range params {
106 vl.Add(k, v)
107 }
108 }
Tang Cheng32e32562015-07-08 17:08:03 +0800109 full_url = full_url + "?" + vl.Encode()
Tang Chengf16121a2015-07-27 13:46:14 +0800110 // fmt.Printf("%v\n", full_url)
Tang Cheng32e32562015-07-08 17:08:03 +0800111 return client.Get(full_url)
112}
113
114func (w *WebSession) GetTimestamp() string {
115 t := time.Now()
116 return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(),
117 t.Hour(), t.Minute(), t.Second())
118}
119
Tang Chengf16121a2015-07-27 13:46:14 +0800120func (w *WebSession) SignWithKey(key, message string) string {
121 mac := hmac.New(sha1.New, []byte(key))
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800122 mac.Write([]byte(message))
123 res := mac.Sum(nil)
Tang Cheng26b91152015-07-22 12:26:52 +0800124 return hex.EncodeToString(res)
Tang Cheng32e32562015-07-08 17:08:03 +0800125}
Tang Chengf16121a2015-07-27 13:46:14 +0800126func (w *WebSession) Sign(message string) string {
127 return w.SignWithKey(w.Appsecret, message)
128}
Tang Cheng32e32562015-07-08 17:08:03 +0800129
Tang Cheng78513ea2015-10-28 14:32:02 +0800130func newTransport(baseurl string, ssl_verify bool) *http.Transport {
Tang Chengf8716aa2015-08-19 10:20:40 +0800131 var transport http.Transport
Tang Cheng78513ea2015-10-28 14:32:02 +0800132 if strings.HasPrefix(baseurl, "https://") {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800133 var b bool
Tang Cheng78513ea2015-10-28 14:32:02 +0800134 if ssl_verify {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800135 b = false
136 } else {
137 b = true
138 }
Tang Cheng78513ea2015-10-28 14:32:02 +0800139 transport = http.Transport{MaxIdleConnsPerHost: 0,
Tang Cheng91665852015-08-29 22:17:20 +0800140 TLSClientConfig: &tls.Config{InsecureSkipVerify: b},
Tang Cheng78513ea2015-10-28 14:32:02 +0800141 TLSHandshakeTimeout: time.Duration(1) * time.Second,
Tang Cheng91665852015-08-29 22:17:20 +0800142 Dial: func(network, addr string) (net.Conn, error) {
143 default_timeout := time.Duration(1) * time.Second
144 return net.DialTimeout(network, addr, default_timeout)
145 }}
Tang Cheng78513ea2015-10-28 14:32:02 +0800146 } else if strings.HasPrefix(baseurl, "http://") {
147 transport = http.Transport{MaxIdleConnsPerHost: 0,
Tang Cheng91665852015-08-29 22:17:20 +0800148 Dial: func(network, addr string) (net.Conn, error) {
149 default_timeout := time.Duration(1) * time.Second
150 return net.DialTimeout(network, addr, default_timeout)
151 }}
Tang Chengf8716aa2015-08-19 10:20:40 +0800152 }
Tang Cheng78513ea2015-10-28 14:32:02 +0800153 log.Debugf("创建新连接")
154 return &transport
Tang Chengf16121a2015-07-27 13:46:14 +0800155}
Tang Chengf8716aa2015-08-19 10:20:40 +0800156
Tang Chenga412d202016-01-27 09:24:53 +0800157func (w *WebSession) DoPost(uri string, param map[string]string) (*goreq.Response, error) {
Tang Cheng26b91152015-07-22 12:26:52 +0800158 param["app_id"] = w.AppId
Tang Chengf8716aa2015-08-19 10:20:40 +0800159 param["term_id"] = w.TermId
Tang Cheng26b91152015-07-22 12:26:52 +0800160 param["sign_method"] = "HMAC"
161 param["session_key"] = w.session_key
Tang Cheng32e32562015-07-08 17:08:03 +0800162 ts := w.GetTimestamp()
Tang Cheng26b91152015-07-22 12:26:52 +0800163 param["timestamp"] = ts
164 param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800165
Tang Cheng32e32562015-07-08 17:08:03 +0800166 full_url := w.BaseUrl + uri
Tang Cheng26b91152015-07-22 12:26:52 +0800167 data, err := json.Marshal(param)
168 if err != nil {
169 return nil, err
170 }
Tang Chenga412d202016-01-27 09:24:53 +0800171 var r *goreq.Response
172 r, err = goreq.Request{
173 Uri: full_url,
174 Method: "POST",
175 ContentType: "application/json",
176 Body: data,
177 Timeout: time.Duration(3) * time.Second}.Do()
Tang Cheng32e32562015-07-08 17:08:03 +0800178 if err != nil || r.StatusCode != 200 {
179 log.Errorf("Status=%v, err=%v", r, err)
180 }
181 return r, err
182}
183
184func (w *WebSession) Auth() error {
qiaoweica037fa2015-07-10 18:31:53 +0800185 token, err := w.getAuthToken()
186 if err != nil {
187 return err
188 }
189 err = w.getAppAccessKey(token)
190 if err != nil {
191 return err
192 }
Tang Cheng32e32562015-07-08 17:08:03 +0800193 return nil
194}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800195
Tang Cheng0b9abf12015-08-20 09:55:32 +0800196func NewSession(appid, appsecret, termid, baseurl string, timeout int, sslVerify bool) *WebSession {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800197 return &WebSession{
198 AppId: appid,
199 Appsecret: appsecret,
200 TermId: termid,
201 BaseUrl: baseurl,
202 DefaultTimeout: timeout,
Tang Cheng78513ea2015-10-28 14:32:02 +0800203 ssl_verify: sslVerify,
204 httpConnectionPool: sync.Pool{New: func() interface{} {
205 return newTransport(baseurl, sslVerify)
206 }}}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800207}
208
qiaoweica037fa2015-07-10 18:31:53 +0800209func (w *WebSession) getAuthToken() (string, error) {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800210 type FormJson struct {
211 AppId string `json:"app_id"`
212 TermId string `json:"term_id"`
213 AccessToken string `json:"access_token"`
214 }
215
Tang Cheng26b91152015-07-22 12:26:52 +0800216 uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800217
218 params := make(map[string]string)
219 params["term_id"] = w.TermId
220 r, err := w.DoGet(uri, params)
221
Tang Chengf8716aa2015-08-19 10:20:40 +0800222 if err != nil {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800223 // log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
Tang Chengf8716aa2015-08-19 10:20:40 +0800224 return "", err
225 }
226 if r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800227 return "", errors.New("请求失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800228 }
229
qiaoweica037fa2015-07-10 18:31:53 +0800230 body, err := ioutil.ReadAll(r.Body)
Tang Cheng91665852015-08-29 22:17:20 +0800231 defer r.Body.Close()
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800232
qiaoweica037fa2015-07-10 18:31:53 +0800233 s := &FormJson{}
234 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800235 if err != nil {
236 log.Errorf("json unmarshal err %v", err)
qiaoweica037fa2015-07-10 18:31:53 +0800237 return "", errors.New("解析失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800238 }
qiaoweica037fa2015-07-10 18:31:53 +0800239 return s.AccessToken, nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800240}
qiaoweica037fa2015-07-10 18:31:53 +0800241func (w *WebSession) getAppAccessKey(token string) error {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800242 type FormJson struct {
qiaoweica037fa2015-07-10 18:31:53 +0800243 AppId string `json:"app_id"`
244 TermId string `json:"term_id"`
245 SessionKey string `json:"session_key"`
246 CardKey string `json:"card_key"`
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800247 }
248
Tang Cheng26b91152015-07-22 12:26:52 +0800249 uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800250
251 params := make(map[string]string)
252 params["term_id"] = w.TermId
qiaoweica037fa2015-07-10 18:31:53 +0800253 params["access_token"] = token
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800254 params["timestamp"] = w.GetTimestamp()
255 params["v"] = "1"
qiaoweica037fa2015-07-10 18:31:53 +0800256 params["sign"] = w.Sign(token + params["timestamp"])
257 params["sign_method"] = "HMAC"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800258
qiaoweica037fa2015-07-10 18:31:53 +0800259 r, err := w.DoGet(uri, params)
Tang Cheng55814742015-09-08 17:24:05 +0800260 if r != nil {
261 defer r.Body.Close()
262 }
zongqiang.zhang134f4182016-06-14 15:23:22 +0800263 if err != nil {
264 log.Errorf("err = %v\n", err)
qiaoweica037fa2015-07-10 18:31:53 +0800265 return err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800266 }
zongqiang.zhang134f4182016-06-14 15:23:22 +0800267 if r.StatusCode != 200 {
268 log.Errorf(" errcode = %v\n", r.StatusCode)
269 return errors.New(fmt.Sprintf("code %v", r.StatusCode))
270 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800271
qiaoweica037fa2015-07-10 18:31:53 +0800272 body, err := ioutil.ReadAll(r.Body)
qiaoweica037fa2015-07-10 18:31:53 +0800273
274 s := &FormJson{}
275 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800276 if err != nil {
277 log.Errorf("json unmarshal err %v", err)
zongqiang.zhang134f4182016-06-14 15:23:22 +0800278 return err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800279 }
qiaoweica037fa2015-07-10 18:31:53 +0800280 w.session_key = s.SessionKey
281 return nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800282}
Tang Cheng26b91152015-07-22 12:26:52 +0800283
284func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) {
285 call_data := request.Serialize()
286 params := make(map[string]string)
287 params["funcdata"] = call_data
288 r, err := w.DoPost("/ecardservice/ecardapi", params)
289
Tang Cheng55814742015-09-08 17:24:05 +0800290 if r != nil {
291 defer r.Body.Close()
292 }
Tang Chengf16121a2015-07-27 13:46:14 +0800293 if err != nil {
Tang Cheng26b91152015-07-22 12:26:52 +0800294 log.Errorf(" err = %v\n", err)
295 return nil, err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800296 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800297
Tang Chengf16121a2015-07-27 13:46:14 +0800298 if r.StatusCode != 200 {
299 return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode))
300 }
301
Tang Cheng26b91152015-07-22 12:26:52 +0800302 body, err := ioutil.ReadAll(r.Body)
Tang Cheng26b91152015-07-22 12:26:52 +0800303 return NewMessageReader(body), nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800304}
Tang Chengf16121a2015-07-27 13:46:14 +0800305
306func (w *WebSession) CallService(path string, params map[string]interface{},
307 sign_field []string, timeout int) (response *ServiceResponse, err error) {
308
309 return w.CallService2(path, params, timeout, sign_field...)
310}
311
312func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int,
313 sign_field ...string) (response *ServiceResponse, err error) {
Tang Chengf16121a2015-07-27 13:46:14 +0800314 err = nil
315 params["app_id"] = w.AppId
316 params["term_id"] = w.TermId
317 ts := w.GetTimestamp()
318 params["timestamp"] = ts
319
320 vl := &url.Values{}
321 for k, v := range params {
322 vl.Set(k, fmt.Sprintf("%v", v))
323 }
324
325 sign_data := ""
326 for _, k := range sign_field {
327 if v, ok := params[k]; ok {
328 sign_data += fmt.Sprintf("%v", v)
329 }
330 }
331 sign_data += ts + w.session_key
332 vl.Set("sign_method", "HMAC")
333 log.Debugf("Sign: key[%v] data[%v]\n", w.session_key, sign_data)
334 vl.Set("sign", w.SignWithKey(w.Appsecret, sign_data))
335
336 full_url := w.BaseUrl + path
337 log.Debugf("CallService: %v\n", full_url)
Tang Chenga412d202016-01-27 09:24:53 +0800338 var r *goreq.Response
339 r, err = goreq.Request{
340 Uri: full_url,
341 Accept: "application/json",
342 ContentType: "application/x-www-form-urlencoded",
343 Method: "POST",
344 Timeout: time.Duration(timeout) * time.Second,
345 Body: vl.Encode()}.Do()
Tang Chengf16121a2015-07-27 13:46:14 +0800346 if err != nil {
347 log.Errorf("Status=%v, err=%v", r, err)
348 return
349 }
350 if r.StatusCode != 200 {
351 log.Errorf("Request Error %v\n", r.StatusCode)
352 err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode))
353 return
354 }
Tang Chenga412d202016-01-27 09:24:53 +0800355 if r.Body != nil {
356 defer r.Body.Close()
357 }
Tang Chengf16121a2015-07-27 13:46:14 +0800358 body, err := ioutil.ReadAll(r.Body)
Tang Chengf16121a2015-07-27 13:46:14 +0800359 var s interface{}
360 err = json.Unmarshal(body, &s)
361 if err != nil {
362 log.Errorf("json unmarshal err %v", err)
363 return
364 }
365 response = NewServiceResponseFromJson(s)
366 return
367}