blob: 3857002fe62611338ffce36784dcb12889f737bb [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 }
127 transport = http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: b},
Tang Chengf8716aa2015-08-19 10:20:40 +0800128 TLSHandshakeTimeout: time.Duration(timeout) * time.Second}
129 } else if strings.HasPrefix(w.BaseUrl, "http://") {
130 transport = http.Transport{Dial: func(network, addr string) (net.Conn, error) {
131 default_timeout := time.Duration(timeout) * time.Second
132 return net.DialTimeout(network, addr, default_timeout)
133 }}
134 }
Tang Chengf16121a2015-07-27 13:46:14 +0800135 return &http.Client{Transport: &transport}
136}
Tang Chengf8716aa2015-08-19 10:20:40 +0800137
Tang Cheng26b91152015-07-22 12:26:52 +0800138func (w *WebSession) DoPost(uri string, param map[string]string) (*http.Response, error) {
Tang Chengf8716aa2015-08-19 10:20:40 +0800139 client := w.NewClient(3)
Tang Cheng26b91152015-07-22 12:26:52 +0800140 param["app_id"] = w.AppId
Tang Chengf8716aa2015-08-19 10:20:40 +0800141 param["term_id"] = w.TermId
Tang Cheng26b91152015-07-22 12:26:52 +0800142 param["sign_method"] = "HMAC"
143 param["session_key"] = w.session_key
Tang Cheng32e32562015-07-08 17:08:03 +0800144 ts := w.GetTimestamp()
Tang Cheng26b91152015-07-22 12:26:52 +0800145 param["timestamp"] = ts
146 param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800147
Tang Cheng32e32562015-07-08 17:08:03 +0800148 full_url := w.BaseUrl + uri
Tang Cheng26b91152015-07-22 12:26:52 +0800149 data, err := json.Marshal(param)
150 if err != nil {
151 return nil, err
152 }
153 var r *http.Response
154 r, err = client.Post(full_url, "application/json", bytes.NewReader(data))
Tang Cheng32e32562015-07-08 17:08:03 +0800155 if err != nil || r.StatusCode != 200 {
156 log.Errorf("Status=%v, err=%v", r, err)
157 }
158 return r, err
159}
160
161func (w *WebSession) Auth() error {
qiaoweica037fa2015-07-10 18:31:53 +0800162 token, err := w.getAuthToken()
163 if err != nil {
164 return err
165 }
166 err = w.getAppAccessKey(token)
167 if err != nil {
168 return err
169 }
Tang Cheng32e32562015-07-08 17:08:03 +0800170 return nil
171}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800172
Tang Cheng0b9abf12015-08-20 09:55:32 +0800173func NewSession(appid, appsecret, termid, baseurl string, timeout int, sslVerify bool) *WebSession {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800174 return &WebSession{
175 AppId: appid,
176 Appsecret: appsecret,
177 TermId: termid,
178 BaseUrl: baseurl,
179 DefaultTimeout: timeout,
Tang Cheng0b9abf12015-08-20 09:55:32 +0800180 ssl_verify: sslVerify}
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800181}
182
qiaoweica037fa2015-07-10 18:31:53 +0800183func (w *WebSession) getAuthToken() (string, error) {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800184 type FormJson struct {
185 AppId string `json:"app_id"`
186 TermId string `json:"term_id"`
187 AccessToken string `json:"access_token"`
188 }
189
Tang Cheng26b91152015-07-22 12:26:52 +0800190 uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800191
192 params := make(map[string]string)
193 params["term_id"] = w.TermId
194 r, err := w.DoGet(uri, params)
195
Tang Chengf8716aa2015-08-19 10:20:40 +0800196 if err != nil {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800197 // log.Errorf("Status = %v, err = %v\n", r.StatusCode, err)
Tang Chengf8716aa2015-08-19 10:20:40 +0800198 return "", err
199 }
200 if r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800201 return "", errors.New("请求失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800202 }
203
qiaoweica037fa2015-07-10 18:31:53 +0800204 body, err := ioutil.ReadAll(r.Body)
205 r.Body.Close()
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800206
qiaoweica037fa2015-07-10 18:31:53 +0800207 s := &FormJson{}
208 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800209 if err != nil {
210 log.Errorf("json unmarshal err %v", err)
qiaoweica037fa2015-07-10 18:31:53 +0800211 return "", errors.New("解析失败")
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800212 }
qiaoweica037fa2015-07-10 18:31:53 +0800213 return s.AccessToken, nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800214}
qiaoweica037fa2015-07-10 18:31:53 +0800215func (w *WebSession) getAppAccessKey(token string) error {
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800216 type FormJson struct {
qiaoweica037fa2015-07-10 18:31:53 +0800217 AppId string `json:"app_id"`
218 TermId string `json:"term_id"`
219 SessionKey string `json:"session_key"`
220 CardKey string `json:"card_key"`
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800221 }
222
Tang Cheng26b91152015-07-22 12:26:52 +0800223 uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800224
225 params := make(map[string]string)
226 params["term_id"] = w.TermId
qiaoweica037fa2015-07-10 18:31:53 +0800227 params["access_token"] = token
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800228 params["timestamp"] = w.GetTimestamp()
229 params["v"] = "1"
qiaoweica037fa2015-07-10 18:31:53 +0800230 params["sign"] = w.Sign(token + params["timestamp"])
231 params["sign_method"] = "HMAC"
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800232
qiaoweica037fa2015-07-10 18:31:53 +0800233 r, err := w.DoGet(uri, params)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800234 if err != nil || r.StatusCode != 200 {
qiaoweica037fa2015-07-10 18:31:53 +0800235 log.Errorf(" err = %v\n", err)
236 return err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800237 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800238
qiaoweica037fa2015-07-10 18:31:53 +0800239 body, err := ioutil.ReadAll(r.Body)
240 r.Body.Close()
qiaoweica037fa2015-07-10 18:31:53 +0800241
242 s := &FormJson{}
243 err = json.Unmarshal(body, &s)
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800244 if err != nil {
245 log.Errorf("json unmarshal err %v", err)
246 }
qiaoweica037fa2015-07-10 18:31:53 +0800247 w.session_key = s.SessionKey
248 return nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800249}
Tang Cheng26b91152015-07-22 12:26:52 +0800250
251func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) {
252 call_data := request.Serialize()
253 params := make(map[string]string)
254 params["funcdata"] = call_data
255 r, err := w.DoPost("/ecardservice/ecardapi", params)
256
Tang Chengf16121a2015-07-27 13:46:14 +0800257 if err != nil {
Tang Cheng26b91152015-07-22 12:26:52 +0800258 log.Errorf(" err = %v\n", err)
259 return nil, err
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800260 }
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800261
Tang Chengf16121a2015-07-27 13:46:14 +0800262 if r.StatusCode != 200 {
263 return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode))
264 }
265
Tang Cheng26b91152015-07-22 12:26:52 +0800266 body, err := ioutil.ReadAll(r.Body)
267 r.Body.Close()
268 return NewMessageReader(body), nil
zongqiang.zhangb8ab9b42015-07-10 17:45:20 +0800269}
Tang Chengf16121a2015-07-27 13:46:14 +0800270
271func (w *WebSession) CallService(path string, params map[string]interface{},
272 sign_field []string, timeout int) (response *ServiceResponse, err error) {
273
274 return w.CallService2(path, params, timeout, sign_field...)
275}
276
277func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int,
278 sign_field ...string) (response *ServiceResponse, err error) {
279 client := w.NewClient(timeout)
280 err = nil
281 params["app_id"] = w.AppId
282 params["term_id"] = w.TermId
283 ts := w.GetTimestamp()
284 params["timestamp"] = ts
285
286 vl := &url.Values{}
287 for k, v := range params {
288 vl.Set(k, fmt.Sprintf("%v", v))
289 }
290
291 sign_data := ""
292 for _, k := range sign_field {
293 if v, ok := params[k]; ok {
294 sign_data += fmt.Sprintf("%v", v)
295 }
296 }
297 sign_data += ts + w.session_key
298 vl.Set("sign_method", "HMAC")
299 log.Debugf("Sign: key[%v] data[%v]\n", w.session_key, sign_data)
300 vl.Set("sign", w.SignWithKey(w.Appsecret, sign_data))
301
302 full_url := w.BaseUrl + path
303 log.Debugf("CallService: %v\n", full_url)
304 var r *http.Response
305 r, err = client.Post(full_url, "application/x-www-form-urlencoded",
306 bytes.NewReader([]byte(vl.Encode())))
307 if err != nil {
308 log.Errorf("Status=%v, err=%v", r, err)
309 return
310 }
311 if r.StatusCode != 200 {
312 log.Errorf("Request Error %v\n", r.StatusCode)
313 err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode))
314 return
315 }
316 body, err := ioutil.ReadAll(r.Body)
317 r.Body.Close()
318 var s interface{}
319 err = json.Unmarshal(body, &s)
320 if err != nil {
321 log.Errorf("json unmarshal err %v", err)
322 return
323 }
324 response = NewServiceResponseFromJson(s)
325 return
326}