blob: ead20d56b3877360bf62955a02c1fd0ddcc4b35f [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"
Tang Cheng78513ea2015-10-28 14:32:02 +080019 "sync"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +080020 "time"
21)
Tang Cheng32e32562015-07-08 17:08:03 +080022
Tang Cheng32e32562015-07-08 17:08:03 +080023type WebSession struct {
Tang Cheng78513ea2015-10-28 14:32:02 +080024 AppId string
25 TermId string
26 Appsecret string
27 BaseUrl string
28 DefaultTimeout int
29 session_key string
30 ssl_verify bool
31 httpConnectionPool sync.Pool
Tang Cheng32e32562015-07-08 17:08:03 +080032}
33
Tang Chengf16121a2015-07-27 13:46:14 +080034func safe_get_json_int(value interface{}) int {
35 if value == nil {
36 return 0
37 }
38 s := fmt.Sprintf("%v", value)
39 if i, err := strconv.Atoi(s); err != nil {
40 return 0
41 } else {
42 return i
43 }
44}
45
46type ServiceResponse struct {
47 RetCode int
48 RetMsg string
49 Result map[string]interface{}
50}
51
52func NewServiceResponseFromJson(json_data interface{}) *ServiceResponse {
53 if json_data == nil {
54 return nil
55 }
56 res := &ServiceResponse{}
57 res.Result = json_data.(map[string]interface{})
58 res.RetCode = safe_get_json_int(res.Result["retcode"])
59 res.RetMsg = res.GetStrValue("retmsg")
60 return res
61}
62func (r *ServiceResponse) GetIntValue(name string) int {
63 return safe_get_json_int(r.Result[name])
64}
65
66func (r *ServiceResponse) GetStrValue(name string) string {
67 if s, ok := r.Result[name]; ok {
68 return fmt.Sprintf("%v", s)
69 } else {
70 return ""
71 }
72}
73
74func (r *ServiceResponse) GetFloatValue(name string) float64 {
75 if s, ok := r.Result[name]; ok {
76 t := fmt.Sprintf("%v", s)
77 if f, err := strconv.ParseFloat(t, 64); err != nil {
78 return 0.0
79 } else {
80 return f
81 }
82 } else {
83 return 0.0
84 }
85}
86
Tang Cheng32e32562015-07-08 17:08:03 +080087func (w *WebSession) DoGet(uri string, params map[string]string) (*http.Response, error) {
Tang Cheng78513ea2015-10-28 14:32:02 +080088 transport := w.httpConnectionPool.Get().(*http.Transport)
89 defer w.httpConnectionPool.Put(transport)
90 client := &http.Client{Transport: transport, Timeout: time.Duration(3) * time.Second}
Tang Cheng32e32562015-07-08 17:08:03 +080091
92 full_url := w.BaseUrl + uri
93
94 vl := url.Values{}
Tang Cheng32e32562015-07-08 17:08:03 +080095
96 if params != nil {
97 for k, v := range params {
98 vl.Add(k, v)
99 }
100 }
Tang Cheng32e32562015-07-08 17:08:03 +0800101 full_url = full_url + "?" + vl.Encode()
Tang Chengf16121a2015-07-27 13:46:14 +0800102 // fmt.Printf("%v\n", full_url)
Tang Cheng32e32562015-07-08 17:08:03 +0800103 return client.Get(full_url)
104}
105
106func (w *WebSession) GetTimestamp() string {
107 t := time.Now()
108 return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(),
109 t.Hour(), t.Minute(), t.Second())
110}
111
Tang Chengf16121a2015-07-27 13:46:14 +0800112func (w *WebSession) SignWithKey(key, message string) string {
113 mac := hmac.New(sha1.New, []byte(key))
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800114 mac.Write([]byte(message))
115 res := mac.Sum(nil)
Tang Cheng26b91152015-07-22 12:26:52 +0800116 return hex.EncodeToString(res)
Tang Cheng32e32562015-07-08 17:08:03 +0800117}
Tang Chengf16121a2015-07-27 13:46:14 +0800118func (w *WebSession) Sign(message string) string {
119 return w.SignWithKey(w.Appsecret, message)
120}
Tang Cheng32e32562015-07-08 17:08:03 +0800121
Tang Cheng78513ea2015-10-28 14:32:02 +0800122func newTransport(baseurl string, ssl_verify bool) *http.Transport {
Tang Chengf8716aa2015-08-19 10:20:40 +0800123 var transport http.Transport
Tang Cheng78513ea2015-10-28 14:32:02 +0800124 if strings.HasPrefix(baseurl, "https://") {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800125 var b bool
Tang Cheng78513ea2015-10-28 14:32:02 +0800126 if ssl_verify {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800127 b = false
128 } else {
129 b = true
130 }
Tang Cheng78513ea2015-10-28 14:32:02 +0800131 transport = http.Transport{MaxIdleConnsPerHost: 0,
Tang Cheng91665852015-08-29 22:17:20 +0800132 TLSClientConfig: &tls.Config{InsecureSkipVerify: b},
Tang Cheng78513ea2015-10-28 14:32:02 +0800133 TLSHandshakeTimeout: time.Duration(1) * time.Second,
Tang Cheng91665852015-08-29 22:17:20 +0800134 Dial: func(network, addr string) (net.Conn, error) {
135 default_timeout := time.Duration(1) * time.Second
136 return net.DialTimeout(network, addr, default_timeout)
137 }}
Tang Cheng78513ea2015-10-28 14:32:02 +0800138 } else if strings.HasPrefix(baseurl, "http://") {
139 transport = http.Transport{MaxIdleConnsPerHost: 0,
Tang Cheng91665852015-08-29 22:17:20 +0800140 Dial: func(network, addr string) (net.Conn, error) {
141 default_timeout := time.Duration(1) * time.Second
142 return net.DialTimeout(network, addr, default_timeout)
143 }}
Tang Chengf8716aa2015-08-19 10:20:40 +0800144 }
Tang Cheng78513ea2015-10-28 14:32:02 +0800145 log.Debugf("创建新连接")
146 return &transport
Tang Chengf16121a2015-07-27 13:46:14 +0800147}
Tang Chengf8716aa2015-08-19 10:20:40 +0800148
Tang Cheng26b91152015-07-22 12:26:52 +0800149func (w *WebSession) DoPost(uri string, param map[string]string) (*http.Response, error) {
Tang Cheng78513ea2015-10-28 14:32:02 +0800150 transport := w.httpConnectionPool.Get().(*http.Transport)
151 defer w.httpConnectionPool.Put(transport)
152 client := &http.Client{Transport: transport, Timeout: time.Duration(3) * time.Second}
Tang Cheng26b91152015-07-22 12:26:52 +0800153 param["app_id"] = w.AppId
Tang Chengf8716aa2015-08-19 10:20:40 +0800154 param["term_id"] = w.TermId
Tang Cheng26b91152015-07-22 12:26:52 +0800155 param["sign_method"] = "HMAC"
156 param["session_key"] = w.session_key
Tang Cheng32e32562015-07-08 17:08:03 +0800157 ts := w.GetTimestamp()
Tang Cheng26b91152015-07-22 12:26:52 +0800158 param["timestamp"] = ts
159 param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800160
Tang Cheng32e32562015-07-08 17:08:03 +0800161 full_url := w.BaseUrl + uri
Tang Cheng26b91152015-07-22 12:26:52 +0800162 data, err := json.Marshal(param)
163 if err != nil {
164 return nil, err
165 }
166 var r *http.Response
167 r, err = client.Post(full_url, "application/json", bytes.NewReader(data))
Tang Cheng32e32562015-07-08 17:08:03 +0800168 if err != nil || r.StatusCode != 200 {
169 log.Errorf("Status=%v, err=%v", r, err)
170 }
171 return r, err
172}
173
174func (w *WebSession) Auth() error {
qiaoweica037fa2015-07-10 18:31:53 +0800175 token, err := w.getAuthToken()
176 if err != nil {
177 return err
178 }
179 err = w.getAppAccessKey(token)
180 if err != nil {
181 return err
182 }
Tang Cheng32e32562015-07-08 17:08:03 +0800183 return nil
184}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800185
Tang Cheng0b9abf12015-08-20 09:55:32 +0800186func NewSession(appid, appsecret, termid, baseurl string, timeout int, sslVerify bool) *WebSession {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800187 return &WebSession{
188 AppId: appid,
189 Appsecret: appsecret,
190 TermId: termid,
191 BaseUrl: baseurl,
192 DefaultTimeout: timeout,
Tang Cheng78513ea2015-10-28 14:32:02 +0800193 ssl_verify: sslVerify,
194 httpConnectionPool: sync.Pool{New: func() interface{} {
195 return newTransport(baseurl, sslVerify)
196 }}}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800197}
198
qiaoweica037fa2015-07-10 18:31:53 +0800199func (w *WebSession) getAuthToken() (string, error) {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800200 type FormJson struct {
201 AppId string `json:"app_id"`
202 TermId string `json:"term_id"`
203 AccessToken string `json:"access_token"`
204 }
205
Tang Cheng26b91152015-07-22 12:26:52 +0800206 uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800207
208 params := make(map[string]string)
209 params["term_id"] = w.TermId
210 r, err := w.DoGet(uri, params)
211
Tang Chengf8716aa2015-08-19 10:20:40 +0800212 if err != nil {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800213 // log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
Tang Chengf8716aa2015-08-19 10:20:40 +0800214 return "", err
215 }
216 if r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800217 return "", errors.New("请求失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800218 }
219
qiaoweica037fa2015-07-10 18:31:53 +0800220 body, err := ioutil.ReadAll(r.Body)
Tang Cheng91665852015-08-29 22:17:20 +0800221 defer r.Body.Close()
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800222
qiaoweica037fa2015-07-10 18:31:53 +0800223 s := &FormJson{}
224 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800225 if err != nil {
226 log.Errorf("json unmarshal err %v", err)
qiaoweica037fa2015-07-10 18:31:53 +0800227 return "", errors.New("解析失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800228 }
qiaoweica037fa2015-07-10 18:31:53 +0800229 return s.AccessToken, nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800230}
qiaoweica037fa2015-07-10 18:31:53 +0800231func (w *WebSession) getAppAccessKey(token string) error {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800232 type FormJson struct {
qiaoweica037fa2015-07-10 18:31:53 +0800233 AppId string `json:"app_id"`
234 TermId string `json:"term_id"`
235 SessionKey string `json:"session_key"`
236 CardKey string `json:"card_key"`
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800237 }
238
Tang Cheng26b91152015-07-22 12:26:52 +0800239 uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800240
241 params := make(map[string]string)
242 params["term_id"] = w.TermId
qiaoweica037fa2015-07-10 18:31:53 +0800243 params["access_token"] = token
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800244 params["timestamp"] = w.GetTimestamp()
245 params["v"] = "1"
qiaoweica037fa2015-07-10 18:31:53 +0800246 params["sign"] = w.Sign(token + params["timestamp"])
247 params["sign_method"] = "HMAC"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800248
qiaoweica037fa2015-07-10 18:31:53 +0800249 r, err := w.DoGet(uri, params)
Tang Cheng55814742015-09-08 17:24:05 +0800250 if r != nil {
251 defer r.Body.Close()
252 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800253 if err != nil || r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800254 log.Errorf(" err = %v\n", err)
255 return err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800256 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800257
qiaoweica037fa2015-07-10 18:31:53 +0800258 body, err := ioutil.ReadAll(r.Body)
qiaoweica037fa2015-07-10 18:31:53 +0800259
260 s := &FormJson{}
261 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800262 if err != nil {
263 log.Errorf("json unmarshal err %v", err)
264 }
qiaoweica037fa2015-07-10 18:31:53 +0800265 w.session_key = s.SessionKey
266 return nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800267}
Tang Cheng26b91152015-07-22 12:26:52 +0800268
269func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) {
270 call_data := request.Serialize()
271 params := make(map[string]string)
272 params["funcdata"] = call_data
273 r, err := w.DoPost("/ecardservice/ecardapi", params)
274
Tang Cheng55814742015-09-08 17:24:05 +0800275 if r != nil {
276 defer r.Body.Close()
277 }
Tang Chengf16121a2015-07-27 13:46:14 +0800278 if err != nil {
Tang Cheng26b91152015-07-22 12:26:52 +0800279 log.Errorf(" err = %v\n", err)
280 return nil, err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800281 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800282
Tang Chengf16121a2015-07-27 13:46:14 +0800283 if r.StatusCode != 200 {
284 return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode))
285 }
286
Tang Cheng26b91152015-07-22 12:26:52 +0800287 body, err := ioutil.ReadAll(r.Body)
Tang Cheng26b91152015-07-22 12:26:52 +0800288 return NewMessageReader(body), nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800289}
Tang Chengf16121a2015-07-27 13:46:14 +0800290
291func (w *WebSession) CallService(path string, params map[string]interface{},
292 sign_field []string, timeout int) (response *ServiceResponse, err error) {
293
294 return w.CallService2(path, params, timeout, sign_field...)
295}
296
297func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int,
298 sign_field ...string) (response *ServiceResponse, err error) {
Tang Cheng78513ea2015-10-28 14:32:02 +0800299 transport := w.httpConnectionPool.Get().(*http.Transport)
300 defer w.httpConnectionPool.Put(transport)
301 client := http.Client{Transport: transport, Timeout: time.Duration(timeout) * time.Second}
Tang Chengf16121a2015-07-27 13:46:14 +0800302 err = nil
303 params["app_id"] = w.AppId
304 params["term_id"] = w.TermId
305 ts := w.GetTimestamp()
306 params["timestamp"] = ts
307
308 vl := &url.Values{}
309 for k, v := range params {
310 vl.Set(k, fmt.Sprintf("%v", v))
311 }
312
313 sign_data := ""
314 for _, k := range sign_field {
315 if v, ok := params[k]; ok {
316 sign_data += fmt.Sprintf("%v", v)
317 }
318 }
319 sign_data += ts + w.session_key
320 vl.Set("sign_method", "HMAC")
321 log.Debugf("Sign: key[%v] data[%v]\n", w.session_key, sign_data)
322 vl.Set("sign", w.SignWithKey(w.Appsecret, sign_data))
323
324 full_url := w.BaseUrl + path
325 log.Debugf("CallService: %v\n", full_url)
326 var r *http.Response
327 r, err = client.Post(full_url, "application/x-www-form-urlencoded",
328 bytes.NewReader([]byte(vl.Encode())))
Tang Cheng55814742015-09-08 17:24:05 +0800329 if r != nil {
330 defer r.Body.Close()
331 }
Tang Chengf16121a2015-07-27 13:46:14 +0800332 if err != nil {
333 log.Errorf("Status=%v, err=%v", r, err)
334 return
335 }
336 if r.StatusCode != 200 {
337 log.Errorf("Request Error %v\n", r.StatusCode)
338 err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode))
339 return
340 }
341 body, err := ioutil.ReadAll(r.Body)
Tang Chengf16121a2015-07-27 13:46:14 +0800342 var s interface{}
343 err = json.Unmarshal(body, &s)
344 if err != nil {
345 log.Errorf("json unmarshal err %v", err)
346 return
347 }
348 response = NewServiceResponseFromJson(s)
349 return
350}