微信浏览器
① 公众号获取定位权限之后,需要在后台 【设置与开发】 - 【公众号设置】 - 【功能设置】 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);
}