blob: 47d750d4cc5df810f66169b6ca6d3f781dc87e74 [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
75func (r *ServiceResponse) GetFloatValue(name string) float64 {
76 if s, ok := r.Result[name]; ok {
77 t := fmt.Sprintf("%v", s)
78 if f, err := strconv.ParseFloat(t, 64); err != nil {
79 return 0.0
80 } else {
81 return f
82 }
83 } else {
84 return 0.0
85 }
86}
87
Tang Cheng32e32562015-07-08 17:08:03 +080088func (w *WebSession) DoGet(uri string, params map[string]string) (*http.Response, error) {
Tang Cheng78513ea2015-10-28 14:32:02 +080089 transport := w.httpConnectionPool.Get().(*http.Transport)
90 defer w.httpConnectionPool.Put(transport)
91 client := &http.Client{Transport: transport, Timeout: time.Duration(3) * time.Second}
Tang Cheng32e32562015-07-08 17:08:03 +080092
93 full_url := w.BaseUrl + uri
94
95 vl := url.Values{}
Tang Cheng32e32562015-07-08 17:08:03 +080096
97 if params != nil {
98 for k, v := range params {
99 vl.Add(k, v)
100 }
101 }
Tang Cheng32e32562015-07-08 17:08:03 +0800102 full_url = full_url + "?" + vl.Encode()
Tang Chengf16121a2015-07-27 13:46:14 +0800103 // fmt.Printf("%v\n", full_url)
Tang Cheng32e32562015-07-08 17:08:03 +0800104 return client.Get(full_url)
105}
106
107func (w *WebSession) GetTimestamp() string {
108 t := time.Now()
109 return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(),
110 t.Hour(), t.Minute(), t.Second())
111}
112
Tang Chengf16121a2015-07-27 13:46:14 +0800113func (w *WebSession) SignWithKey(key, message string) string {
114 mac := hmac.New(sha1.New, []byte(key))
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800115 mac.Write([]byte(message))
116 res := mac.Sum(nil)
Tang Cheng26b91152015-07-22 12:26:52 +0800117 return hex.EncodeToString(res)
Tang Cheng32e32562015-07-08 17:08:03 +0800118}
Tang Chengf16121a2015-07-27 13:46:14 +0800119func (w *WebSession) Sign(message string) string {
120 return w.SignWithKey(w.Appsecret, message)
121}
Tang Cheng32e32562015-07-08 17:08:03 +0800122
Tang Cheng78513ea2015-10-28 14:32:02 +0800123func newTransport(baseurl string, ssl_verify bool) *http.Transport {
Tang Chengf8716aa2015-08-19 10:20:40 +0800124 var transport http.Transport
Tang Cheng78513ea2015-10-28 14:32:02 +0800125 if strings.HasPrefix(baseurl, "https://") {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800126 var b bool
Tang Cheng78513ea2015-10-28 14:32:02 +0800127 if ssl_verify {
Tang Cheng0b9abf12015-08-20 09:55:32 +0800128 b = false
129 } else {
130 b = true
131 }
Tang Cheng78513ea2015-10-28 14:32:02 +0800132 transport = http.Transport{MaxIdleConnsPerHost: 0,
Tang Cheng91665852015-08-29 22:17:20 +0800133 TLSClientConfig: &tls.Config{InsecureSkipVerify: b},
Tang Cheng78513ea2015-10-28 14:32:02 +0800134 TLSHandshakeTimeout: time.Duration(1) * time.Second,
Tang Cheng91665852015-08-29 22:17:20 +0800135 Dial: func(network, addr string) (net.Conn, error) {
136 default_timeout := time.Duration(1) * time.Second
137 return net.DialTimeout(network, addr, default_timeout)
138 }}
Tang Cheng78513ea2015-10-28 14:32:02 +0800139 } else if strings.HasPrefix(baseurl, "http://") {
140 transport = http.Transport{MaxIdleConnsPerHost: 0,
Tang Cheng91665852015-08-29 22:17:20 +0800141 Dial: func(network, addr string) (net.Conn, error) {
142 default_timeout := time.Duration(1) * time.Second
143 return net.DialTimeout(network, addr, default_timeout)
144 }}
Tang Chengf8716aa2015-08-19 10:20:40 +0800145 }
Tang Cheng78513ea2015-10-28 14:32:02 +0800146 log.Debugf("创建新连接")
147 return &transport
Tang Chengf16121a2015-07-27 13:46:14 +0800148}
Tang Chengf8716aa2015-08-19 10:20:40 +0800149
Tang Chenga412d202016-01-27 09:24:53 +0800150func (w *WebSession) DoPost(uri string, param map[string]string) (*goreq.Response, error) {
Tang Cheng26b91152015-07-22 12:26:52 +0800151 param["app_id"] = w.AppId
Tang Chengf8716aa2015-08-19 10:20:40 +0800152 param["term_id"] = w.TermId
Tang Cheng26b91152015-07-22 12:26:52 +0800153 param["sign_method"] = "HMAC"
154 param["session_key"] = w.session_key
Tang Cheng32e32562015-07-08 17:08:03 +0800155 ts := w.GetTimestamp()
Tang Cheng26b91152015-07-22 12:26:52 +0800156 param["timestamp"] = ts
157 param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800158
Tang Cheng32e32562015-07-08 17:08:03 +0800159 full_url := w.BaseUrl + uri
Tang Cheng26b91152015-07-22 12:26:52 +0800160 data, err := json.Marshal(param)
161 if err != nil {
162 return nil, err
163 }
Tang Chenga412d202016-01-27 09:24:53 +0800164 var r *goreq.Response
165 r, err = goreq.Request{
166 Uri: full_url,
167 Method: "POST",
168 ContentType: "application/json",
169 Body: data,
170 Timeout: time.Duration(3) * time.Second}.Do()
Tang Cheng32e32562015-07-08 17:08:03 +0800171 if err != nil || r.StatusCode != 200 {
172 log.Errorf("Status=%v, err=%v", r, err)
173 }
174 return r, err
175}
176
177func (w *WebSession) Auth() error {
qiaoweica037fa2015-07-10 18:31:53 +0800178 token, err := w.getAuthToken()
179 if err != nil {
180 return err
181 }
182 err = w.getAppAccessKey(token)
183 if err != nil {
184 return err
185 }
Tang Cheng32e32562015-07-08 17:08:03 +0800186 return nil
187}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800188
Tang Cheng0b9abf12015-08-20 09:55:32 +0800189func NewSession(appid, appsecret, termid, baseurl string, timeout int, sslVerify bool) *WebSession {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800190 return &WebSession{
191 AppId: appid,
192 Appsecret: appsecret,
193 TermId: termid,
194 BaseUrl: baseurl,
195 DefaultTimeout: timeout,
Tang Cheng78513ea2015-10-28 14:32:02 +0800196 ssl_verify: sslVerify,
197 httpConnectionPool: sync.Pool{New: func() interface{} {
198 return newTransport(baseurl, sslVerify)
199 }}}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800200}
201
qiaoweica037fa2015-07-10 18:31:53 +0800202func (w *WebSession) getAuthToken() (string, error) {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800203 type FormJson struct {
204 AppId string `json:"app_id"`
205 TermId string `json:"term_id"`
206 AccessToken string `json:"access_token"`
207 }
208
Tang Cheng26b91152015-07-22 12:26:52 +0800209 uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800210
211 params := make(map[string]string)
212 params["term_id"] = w.TermId
213 r, err := w.DoGet(uri, params)
214
Tang Chengf8716aa2015-08-19 10:20:40 +0800215 if err != nil {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800216 // log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
Tang Chengf8716aa2015-08-19 10:20:40 +0800217 return "", err
218 }
219 if r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800220 return "", errors.New("请求失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800221 }
222
qiaoweica037fa2015-07-10 18:31:53 +0800223 body, err := ioutil.ReadAll(r.Body)
Tang Cheng91665852015-08-29 22:17:20 +0800224 defer r.Body.Close()
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800225
qiaoweica037fa2015-07-10 18:31:53 +0800226 s := &FormJson{}
227 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800228 if err != nil {
229 log.Errorf("json unmarshal err %v", err)
qiaoweica037fa2015-07-10 18:31:53 +0800230 return "", errors.New("解析失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800231 }
qiaoweica037fa2015-07-10 18:31:53 +0800232 return s.AccessToken, nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800233}
qiaoweica037fa2015-07-10 18:31:53 +0800234func (w *WebSession) getAppAccessKey(token string) error {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800235 type FormJson struct {
qiaoweica037fa2015-07-10 18:31:53 +0800236 AppId string `json:"app_id"`
237 TermId string `json:"term_id"`
238 SessionKey string `json:"session_key"`
239 CardKey string `json:"card_key"`
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800240 }
241
Tang Cheng26b91152015-07-22 12:26:52 +0800242 uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800243
244 params := make(map[string]string)
245 params["term_id"] = w.TermId
qiaoweica037fa2015-07-10 18:31:53 +0800246 params["access_token"] = token
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800247 params["timestamp"] = w.GetTimestamp()
248 params["v"] = "1"
qiaoweica037fa2015-07-10 18:31:53 +0800249 params["sign"] = w.Sign(token + params["timestamp"])
250 params["sign_method"] = "HMAC"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800251
qiaoweica037fa2015-07-10 18:31:53 +0800252 r, err := w.DoGet(uri, params)
Tang Cheng55814742015-09-08 17:24:05 +0800253 if r != nil {
254 defer r.Body.Close()
255 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800256 if err != nil || r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800257 log.Errorf(" err = %v\n", err)
258 return err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800259 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800260
qiaoweica037fa2015-07-10 18:31:53 +0800261 body, err := ioutil.ReadAll(r.Body)
qiaoweica037fa2015-07-10 18:31:53 +0800262
263 s := &FormJson{}
264 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800265 if err != nil {
266 log.Errorf("json unmarshal err %v", err)
267 }
qiaoweica037fa2015-07-10 18:31:53 +0800268 w.session_key = s.SessionKey
269 return nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800270}
Tang Cheng26b91152015-07-22 12:26:52 +0800271
272func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) {
273 call_data := request.Serialize()
274 params := make(map[string]string)
275 params["funcdata"] = call_data
276 r, err := w.DoPost("/ecardservice/ecardapi", params)
277
Tang Cheng55814742015-09-08 17:24:05 +0800278 if r != nil {
279 defer r.Body.Close()
280 }
Tang Chengf16121a2015-07-27 13:46:14 +0800281 if err != nil {
Tang Cheng26b91152015-07-22 12:26:52 +0800282 log.Errorf(" err = %v\n", err)
283 return nil, err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800284 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800285
Tang Chengf16121a2015-07-27 13:46:14 +0800286 if r.StatusCode != 200 {
287 return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode))
288 }
289
Tang Cheng26b91152015-07-22 12:26:52 +0800290 body, err := ioutil.ReadAll(r.Body)
Tang Cheng26b91152015-07-22 12:26:52 +0800291 return NewMessageReader(body), nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800292}
Tang Chengf16121a2015-07-27 13:46:14 +0800293
294func (w *WebSession) CallService(path string, params map[string]interface{},
295 sign_field []string, timeout int) (response *ServiceResponse, err error) {
296
297 return w.CallService2(path, params, timeout, sign_field...)
298}
299
300func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int,
301 sign_field ...string) (response *ServiceResponse, err error) {
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)
Tang Chenga412d202016-01-27 09:24:53 +0800326 var r *goreq.Response
327 r, err = goreq.Request{
328 Uri: full_url,
329 Accept: "application/json",
330 ContentType: "application/x-www-form-urlencoded",
331 Method: "POST",
332 Timeout: time.Duration(timeout) * time.Second,
333 Body: vl.Encode()}.Do()
Tang Chengf16121a2015-07-27 13:46:14 +0800334 if err != nil {
335 log.Errorf("Status=%v, err=%v", r, err)
336 return
337 }
338 if r.StatusCode != 200 {
339 log.Errorf("Request Error %v\n", r.StatusCode)
340 err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode))
341 return
342 }
Tang Chenga412d202016-01-27 09:24:53 +0800343 if r.Body != nil {
344 defer r.Body.Close()
345 }
Tang Chengf16121a2015-07-27 13:46:14 +0800346 body, err := ioutil.ReadAll(r.Body)
Tang Chengf16121a2015-07-27 13:46:14 +0800347 var s interface{}
348 err = json.Unmarshal(body, &s)
349 if err != nil {
350 log.Errorf("json unmarshal err %v", err)
351 return
352 }
353 response = NewServiceResponseFromJson(s)
354 return
355}