博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
***微信LBS地理位置开发+百度地图API(地理位置和坐标转换)
阅读量:6825 次
发布时间:2019-06-26

本文共 9724 字,大约阅读时间需要 32 分钟。

微信公众平台开发 - 获取用户地理位置

 

本文介绍在微信公众平台上如何使用高级接口开发获取用户地理位置的功能。

一、获取用户地理位置接口

开通了上报地理位置接口的公众号,用户在关注后进入公众号会话时,会弹框让用户确认是否允许公众号使用其地理位置。弹框只在关注后出现一次,用户以后可以在公众号详情页面进行操作。

用户同意上报地理位置后,每次进入公众号会话时,都会在进入时上报地理位置,上报地理位置以推送XML数据包到开发者填写的URL来实现。

推送XML数据包示例:

123456789
23.137466
113.352425
119.385040

参数说明:

参数

描述

ToUserName

开发者微信号

FromUserName

发送方帐号(一个OpenID)

CreateTime

消息创建时间 (整型)

MsgType

消息类型,event

Event

事件类型,LOCATION

Latitude

地理位置纬度

Longitude

地理位置经度

Precision

地理位置精度

 

二、程序接收用户地理位置坐标

地理位置是一个事件消息,在方倍工作室的微信公众平台PHP SDK中,增加位置信息判断,然后获取用户的纬度和经度。

private function receiveEvent($object){    $contentStr = "";    switch ($object->Event)    {        case "subscribe":            $contentStr = "欢迎关注方倍工作室";            break;        case "LOCATION":            $contentStr = "纬度 ".$object->Latitude." 经度".$object->Longitude;            break;        default:            break;    }    $resultStr = $this->transmitText($object, $contentStr);    return $resultStr;}

也可以把位置信息存到数据库,这样方便以后分析。

 


微信公众平台消息接口开发(11)地理位置查询附近商家

 

一、获取用户地址位置消息

用户发送位置时的消息及格式如下

后台格式:

1359036619
22.539968
113.954980
16
5837017832671832047

 XML格式讲解

ToUserName 消息接收方微信号,一般为公众平台账号微信号 FromUserName 消息发送方微信号 CreateTime 消息创建时间 MsgType 消息类型,地理位置为location Location_X 地理位置纬度 Location_Y 地理位置经度 Scale 地图缩放大小 Label 地理位置信息 MsgId 消息ID号

 

二、获取周边区域信息

百度地图Place API 是一类简单的HTTP接口,用于返回查询某个区域的某类POI数据,且提供单个POI的详情查询服务,用户可以使用C#、C++、Java等开发语言发送HTTP请求且接收json、xml的数据。

Place API 提供区域检索POI服务、POI详情服务与团购信息检索服务、商家团购详情查询。区域检索POI服务提供三种区域检索方法:城市内检索、矩形检索、圆形区域检索。

我们使用圆形区域检索来实现附近搜索功能。

place区域检索POI服务接口如下:

http://api.map.baidu.com/place/v2/search

参数

是否必须

默认值

格式举例

含义

location

38.76623,116.43213 

lat<纬度>,lng<经度>

周边检索中心点,不支持多个点

radius(r)

2000

周边检索半径,单位为米

q(query)

中关村、ATM、百度大厦

检索关键字,周边检索和矩形区域内检索支持多个关键字并集检索,不同关键字间以$符号分隔,最多支持10个关键字检索。如:”银行$酒店”。

tag

日式烧烤/铁板烧、朝外大街

标签项,与q组合进行检索

output

xml

json或xml

输出格式为json或者xml

scope

1

1、2

检索结果详细程度。取值为1 或空,则返回基本信息;取值为2,返回检索POI详细信息

filter

filter=industry_type:cater

|sort_name:price
|sort_rule:0
|price_section:100,200
|groupon:0
|discount:0

检索过滤条件,当scope取值为2时,可以设置filter进行排序。

industry_type:行业类型
sort_name:排序字段
sort_rule:排序规则,取值如下:0:从高到低,1:从低到高;
price_section:价格区间;
groupon:是否有团购,1为有团购,0为无团购;
discount:是否打折,1为有打折,0为无打折;

page_size

10

10

范围记录数量,默认为10条记录,最大返回20条。多关键字检索时,返回的记录数为关键字个数*page_size。

page_num

0

0、1、2

分页页码,默认为0,0代表第一页,1代表第二页,以此类推。

ak

E4805d16520de693a3fe707cdc962045

用户的访问密钥,必填项。v2之前该属性为key。

sn

 

用户的权限签名。

timestamp

 

设置sn后该值必填。

调用举例如下:

http://api.map.baidu.com/place/v2/search?ak=MgBALVVeCd8THVBi6gPdvsvG&output=json&query=%E9%93%B6%E8%A1%8C&page_size=5&page_num=0&scope=2&location=39.915,116.404&radius=2000&filter=sort_name:distance

 

