package utils import ( "encoding/json" "fmt" "io" "io/ioutil" "net/http" "net/url" "strings" "time" ) const baiduIPLocationAPI = "https://api.map.baidu.com/location/ip" // 建议把 ak 放配置;这里先保留你给的 key,后续可改为从配置读取。 const baiduMapAK = "T8DGBYxbZ1iAeXx1J57McKigyHJHulPQ" type baiduIPResp struct { Status int `json:"status"` Address string `json:"address"` Content struct { Address string `json:"address"` } `json:"content"` Message string `json:"message"` } type ReverseGeocodingReq struct { Ak string `json:"ak"` Coordtype string `json:"coordtype"` RetCoordtype string `json:"retCoordtype"` Location string `json:"location"` Output string `json:"output"` Language string `json:"language"` } type ReverseGeocodingRes struct { Status int `json:"status"` Result struct { Location struct { Lng float64 `json:"lng"` Lat float64 `json:"lat"` } `json:"location"` FormattedAddress string `json:"formatted_address"` Edz struct { Name string `json:"name"` } `json:"edz"` Business string `json:"business"` AddressComponent struct { Country string `json:"country"` CountryCodeIso string `json:"country_code_iso"` CountryCodeIso2 string `json:"country_code_iso2"` CountryCode int `json:"country_code"` Province string `json:"province"` City string `json:"city"` CityLevel int `json:"city_level"` District string `json:"district"` Town string `json:"town"` TownCode string `json:"town_code"` Distance string `json:"distance"` Direction string `json:"direction"` Adcode string `json:"adcode"` Street string `json:"street"` StreetNumber string `json:"street_number"` } `json:"addressComponent"` } `json:"result"` } // ReverseGeo 经纬度逆编码 func ReverseGeo(longitude, latitude string, language string) (address string, err error) { var reverseGeocodingReq ReverseGeocodingReq reverseGeocodingReq.Ak = "3bAjKGA0pv7qvszGe98RsVZ04Ob5r4ZZ" reverseGeocodingReq.Coordtype = "gcj02ll" reverseGeocodingReq.Output = "json" reverseGeocodingReq.RetCoordtype = "gcj02ll" reverseGeocodingReq.Location = strings.Join([]string{latitude, longitude}, ",") reverseGeocodingReq.Language = language url := "https://api.map.baidu.com/reverse_geocoding/v3/?ak=" + reverseGeocodingReq.Ak + "&output=" + reverseGeocodingReq.Output + "&coordtype=" + reverseGeocodingReq.Coordtype + "&location=" + reverseGeocodingReq.Location + "&ret_coordtype=" + reverseGeocodingReq.RetCoordtype + "&language=" + reverseGeocodingReq.Language resp, err := http.Get(url) if err != nil { return "", err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } var results ReverseGeocodingRes err = json.Unmarshal(body, &results) if err != nil { return "", err } if results.Status != 0 { address = "未知地址" return address, err } address = results.Result.FormattedAddress return address, nil } func GetAddressByIP(ip string) (string, error) { ip = strings.TrimSpace(ip) if ip == "" { return "", fmt.Errorf("ip is empty") } q := url.Values{} q.Set("ip", ip) q.Set("coor", "bd09ll") q.Set("ak", baiduMapAK) reqURL := baiduIPLocationAPI + "?" + q.Encode() client := &http.Client{Timeout: 5 * time.Second} resp, err := client.Get(reqURL) if err != nil { return "", err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("baidu api status: %d", resp.StatusCode) } body, err := io.ReadAll(resp.Body) if err != nil { return "", err } var r baiduIPResp if err := json.Unmarshal(body, &r); err != nil { return "", err } if r.Status != 0 { if r.Message == "" { r.Message = "baidu api error" } return "", fmt.Errorf("%s", r.Message) } if strings.TrimSpace(r.Content.Address) != "" { return r.Content.Address, nil } if strings.TrimSpace(r.Address) != "" { return r.Address, nil } return "", nil }