使用百度地图接口和公众平台地理位置接口实现附近搜索
一、使用百度地图接口和公众平台地理位置接口实现附近搜索
1.截图
2.前期准备工作
1.前往此链接获取AK,http://lbsyun.baidu.com/index.php?title=webapi
需要有百度账号,没有就注册
地点检索下拉菜单有开发文档可以查看
2.前往新浪云SAE开启Memcache
3.检测使用自己的ak能不能获取附近位置信息,能则OK
4.公众号功能则还需要一步,前往测试号开启
http://api.map.baidu.com/place/v2/search?ak=你的AK&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
3.代码实现
1》实现思路:
1.首先实现在缓存中保存用户地理位置功能(不用每次让用户上传地理位置)
2.其次实现从缓存中读取用户地理位置信息功能
3.然后通过百度地图接口实现搜索附近信息的功能(解析用户地理位置)
4.最后实现公众号接收地理位置消息处理功能(业务逻辑调用相应接口实现)
根据以上思路:我们新建文件夹baiduMapSearch,包含3个文件,分别为:location.php、mapbaidu.php、index.php
location.php:实现功能1和2
mapbaidu.php:实现功能3
index.php:实现功能4
2》代码【均简化功能,仅是实现此标题的功能】
fun.php,前几篇有,懒得再般过来了。
(1)【location.php】
<?php
//1.缓存用户位置
function setLocation($OpenID, $locationX, $locationY)
{
$memcache = memcache_init();
if ($memcache == true) {
$location = array("locationX" => $locationX, "locationY" => $locationY);
memcache_set($memcache, $OpenID, json_encode($location), 60);
return $OpenID . "+" . $locationX . "+" . $locationY .
"您的位置已经缓存好。\n现在可以发送“附近”加目标的命令给我,如“附近酒店”,“附近银行”等。";
} else {
return "未启用缓存,请先开启服务器的缓存功能1";
}
}
//2.从缓存中读取用户地理位置,3.返回位置信息
function getLocation($OpenID)
{
if (!empty($OpenID)) {
$memcache = memcache_init();
if ($memcache == true) {
$location = memcache_get($memcache, $OpenID);
if (!empty($location)) {
return json_decode($location, true);
} else {
return "请先发送位置给我!点击底部‘+’号,再选择‘位置’,等地图显示出来以后,点击‘发送’";
}
} else {
return "未启用缓存,请先开启服务器的缓存功能2";
}
} else {
return "openid是空kkkk";
}
}
(2)【mapbaidu.php】
<?php
require_once "FUN.php";
define("MEBUG_MODE", false);
function MapLocation($Entity, $X, $Y, $Radius, $AK)
{
if (!empty($X) || !empty($Y)) {
$url = "http://api.map.baidu.com/place/v2/search?ak=" .
$AK . "&output=json&query=" . $Entity . "&page_size=5&page_num=0&scope=2&location=" .
$X . "," . $Y . "&radius=" . $Radius . "&filter=sort_name:distance";
$output = https_request($url);
$data = json_decode($output, true);
if ($data['status'] != 0) {
return $url . "附近没有找到111" . $data['message'];
}
$results = $data['results'];
if (count($results) == 0) {
return $url . "附近没有找到222" . $Entity;
}
$shopArray = array();
for ($i = 0; $i < count($results); $i++) {
$shopArray[] = array(
"Title" =>
"【" . $results[$i]['name'] . "】<" . $results[$i]['detail_info']['distance'] ."米>\n" .
$results[$i]['address'] . (isset($results[$i]['telephone']) ? "\n" . $results[$i]['telephone'] : ""),
"Description" => "",
"Pic" => "",
"Url" =>
(isset($results[$i]['detail_info']['detail_url']) ? ($results[$i]['detail_info']['detail_url']) : ""));
}
} else {
return "XXXX是空YYYY是空" . $Entity . "+" . $X . "+" . $Y . "+" . $Radius . "+" . $AK;
}
return $shopArray;
}
(3)【index.php】
<?php
//error_reporting(0);
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
if (!isset($_GET['echostr'])) {
$wechatObj->responseMsg();
} else {
$wechatObj->valid();
}
class wechatCallbackapiTest
{
//验证接口的函数,用于申请成为开发者时向微信发送验证信息
public function valid()
{
$echoStr = $_GET["echostr"];
if ($this->checkSignature()) {
echo $echoStr;
exit;
}
}
//校验函数,校验对接身份函数,签名验证程序
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
//响应消息函数
public function responseMsg()
{
//$postStr为用户在微信公众平台发的信息
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
if (!empty($postStr)) {
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);//判断平台接受的消息类型
//用户发送的消息类型判断
switch ($RX_TYPE) {
case "event": //事件消息
$resultStr = $this->receiveEvent($postObj);
break;
case "text": //文本消息
$resultStr = $this->receiveText($postObj);
break;
case "location"://位置消息
$resultStr = $this->receiveLocation($postObj);
break;
default:
$resultStr = "unknow msg type: " . $RX_TYPE;
break;
}
echo $resultStr;
} else {
echo "???";
exit;
}
}
//7.事件处理
private function receiveEvent($object)
{
$MsgEvent = trim($object->Event);//判断事件类型
if ($MsgEvent == "LOCATION") {
require_once "location.php";
$contentStr = setLocation($object->FromUserName, (string)$object->Latitude, (string)$object->Longitude);
// $contentStr = setLocation($object->FromUserName, (string)$object->Location_X, (string)$object->Location_Y);
$resultStr = $this->transmitText($object, $contentStr);
return $resultStr;
}
}
//1.接收文本消息
private function receiveText($object)
{
$keyword = $object->Content;
if ($keyword == "附近") {
$contentStr = "请先发送位置给我!点击底部‘+’号,再选择‘位置’,等地图显示出来以后,点击‘发送’";
$resultStr = $this->transmitText($object, $contentStr);
return $resultStr;
} elseif (substr($keyword, 0, 6) == "附近") {
require_once "location.php";
$Entity = trim(substr($keyword, 6, strlen($keyword)));
$AK = "替换你的AK值";
$location = getLocation($object->FromUserName);
if (is_array($location)) {
require_once "mapbaidu.php";
$contentStr = MapLocation($Entity, $location["locationX"], $location["locationY"], "5000", $AK);
} else {
$contentStr = $location;
}
if (is_array($contentStr)) {
$resultStr = $this->transmitNews($object, $contentStr);
} else {
$resultStr = $this->transmitText($object, $contentStr);
}
return $resultStr;
}
}
//5.接收位置消息
private function receiveLocation($object)
{
require_once "location.php";
$contentStr = setLocation($object->FromUserName, (string)$object->Location_X, (string)$object->Location_Y);
$resultStr = $this->transmitText($object, $contentStr);
return $resultStr;
}
//1.回复文本消息
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$resultStr = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(), $content);
return $resultStr;
}
//2.回复图文消息
private function transmitNews($object, $arr_item)
{
if (!is_array($arr_item))
return;
$itemTpl = " <item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
";
$item_str = "";
foreach ($arr_item as $item)
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
$newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str
</Articles>
</xml>";
$resultStr = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(), count($arr_item));
return $resultStr;
}
}
?>
4.思路【卡点】
5.遇到的问题
有个bug没解决,不清楚怎么回事:
用户取消关注再关注,然后发送“附近”,会返回附近没有找到;但发送“附近酒店”,则会返回取消关注前给用户下发的信息。
**“http://api.map.baidu.com/place/v2/search?ak=” . $AK . “&output=json&query=” . $Entity . “&page_size=5&page_num=0&scope=2&location=” . $X . “,” . $Y . “&radius=” . $Radius . “&filter=sort_name:distance”**链接何处来,,,,不知道。
附:
百度地图API:http://lbsyun.baidu.com/index.php?title=首页
【在开发文档-web服务API】
微信开放文档:
1、【消息管理-接收普通消息】https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
2、【消息管理-接收信息推送】
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html
微信调试器:http://www.fangbei.org/tool/message