• 0
  • 0

基于网页定位模块的解决方案

2021-08-27 603 0 admin 所属分类:PHP 记录

微信浏览器


① 公众号获取定位权限之后,需要在后台 【设置与开发】 - 【公众号设置】 - 【功能设置】 JS接口安全域名 补上你打开授权网页的域名,否则会导致初始化失败

② 前端调用接口往后台取授权票据 ticket  需要传入当前请求地址的链接 包括参数 可以调用 window.location.href 传入 否则会导致签名失败

前端代码

if (window && window.top==window.self) {
   // 必须保证是顶层框架调用wx jsdk 否则会导致调用失败
   $.get('/config',{'url':location.href},function(res){
      if (res.status==1) {
         wx.config({
           debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
           appId: res.data.appId, // 必填,公众号的唯一标识
           timestamp: res.data.timestamp, // 必填,生成签名的时间戳
           nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
           signature: res.data.signature,// 必填,签名
           jsApiList: ['getLocation'] // 必填,需要使用的JS接口列表
         });
         wx.ready(function(){
              wx.getLocation({
               type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
               success: function (res) {
                  var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
                  var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
                  var speed = res.speed; // 速度,以米/每秒计
                  var accuracy = res.accuracy; // 位置精度
                  var location = longitude+','+latitude;
                  getLocationByPos(location);
               }, fail:function(res){
                  getLocationByIp();
               }
              });
         });
      }
   })
} else {
   getLocationByIp();
}

普通浏览器

var geolocation ;
setTimeout(function(){
   geolocation = new qq.maps.Geolocation("{$config['qq_map_key']}", "myapp");
   geolocation.watchPosition(showPosition,showError);
});

成功 失败的回调实现

function showPosition(pos) {
   console.log(pos);
   position = pos;
   geolocation.clearWatch();
   //开始定位
   if(pos.type=='ip'){
      var latitude = pos.lat; // 纬度,浮点数,范围为90 ~ -90
      var longitude = pos.lng; // 经度,浮点数,范围为180 ~ -180。
      var location = longitude+','+latitude;
      //IP模拟不处理
      getLocationByPos(location);
      return false;
   }
   var addr = pos.addr||'';
   addr = addr.replace(/\(/g,' ');
   addr = addr.replace(/\)/g,'');
   getLocation(
      pos.province,
      pos.city,
      pos.district,
      addr
   );
}
function showError(error) {
   console.log('showError')
   console.log(error)
   console.log(JSON.stringify(error))
}

前端通用函数

function getLocationByPos(location) {
   $.get('https://restapi.amap.com/v3/geocode/regeo?key={$config["geo_map_key"]}&callback=&location=' + location, {}, function (res) {
      if (res.status == 1) {
         var addr = res.regeocode.formatted_address.length != 0 ? res.regeocode.formatted_address : '';
         addr = addr.replace(/\(/g, ' ');
         addr = addr.replace(/\)/g, '');
         getLocation(
            res.regeocode.addressComponent.province, 
            res.regeocode.addressComponent.city, 
            res.regeocode.addressComponent.district,
            addr  
         );
      }
   });
}
function getLocationByIp() {
   $.get('/ip', {}, function (res) {
      getLocation(res.data.province, res.data.city, res.data.district,'');
   });
}
function getLocation(province, city, district, addr) {
   $.get('/location', {
      province: province,
      city: city,
      district: district,
      addr: addr,
   }, function (res) {
      if (res.status == 1) {
         //匹配成功 返回
         mul_type.showResult(res.data);
      }
   })
}

前端下拉组件导入  jquery.area.js

var mul_type = new mulTypes({'level':4,'selector':'.inpu-box','title':'选择省市区','sub_title':'选择省份/地区','callback':function(pid,callBack){
   //获取分类的函数
   $.post('/types',{
      pid:pid,
   },function(res){
      if (res.status==1) {
         callBack(res.data);
      }
   })
}});

后端实现 

微信token取JSDK初始化信息  /config

$nonce = noncestr();
$token = (new WX(API_WX_APPID, API_WX_APPKEY))->getAccessToken();
$r = json_decode(httpRequest("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$token}&type=jsapi"));
succ([
   'appId' => API_WX_APPID,
   'timestamp' => TIMESTAMP,
   'nonceStr' => $nonce,
   'signature' => sha1("jsapi_ticket={$r->ticket}&noncestr={$nonce}×tamp=" . TIMESTAMP . "&url={$_GET['url']}"),
]);

通过pid取下级列表 直到叶子节点 /types

succ(onlyfields(fetch_all("SELECT * FROM areas WHERE pid=" . intval($_GET['pid'])), 'id,pid,name'));

通过ip反差位置 /ip

$rs = json_decode(httpRequest("https://restapi.amap.com/v3/ip?ip={$ip}&key={$config['geo_map_key']}"), true);
$city = fetch_first("SELECT * FROM district WHERE name like '%" . addslashes($_GET['city']) . "%'");
$province = fetch_first("SELECT * FROM district WHERE id={$city['upid']}");
$district = fetch_first("SELECT * FROM district WHERE upid={$city['id']}");
succ(['province' => $province['name'], 'city' => $city['name'], 'district' => $district['name']]);

通过省市区位置取区域信息 /location

//匹配区域
$district = addslashes(trim($_GET['district']));
$city = addslashes(trim($_GET['city']));
$province = addslashes(trim($_GET['province']));
$addr = addslashes(trim($_GET['addr']));
// fail("SELECT * FROM area WHERE name='{$district}' AND city='{$city}' AND province='{$province}'");
$district_row = fetch_first("SELECT * FROM area WHERE name='{$district}' AND city='{$city}' AND province='{$province}'");
if (!$district_row) {
   fail('无法获取内容');
}
//匹配到镇或者街道
$zones = fetch_all("SELECT * FROM area WHERE pid={$district_row['id']}");
$res = [];
foreach ($zones as $k => $v) {
   similar_text($v['name'], $addr, $percent);
   $res[$k] = $percent;
}
arsort($res);
$index = key($res);
$zone = $zones[$index];
succ(onlyfields(C::t(PT_ZONE)->backtrace($zone['id'], true), 'id,pid,name'));

backtrace 实现

// 追溯 整条树链结构  all true 获取全部信息 false只获取主键ID信息  递归转迭代 然后逆转 取整条链接数据
public function backtrace($id, $all = false)
{
   $tasks   = [$id];
   $results = [];
   while (count($tasks)) {
      $cur_id = (int)array_pop($tasks);
      $row    = $this->fetch($cur_id);
      $pid    = $row['pid'];
      if ($all) {
         $results[] = $row;
      } else {
         $results[] = $cur_id;
      }
      if ($pid > 0) {
         $tasks[] = $pid;
      }
   }
   return array_reverse($results);
}


返回顶部