feat(实现功能): 使用高德IP定位2.0实现功能

This commit is contained in:
xiaoqidun 2021-10-01 12:44:02 +08:00
parent e35b220ac1
commit 6804ad03c0
3 changed files with 141 additions and 0 deletions

View File

@ -1,2 +1,16 @@
# aipdw
Golang 高德IP定位库
# 在线演示
- [https://aite.xyz/aipdw](https://aite.xyz/aipdw)
# 类似项目
- [https://github.com/xiaoqidun/tipdw](https://github.com/xiaoqidun/tipdw)
# 接口文档
- [https://lbs.amap.com/faq/quota-key/key/41181](https://lbs.amap.com/faq/quota-key/key/41181)
- [https://lbs.amap.com/api/webservice/guide/api/ipconfig](https://lbs.amap.com/api/webservice/guide/api/ipconfig)

85
aipdw.go Normal file
View File

@ -0,0 +1,85 @@
package aipdw
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"sync"
"time"
)
var (
client = &http.Client{Timeout: 5 * time.Second}
ipCache = &sync.Map{}
)
type Body struct {
Status string `json:"status"` // 返回结果状态值值为0或1,0表示失败1表示成功
Info string `json:"info"` // status为0时info返回错误原因否则返回“OK”
Infocode string `json:"infocode"` // 返回状态说明,10000代表正确,详情参阅info状态表
Result
}
type Result struct {
Country string `json:"country"` // 国家
Province string `json:"province"` // 省份
City string `json:"city"` // 城市
District string `json:"district"` // 区县
Isp string `json:"isp"` // 运营商
Location string `json:"location"` // 经纬度
IP string `json:"ip"` // IP地址
}
// QueryIP 使用高德位置服务查询IP
func QueryIP(sk string, key string, ip string) (result Result, err error) {
v, ok := ipCache.Load(ip)
if ok {
result = v.(Result)
return
}
pip := net.ParseIP(ip)
if pip == nil {
err = errors.New("ip is not ipv4 or ipv6")
return
}
ipt := "6"
if pip.To4() != nil {
ipt = "4"
}
arg := &reqLBS{
SK: sk,
Args: map[string]string{
"ip": ip,
"key": key,
"type": ipt,
},
}
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s?%s", "https://restapi.amap.com/v5/ip", arg.Encode()), nil)
if err != nil {
return
}
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
var bodyUnmarshal Body
err = json.Unmarshal(body, &bodyUnmarshal)
if err != nil {
return
}
if bodyUnmarshal.Infocode != "10000" {
err = fmt.Errorf("resp code is %s, body is %s", bodyUnmarshal.Infocode, body)
return
}
result = bodyUnmarshal.Result
ipCache.Store(ip, bodyUnmarshal.Result)
return
}

42
aipdw_util.go Normal file
View File

@ -0,0 +1,42 @@
package aipdw
import (
"crypto/md5"
"encoding/hex"
"fmt"
"net/url"
"sort"
"strings"
)
type reqLBS struct {
SK string
Args map[string]string
}
func (r *reqLBS) Encode() string {
r.Signature()
req := url.Values{}
for k, v := range r.Args {
req.Set(k, v)
}
return req.Encode()
}
func (r *reqLBS) Signature() {
if r.Args == nil {
r.Args = make(map[string]string)
}
var keys []string
for k := range r.Args {
keys = append(keys, k)
}
sort.Strings(keys)
var keyValue []string
for i := 0; i < len(keys); i++ {
keyValue = append(keyValue, fmt.Sprintf("%s=%s", keys[i], r.Args[keys[i]]))
}
signStr := strings.Join(keyValue, "&") + r.SK
signMd5 := md5.Sum([]byte(signStr))
r.Args["sig"] = hex.EncodeToString(signMd5[:])
}