三、程序实现

百度地图类定义如下

class baiduMapClient{        private $api_server_url;    private $auth_params;    public function __construct()    {        $this->api_server_url = "http://api.map.baidu.com/";        $this->auth_params = array();           $this->auth_params['key'] = "401f9a693dd267dd9a4661ec0895fb20";        $this->auth_params['output'] = "json";    }    public function Geocoding_coordinate_address($location)     {           return $this->call("geocoder", array("location" => $location));    }        //http://api.map.baidu.com/place/search?&query=眼镜&location=39.915,116.404&radius=3000&output=json&key=37492c0ee6f924cb5e934fa08c6b1676    public function Place_search($query, $location, $radius)     {        return $this->call("place/search", array("query" => $query, "location" => $location, "radius" => $radius));    }        protected function call($method, $params = array())    {        $headers = array(            "User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:14.0) Gecko/20100101 Firefox/14.0.1",            "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",            "Accept-Language: en-us,en;q=0.5",            //"Accept-Encoding: gzip, deflate",            "Referer: http://developer.baidu.com/"        );        $params = array_merge($this->auth_params, $params);        $url = $this->api_server_url . "$method?".http_build_query($params);        if (DEBUG_MODE){echo "REQUEST: $url" . "\n";}        $ch = curl_init();        curl_setopt($ch, CURLOPT_URL, $url);        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);        //curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);          $data = curl_exec($ch);        curl_close($ch);            $result = null;        if (!empty($data)){            if (DEBUG_MODE){                echo "RETURN: " . $data . "\n";            }            $result = json_decode($data);        }        else{            echo "cURL Error:". curl_error($ch);        }        return $result;    }}

获取附近的调用代码如下:

function catchEntitiesFromLocation($entity, $x, $y, $radius){       $mapObj = new baiduMapClient();    $search = $mapObj->Place_search($entity, $x.",".$y, $radius);    $results = $search->results;    for ($i = 0; $i < count($results); $i++) {        $distance = getDistance($x, $y, $results[$i]->location->lat, $results[$i]->location->lng);        $shopSortArrays[$distance] = array(            "Title"=>"【".$results[$i]->name."】<".$distance."M>".$results[$i]->address.(isset($results[$i]->telephone)?" ".$results[$i]->telephone:""),            "Description"=>"",             "PicUrl"=>"",             "Url"=>"");    }    ksort($shopSortArrays);//排序    $shopArray = array();     foreach ($shopSortArrays as $key => $value) {          $shopArray[] =  array(                        "title" => $value["Title"],                        "description" => $value["Description"],                        "pic" => $value["PicUrl"],                        "url" => $value["Url"],                    );        if (count($shopArray) > 6){break;}    }    return $shopArray;}

计算两坐标之间距离如下

function getDistance($lat_a, $lng_a, $lat_b, $lng_b) {    //R是地球半径(米)    $R = 6366000;    $pk = doubleval(180 / 3.14169);        $a1 = doubleval($lat_a / $pk);    $a2 = doubleval($lng_a / $pk);    $b1 = doubleval($lat_b / $pk);    $b2 = doubleval($lng_b / $pk);    $t1 = doubleval(cos($a1) * cos($a2) * cos($b1) * cos($b2));    $t2 = doubleval(cos($a1) * sin($a2) * cos($b1) * sin($b2));    $t3 = doubleval(sin($a1) * sin($b1));    $tt = doubleval(acos($t1 + $t2 + $t3));    return round($R * $tt);}

对于用户的坐标记录,我们使用数据库的方式来存储,

 

如果用户发送查询命令,则直接查询,

function searchUserLocation($userWxid){    Global $mysql_host;    Global $mysql_host_s;    Global $mysql_port;    Global $mysql_user;    Global $mysql_password;    Global $mysql_database;        //查询使用从库,支持SAE    $mysql_table = "location";    $mysql_state = "SELECT * FROM ".$mysql_table." WHERE userWxid = \"".$userWxid."\"";    $con = mysql_connect($mysql_host.':'.$mysql_port, $mysql_user, $mysql_password);    if (!$con){        die('Could not connect: ' . mysql_error());    }    mysql_query("SET NAMES 'UTF8'");    mysql_select_db($mysql_database, $con);    $result = mysql_query($mysql_state);    $location = array();     while($row = mysql_fetch_array($result))    {        $location["x"] = $row["locationX"];         $location["y"] = $row["locationY"];     }    mysql_close($con);    if (isset($location["x"]) && $location["x"] != 0.0){        return $location;    }else{        return "系统中没有你的地理位置信息,请先发送位置给我!您不用担心你的行踪被泄漏,因为你可以滑动地图,把别处的地址发送过来。";    }    }

如果用户发了位置,则进行更新

function updateOrInsert($weixinid, $locationX, $locationY){        if (isset($_SERVER['HTTP_APPNAME'])){        $mysql_host = SAE_MYSQL_HOST_M;        $mysql_host_s = SAE_MYSQL_HOST_S;  //sae的从库        $mysql_port = SAE_MYSQL_PORT;        $mysql_user = SAE_MYSQL_USER;        $mysql_password = SAE_MYSQL_PASS;        $mysql_database = SAE_MYSQL_DB;    }else{        $mysql_host = "127.0.0.1";        $mysql_host_s = "127.0.0.1";        $mysql_port = "3306";        $mysql_user = "root";        $mysql_password = "root";        $mysql_database = "sae";    }        $mysql_table = "location";    //INSERT INTO location VALUES("23s2s", 1122.2, 366.2) ON DUPLICATE KEY UPDATE locationX = 1122.2, locationY = 366.2;        $mysql_state = "INSERT INTO ".$mysql_table." VALUES(\"".$weixinid."\", ".$locationX.", ".$locationY.") ON DUPLICATE KEY UPDATE locationX = ".$locationX.", locationY = ".$locationY.";";    var_dump($mysql_state);    //        $con = mysql_connect($mysql_host.':'.$mysql_port, $mysql_user, $mysql_password);    if (!$con){        die('Could not connect: ' . mysql_error());    }    mysql_query("SET NAMES 'UTF8'");    mysql_select_db($mysql_database, $con);    $result = mysql_query($mysql_state);    if ($result == true){        //return "你提交的位置为纬度:".$locationX.",经度:".$locationY."。\n现在可以发送“附近”加关键字的命令查询附近的目标,如“附近酒店”,“附近医院”。";        return "已经成功获取你的位置。您不用担心你的行踪被泄漏,因为你可以把千里之外的地址提交过来。\n现在可以发送“附近”加关键字的命令查询附近的目标,如“附近酒店”,“附近医院”。";    }else{        return "提交失败,请重试。如果一直出现这样的错误,请给我们留言。";    }}

对于用户发送的内容,先提取坐标,然后进行组合查询

实现效果如下:

 

 


 

1.由地名(省份、城市、街道等)得到其对应的百度地图坐标:

http://api.map.baidu.com/geocoder/v2/?output=json&ak=你从百度申请到的Key&address=北京市

其对大陆主要城市的解析很好,但是有些大陆的小城市、香港、台湾的一些区域无法解析,我测试到的如下:

解析错误的城市:伊犁|新界|新竹|港岛|基隆|云林|博尔塔拉|桃园|苗栗|南投|克孜勒苏|台东|

 伊犁可以使用新疆伊犁来解析,更好的办法是使用谷歌地图API,比如这样使用:

http://maps.google.com/maps/api/geocode/json?sensor=false&address=地址

 在谷歌地图中,港岛可以使用:

Hong Kong Island

来解析,

云林可以使用:

Yunlin County, Taiwan

来解析,

博尔塔拉可以使用博尔塔拉蒙古自治州来解析,

2.由坐标反解得到对应的地址:

 http://api.map.baidu.com/geocoder/v2/?output=json&ak=你从百度申请到的Key&location=纬度(Latitude),经度(Longitude)

 

注意,纬度和经度之间有个英文逗号。

具体参考:

转载地址:http://jgezl.baihongyu.com/

你可能感兴趣的文章
From 192.168.25.133 icmp_seq=238 Destination Host Unreachable 虚拟机ping主机不通
查看>>
上交所回应“科创板受理企业科技含量不高”:会在审核问询环节对企业进行多轮问询...
查看>>
教你如何用python操作数据库mysql ! !
查看>>
全栈必备 Log日志
查看>>
阿里云服务器企业该如何选择
查看>>
Nginx性能优化
查看>>
SQL与NoSQL数据库入门基础知识详解
查看>>
Redis命令——键(key)
查看>>
[Server] 服务器配置SSH登录邮件通知
查看>>
ceph 添加新硬盘删除旧的OSD
查看>>
Kubernetes 的安全机制 APIServer 认证、授权、准入控制
查看>>
杨老师课堂之Nginx学习之反向代理
查看>>
阿里云GPU云服务器
查看>>
自定义Dialog之旅程(二)理解Dialog大小
查看>>
最伟大的程序员高德纳: 谈计算机程序设计艺术
查看>>
利用Xamaria构建Android应用-公交发车信息屏
查看>>
Android自定义注解(一)
查看>>
Java并发编程-AQS
查看>>
修复网站漏洞对phpmyadmin防止被入侵提权的解决办法
查看>>
Android Studio 中无法下载com.android.tools.build:gradle:3.0.1
查看>>