Files
baseapi/platformapi/baidunavi/baidunavi.go
邹宗楠 2ed93fe209 1
2022-10-22 22:45:36 +08:00

168 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package baidunavi
import (
"crypto/md5"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
)
const (
signKey = "sn"
resultKey = "result"
prodURL = "http://api.map.baidu.com"
)
const (
StatusCodeSuccess = 0
StatusCodeInternalErr = 1 // 服务器内部错误
StatusCodeExceedDailyQuota = 301 // 永久配额超限,限制访问
StatusCodeExceedQuota = 302 // 天配额超限,限制访问
StatusCodeExceedDailyConcurrentQuota = 401 // 当前并发量已经超过约定并发配额,限制访问
StatusCodeExceedConcurrentQuota = 402 // 当前并发量已经超过约定并发配额,并且服务总并发量也已经超过设定的总并发配额,限制访问
)
const (
CoordSysWGS84 = 1 // GPS设备获取的角度坐标WGS84坐标
CoordSysGCJ02 = 3 // google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标国测局GCJ02坐标
CoordSysBaiDu = 5 // 百度地图采用的经纬度坐标
)
const (
MaxCoordsConvBatchSize = 100
)
var (
exceedLimitCodes = map[int]int{
StatusCodeExceedDailyQuota: 1,
StatusCodeExceedQuota: 1,
StatusCodeExceedDailyConcurrentQuota: 1,
StatusCodeExceedConcurrentQuota: 1,
}
canRetryCodes = map[int]int{
StatusCodeInternalErr: 1,
}
)
type Coordinate struct {
Lng float64 `json:"x"`
Lat float64 `json:"y"`
}
type API struct {
client *http.Client
config *platformapi.APIConfig
ak string
sk string
}
func New(ak, sk string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
ak: ak,
sk: sk,
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
}
func (a *API) signParams(apiStr string, mapData map[string]interface{}) string {
keys := make([]string, 0)
for k := range mapData {
if k != signKey {
keys = append(keys, k)
}
}
sort.Strings(keys)
strList := []string{}
for _, k := range keys {
strList = append(strList, k+"="+url.QueryEscape(fmt.Sprint(mapData[k])))
}
finalStr := "/" + apiStr + "?" + strings.Join(strList, "&") + a.sk
finalStr = url.QueryEscape(finalStr)
return fmt.Sprintf("%x", md5.Sum([]byte(finalStr)))
}
func genGetURL(baseURL, apiStr string, params map[string]interface{}) string {
keys := make([]string, 0)
for k := range params {
if k != signKey {
keys = append(keys, k)
}
}
sort.Strings(keys)
strList := []string{}
for _, k := range keys {
strList = append(strList, k+"="+url.QueryEscape(fmt.Sprint(params[k])))
}
strList = append(strList, signKey+"="+url.QueryEscape(fmt.Sprint(params[signKey])))
queryString := "?" + strings.Join(strList, "&")
if apiStr != "" {
return baseURL + "/" + apiStr + queryString
}
return baseURL + queryString
}
func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal interface{}, err error) {
apiStr += "/"
params2 := utils.MergeMaps(utils.Params2Map("ak", a.ak, "output", "json"), params)
params2[signKey] = a.signParams(apiStr, params2)
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodGet, genGetURL(prodURL, apiStr, params2), nil)
return request
},
a.config,
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
if jsonResult1 == nil {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
}
status := int(utils.MustInterface2Int64(jsonResult1["status"]))
if status == StatusCodeSuccess {
retVal = jsonResult1[resultKey]
return platformapi.ErrLevelSuccess, nil
}
newErr := utils.NewErrorIntCode(utils.Interface2String(jsonResult1["message"]), status)
if _, ok := exceedLimitCodes[status]; ok {
return platformapi.ErrLevelExceedLimit, newErr
} else if _, ok := canRetryCodes[status]; ok {
return platformapi.ErrLevelRecoverableErr, newErr
} else {
return platformapi.ErrLevelCodeIsNotOK, newErr
}
})
return retVal, err
}
func (a *API) BatchCoordinateConvert(coords []*Coordinate, fromCoordSys, toCoordSys int) (outCoords []*Coordinate, err error) {
if fromCoordSys == toCoordSys {
return coords, nil
}
var coordsStrList []string
for _, v := range coords {
coordsStrList = append(coordsStrList, fmt.Sprintf("%.6f,%.6f", v.Lng, v.Lat))
}
params := map[string]interface{}{
"coords": strings.Join(coordsStrList, ";"),
"from": fromCoordSys,
"to": toCoordSys,
}
result, err := a.AccessAPI("geoconv/v1", params)
if err == nil {
err = utils.Map2StructByJson(result, &outCoords, false)
}
return outCoords, err
}