调试通过webservice接口
diff --git a/webservice.go b/webservice.go
index 732f8be..067b172 100644
--- a/webservice.go
+++ b/webservice.go
@@ -13,6 +13,7 @@
 	"net"
 	"net/http"
 	"net/url"
+	"strconv"
 	"time"
 )
 
@@ -31,6 +32,59 @@
 	session_key    string
 }
 
+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) {
 	transport := http.Transport{Dial: dailTimeout}
 
@@ -46,6 +100,7 @@
 		}
 	}
 	full_url = full_url + "?" + vl.Encode()
+	//	fmt.Printf("%v\n", full_url)
 	return client.Get(full_url)
 }
 
@@ -55,18 +110,29 @@
 		t.Hour(), t.Minute(), t.Second())
 }
 
-func (w *WebSession) Sign(message string) string {
-	mac := hmac.New(sha1.New, []byte(w.Appsecret))
+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 {
+	transport := http.Transport{Dial: func(network, addr string) (net.Conn, error) {
+		default_timeout := time.Duration(timeout) * time.Second
+		return net.DialTimeout(network, addr, default_timeout)
+	}}
+
+	return &http.Client{Transport: &transport}
+}
 func (w *WebSession) DoPost(uri string, param map[string]string) (*http.Response, error) {
 	transport := http.Transport{Dial: dailTimeout}
 	client := &http.Client{Transport: &transport}
 	param["app_id"] = w.AppId
-	param["term_id"] = w.TermId
+	//	param["term_id"] = w.TermId
 	param["sign_method"] = "HMAC"
 	param["session_key"] = w.session_key
 	ts := w.GetTimestamp()
@@ -74,7 +140,7 @@
 	param["sign"] = w.Sign(w.AppId + w.TermId + w.session_key + ts)
 
 	full_url := w.BaseUrl + uri
-	log.Debugf("Url=%v", full_url)
+	//	log.Debugf("Url=%v", full_url)
 	data, err := json.Marshal(param)
 	if err != nil {
 		return nil, err
@@ -181,12 +247,73 @@
 	params["funcdata"] = call_data
 	r, err := w.DoPost("/ecardservice/ecardapi", params)
 
-	if err != nil || r.StatusCode != 200 {
+	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)
 	r.Body.Close()
 	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 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)
+	r.Body.Close()
+	var s interface{}
+	err = json.Unmarshal(body, &s)
+	if err != nil {
+		log.Errorf("json unmarshal err %v", err)
+		return
+	}
+	response = NewServiceResponseFromJson(s)
+	return
+}