package services import ( "bytes" "crypto/md5" "encoding/json" "errors" "eta/eta_task/utils" "fmt" "github.com/shopspring/decimal" "io/ioutil" "net/http" "reflect" "sort" "strings" "time" ) func HttpPost(funcName, method string, postDataMap map[string]interface{}) (result string, err error) { defer func() { if err != nil { fmt.Println("Sync hz crawler err:" + err.Error()) utils.FileLog.Info("Sync hz crawler err:" + err.Error()) } }() bytesData, err := handlePostData(postDataMap) if err != nil { fmt.Println("handlePostData Err:" + err.Error()) return } fmt.Println("URL:" + utils.HzDataApi + method) fmt.Println("Params:" + string(bytesData)) client := &http.Client{} req, err := http.NewRequest("POST", utils.HzDataApi+method, bytes.NewReader(bytesData)) if err != nil { fmt.Println("http.NewRequest Err:" + err.Error()) return "", err } req.Header.Set("content-type", "application/json") utils.FileLog.Info(fmt.Sprintf("请求函数:%s ;请求地址:%s;请求体:%s", funcName, utils.HzDataApi+method, string(bytesData))) resp, err := client.Do(req) if err != nil { return "", err } if resp.Body != nil { body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } result = string(body) fmt.Println("HttpPost Result:" + string(body)) } utils.FileLog.Info(fmt.Sprintf("请求函数:%s ;返回体:%s", funcName, result)) return } // handlePostData 处理post请求数据 func handlePostData(postDataMap map[string]interface{}) (bytesData []byte, err error) { postDataMap["nonce_str"] = utils.GetRandString(16) // 随机字符串 postDataMap["timestamp"] = time.Now().Unix() //当前格林威治时间,int64类型 postDataMap["appid"] = utils.APPID //当前格林威治时间,int64类型 // 待签名数据 signData := convertParamInterface(postDataMap) sign, err := getSignData(signData) if err != nil { return } postDataMap["sign"] = sign //签名 bytesData, err = json.Marshal(postDataMap) return } // 将请求传入的数据格式转换成签名需要的格式(目前只能处理简单的类型,数组、对象暂不支持) func convertParamInterface(params map[string]interface{}) (signData map[string]string) { signData = make(map[string]string) for key := range params { val := `` //fmt.Println("key", key, ";val:", params[key], ";type:", reflect.TypeOf(params[key])) //signData[key] = params[key][0] tmpVal := params[key] switch reflect.TypeOf(tmpVal).Kind() { case reflect.String: val = fmt.Sprint(tmpVal) case reflect.Int, reflect.Int16, reflect.Int64, reflect.Int32, reflect.Int8: val = fmt.Sprint(tmpVal) case reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint64: val = fmt.Sprint(tmpVal) case reflect.Bool: val = fmt.Sprint(tmpVal) case reflect.Float64: decimalNum := decimal.NewFromFloat(tmpVal.(float64)) val = decimalNum.String() //val = strconv.FormatFloat(tmpVal.(float64), 'E', -1, 64) //float64 case reflect.Float32: decimalNum := decimal.NewFromFloat32(tmpVal.(float32)) val = decimalNum.String() } signData[key] = val } return signData } // getSignData 获取参数签名 func getSignData(postData map[string]string) (sign string, err error) { appid := utils.APPID if appid == "" { err = errors.New("参数异常,缺少appid") return } secret := utils.SECRET if secret == "" { err = errors.New("参数异常,缺少secret") return } if postData["nonce_str"] == "" { err = errors.New("参数异常,缺少随机字符串") return } if postData["timestamp"] == "" { err = errors.New("参数异常,缺少时间戳") return } //先取出除sign外的所有的提交的参数key var keys []string for k := range postData { if k != "sign" { keys = append(keys, k) } } //1,根据参数名称的ASCII码表的顺序排序 sort.Strings(keys) //2 根据排序后的参数名称,取出对应的值,并拼接字符串 var signStr string for _, v := range keys { signStr += v + "=" + postData[v] + "&" } //3,全转小写(md5(拼装的字符串后+分配给你的app_secret)) //sign := strings.ToLower(fmt.Sprintf("%x", md5.Sum([]byte(strings.Trim(signStr, "&")+key)))) //md5.Sum([]byte(signStr+"key="+key)) 这是md5加密出来后的每个字符的ascall码,需要再转换成对应的字符 //3,全转大写(md5(拼装的字符串后+分配给你的app_secret)) sign = strings.ToUpper(fmt.Sprintf("%x", md5.Sum([]byte(signStr+"secret="+secret)))) return }