| package swservice |
| |
| import ( |
| "bytes" |
| "crypto/hmac" |
| "crypto/sha1" |
| "crypto/tls" |
| "encoding/hex" |
| "encoding/json" |
| "errors" |
| "fmt" |
| log "github.com/Sirupsen/logrus" |
| "io/ioutil" |
| "net" |
| "net/http" |
| "net/url" |
| "strconv" |
| "strings" |
| "time" |
| ) |
| |
| type WebSession struct { |
| AppId string |
| TermId string |
| Appsecret string |
| BaseUrl string |
| DefaultTimeout int |
| session_key string |
| ssl_verify bool |
| } |
| |
| func safe_get_json_int(value interface{}) int { |
| if value == nil { |
| return 0 |
| } |
| s := fmt.Sprintf("%v", value) |
| if i, err := strconv.Atoi(s); err != nil { |
| return 0 |
| } else { |
| return i |
| } |
| } |
| |
| type ServiceResponse struct { |
| RetCode int |
| RetMsg string |
| Result map[string]interface{} |
| } |
| |
| func NewServiceResponseFromJson(json_data interface{}) *ServiceResponse { |
| if json_data == nil { |
| return nil |
| } |
| res := &ServiceResponse{} |
| res.Result = json_data.(map[string]interface{}) |
| res.RetCode = safe_get_json_int(res.Result["retcode"]) |
| res.RetMsg = res.GetStrValue("retmsg") |
| return res |
| } |
| func (r *ServiceResponse) GetIntValue(name string) int { |
| return safe_get_json_int(r.Result[name]) |
| } |
| |
| func (r *ServiceResponse) GetStrValue(name string) string { |
| if s, ok := r.Result[name]; ok { |
| return fmt.Sprintf("%v", s) |
| } else { |
| return "" |
| } |
| } |
| |
| func (r *ServiceResponse) GetFloatValue(name string) float64 { |
| if s, ok := r.Result[name]; ok { |
| t := fmt.Sprintf("%v", s) |
| if f, err := strconv.ParseFloat(t, 64); err != nil { |
| return 0.0 |
| } else { |
| return f |
| } |
| } else { |
| return 0.0 |
| } |
| } |
| |
| func (w *WebSession) DoGet(uri string, params map[string]string) (*http.Response, error) { |
| client := w.NewClient(3) |
| |
| full_url := w.BaseUrl + uri |
| |
| vl := url.Values{} |
| |
| if params != nil { |
| for k, v := range params { |
| vl.Add(k, v) |
| } |
| } |
| full_url = full_url + "?" + vl.Encode() |
| // fmt.Printf("%v\n", full_url) |
| return client.Get(full_url) |
| } |
| |
| func (w *WebSession) GetTimestamp() string { |
| t := time.Now() |
| return fmt.Sprintf("%04d%02d%02d%02d%02d%02d", t.Year(), t.Month(), t.Day(), |
| t.Hour(), t.Minute(), t.Second()) |
| } |
| |
| func (w *WebSession) SignWithKey(key, message string) string { |
| mac := hmac.New(sha1.New, []byte(key)) |
| mac.Write([]byte(message)) |
| res := mac.Sum(nil) |
| return hex.EncodeToString(res) |
| } |
| func (w *WebSession) Sign(message string) string { |
| return w.SignWithKey(w.Appsecret, message) |
| } |
| |
| func (w *WebSession) NewClient(timeout int) *http.Client { |
| var transport http.Transport |
| if strings.HasPrefix(w.BaseUrl, "https://") { |
| var b bool |
| if w.ssl_verify { |
| b = false |
| } else { |
| b = true |
| } |
| transport = http.Transport{MaxIdleConnsPerHost: 0, DisableKeepAlives: true, |
| TLSClientConfig: &tls.Config{InsecureSkipVerify: b}, |
| TLSHandshakeTimeout: time.Duration(timeout) * time.Second, |
| Dial: func(network, addr string) (net.Conn, error) { |
| default_timeout := time.Duration(1) * time.Second |
| return net.DialTimeout(network, addr, default_timeout) |
| }} |
| } else if strings.HasPrefix(w.BaseUrl, "http://") { |
| transport = http.Transport{MaxIdleConnsPerHost: 0, DisableKeepAlives: true, |
| Dial: func(network, addr string) (net.Conn, error) { |
| default_timeout := time.Duration(1) * time.Second |
| return net.DialTimeout(network, addr, default_timeout) |
| }} |
| } |
| return &http.Client{Transport: &transport, Timeout: time.Duration(timeout) * time.Second} |
| } |
| |
| func (w *WebSession) DoPost(uri string, param map[string]string) (*http.Response, error) { |
| client := w.NewClient(3) |
| param["app_id"] = w.AppId |
| param["term_id"] = w.TermId |
| param["sign_method"] = "HMAC" |
| param["session_key"] = w.session_key |
| ts := w.GetTimestamp() |
| param["timestamp"] = ts |
| param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts) |
| |
| full_url := w.BaseUrl + uri |
| data, err := json.Marshal(param) |
| if err != nil { |
| return nil, err |
| } |
| var r *http.Response |
| r, err = client.Post(full_url, "application/json", bytes.NewReader(data)) |
| if err != nil || r.StatusCode != 200 { |
| log.Errorf("Status=%v, err=%v", r, err) |
| } |
| return r, err |
| } |
| |
| func (w *WebSession) Auth() error { |
| token, err := w.getAuthToken() |
| if err != nil { |
| return err |
| } |
| err = w.getAppAccessKey(token) |
| if err != nil { |
| return err |
| } |
| return nil |
| } |
| |
| func NewSession(appid, appsecret, termid, baseurl string, timeout int, sslVerify bool) *WebSession { |
| return &WebSession{ |
| AppId: appid, |
| Appsecret: appsecret, |
| TermId: termid, |
| BaseUrl: baseurl, |
| DefaultTimeout: timeout, |
| ssl_verify: sslVerify} |
| } |
| |
| func (w *WebSession) getAuthToken() (string, error) { |
| type FormJson struct { |
| AppId string `json:"app_id"` |
| TermId string `json:"term_id"` |
| AccessToken string `json:"access_token"` |
| } |
| |
| uri := fmt.Sprintf("/authservice/getauth/%v/getaccesstoken", w.AppId) |
| |
| params := make(map[string]string) |
| params["term_id"] = w.TermId |
| r, err := w.DoGet(uri, params) |
| |
| if err != nil { |
| // log.Errorf("Status = %v, err = %v\n", r.StatusCode, err) |
| return "", err |
| } |
| if r.StatusCode != 200 { |
| return "", errors.New("请求失败") |
| } |
| |
| body, err := ioutil.ReadAll(r.Body) |
| defer r.Body.Close() |
| |
| s := &FormJson{} |
| err = json.Unmarshal(body, &s) |
| if err != nil { |
| log.Errorf("json unmarshal err %v", err) |
| return "", errors.New("解析失败") |
| } |
| return s.AccessToken, nil |
| } |
| func (w *WebSession) getAppAccessKey(token string) error { |
| type FormJson struct { |
| AppId string `json:"app_id"` |
| TermId string `json:"term_id"` |
| SessionKey string `json:"session_key"` |
| CardKey string `json:"card_key"` |
| } |
| |
| uri := fmt.Sprintf("/authservice/getauth/%v", w.AppId) |
| |
| params := make(map[string]string) |
| params["term_id"] = w.TermId |
| params["access_token"] = token |
| params["timestamp"] = w.GetTimestamp() |
| params["v"] = "1" |
| params["sign"] = w.Sign(token + params["timestamp"]) |
| params["sign_method"] = "HMAC" |
| |
| r, err := w.DoGet(uri, params) |
| if r != nil { |
| defer r.Body.Close() |
| } |
| if err != nil || r.StatusCode != 200 { |
| log.Errorf(" err = %v\n", err) |
| return err |
| } |
| |
| body, err := ioutil.ReadAll(r.Body) |
| |
| s := &FormJson{} |
| err = json.Unmarshal(body, &s) |
| if err != nil { |
| log.Errorf("json unmarshal err %v", err) |
| } |
| w.session_key = s.SessionKey |
| return nil |
| } |
| |
| func (w *WebSession) CallYKTApi(request *MessageWriter) (*MessageReader, error) { |
| call_data := request.Serialize() |
| params := make(map[string]string) |
| params["funcdata"] = call_data |
| r, err := w.DoPost("/ecardservice/ecardapi", params) |
| |
| if r != nil { |
| defer r.Body.Close() |
| } |
| if err != nil { |
| log.Errorf(" err = %v\n", err) |
| return nil, err |
| } |
| |
| if r.StatusCode != 200 { |
| return nil, errors.New(fmt.Sprintf("Request StatusCode:%v", r.StatusCode)) |
| } |
| |
| body, err := ioutil.ReadAll(r.Body) |
| return NewMessageReader(body), nil |
| } |
| |
| func (w *WebSession) CallService(path string, params map[string]interface{}, |
| sign_field []string, timeout int) (response *ServiceResponse, err error) { |
| |
| return w.CallService2(path, params, timeout, sign_field...) |
| } |
| |
| func (w *WebSession) CallService2(path string, params map[string]interface{}, timeout int, |
| sign_field ...string) (response *ServiceResponse, err error) { |
| client := w.NewClient(timeout) |
| err = nil |
| params["app_id"] = w.AppId |
| params["term_id"] = w.TermId |
| ts := w.GetTimestamp() |
| params["timestamp"] = ts |
| |
| vl := &url.Values{} |
| for k, v := range params { |
| vl.Set(k, fmt.Sprintf("%v", v)) |
| } |
| |
| sign_data := "" |
| for _, k := range sign_field { |
| if v, ok := params[k]; ok { |
| sign_data += fmt.Sprintf("%v", v) |
| } |
| } |
| sign_data += ts + w.session_key |
| vl.Set("sign_method", "HMAC") |
| log.Debugf("Sign: key[%v] data[%v]\n", w.session_key, sign_data) |
| vl.Set("sign", w.SignWithKey(w.Appsecret, sign_data)) |
| |
| full_url := w.BaseUrl + path |
| log.Debugf("CallService: %v\n", full_url) |
| var r *http.Response |
| r, err = client.Post(full_url, "application/x-www-form-urlencoded", |
| bytes.NewReader([]byte(vl.Encode()))) |
| if r != nil { |
| defer r.Body.Close() |
| } |
| if err != nil { |
| log.Errorf("Status=%v, err=%v", r, err) |
| return |
| } |
| if r.StatusCode != 200 { |
| log.Errorf("Request Error %v\n", r.StatusCode) |
| err = errors.New(fmt.Sprintf("Request Error, StatusCode : %v", r.StatusCode)) |
| return |
| } |
| body, err := ioutil.ReadAll(r.Body) |
| var s interface{} |
| err = json.Unmarshal(body, &s) |
| if err != nil { |
| log.Errorf("json unmarshal err %v", err) |
| return |
| } |
| response = NewServiceResponseFromJson(s) |
| return |
| } |