前提:在企业微信中开发自建应用,需要获取用户的实际地址(一波三折)(比如:上海市迪士尼乐园~)
“一波”:
最初的企业微信版本的获取经纬度与实际地址的方式是使用的百度地图JavaScript API(需要用户授权才可以正常使用)。
“一折”:
遇到的问题:移动端的兼容性是很难测试的全面的,因为市场上手机机型厂商、系统版本等五花八门,公司的测试机型有限,所以并没有测试出来兼容性问题。等上线之后,问题出来了,很多用户会提示“用户拒绝授权地理位置”,是什么原因导致的呢?我们来看一下仅使用百度地图JS API的代码:
getCurrentPositionByBaidu() {
return new Promise(function(resolve, reject) {
let geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(
function(r) {
if (this.getStatus() === BMAP_STATUS_SUCCESS) {
//精度为undefined 代表用户拒绝授权地理位置
if (r.accuracy === null) {
reject({
type: '1', //授权失败
errorMessage: '用户拒绝授权地理位置',
});
}
let myGeo = new BMap.Geocoder();
myGeo.getLocation(new BMap.Point(r.longitude, r.latitude), result => {
if (result) {
resolve({
longitude: r.longitude,
latitude: r.latitude,
address: result.address,
});
} else {
reject({
type: '2', //详细地址解析失败
errorMessage: '详细地址解析失败',
});
}
});
} else {
reject({
type: '0', //百度地图api调用出错
errorMessage: '百度地图api调用出错',
});
}
},
function(err) {
//没有网络的返回值
if (err.errorCode === 3) {
reject({
type: '3', //超时,没有网络
errorMessage: '超时,没有网络',
});
} else {
reject({
type: '4', //未知的错误
errorMessage: 'unknown error',
});
}
}
)
}
}
我们从代码上可以看出,当百度地图的api返回精确度(accuracy)为null时,获取到的经纬度非常不准确,所以我们默认是用户拒绝授权了地理位置。经过对比排查,发现导致这个问题的原因是,在企业微信环境中,没有唤起百度地图的授权弹框。
“二折”
我们如何在企业微信环境中唤起百度地图的授权弹框呢?翻了一波百度地图的api文档,发现并没有提供相关的api,这个授权弹框是浏览器的行为,看着像是部分机型的企业微信禁掉了这个行为。
从百度地图的角度没有找到解决办法,我想着是不是企业微信的客户端api有破解之道呢?
哎发现了企业微信提供的getLocation方法:
//获取地理位置接口
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; // 位置精度
}
});
我们使用官方demo链接尝试了一下这个api:http://open.work.weixin.qq.com/api/jsapidemo
惊喜!调用企业微信的api,弹起了企业微信的授权框:
所以我们想,通过企业微信的位置授权方式,应该是已经把app的位置权限控制好了,但是我们发现企业微信的getLocation方法的返回值只有经纬度,然而我们需要获取用户的实际地址,所以我们打算:使用企业微信的授权+百度地图的经纬度+百度地图的逆地址解析功能结合的方式,代码变化如下:
//简写
getCurrentPositionByQYWX(){
wx.getLocation().then(
()=>{
getCurrentPositionByBaidu()
}
)
}
经过测试,这个方式并没有解决所有用户的授权问题。部分手机仍然需要百度地图的授权才可以正常使用。
脑壳疼~
“三折”
我们从代码本身来找找解决问题的方法。
罪魁祸首是这里:
let geolocation = new BMap.Geolocation();
geolocation.getCurrentPosition(
function(r) {
if (this.getStatus() === BMAP_STATUS_SUCCESS) {
//精度为undefined 代表用户拒绝授权地理位置
if (r.accuracy === null) {
reject({
type: '1', //授权失败
errorMessage: '用户拒绝授权地理位置',
});
}
}
}
)
我们调用百度地图的api:getCurrentPosition()来获取经纬度的时候,会有这个精度(accuracy)的问题,我们再看下企业微信的api: getLocation()方法返回了经纬度,哎,有戏。但是企业微信使用的坐标系是gps坐标,然而百度地图使用的是百度坐标系,坐标系的不同会影响经纬度的精确性,所以我们找到一个转换坐标系的方法库:gcoord.js。最终我们的想法是采用如下方案:企业微信授权+企业微信经纬度转百度坐标+百度地图逆地址解析。代码如下:
getCurrentPosition(){
return new Promise(function(resolve, reject) {
weixin.getLocation().then(
(res) => {
let [longitude, latitude] = gcoord.transform(
[ res.longitude, res.latitude ], // 经纬度坐标
gcoord.WGS84, // 当前坐标系
gcoord.BD09 // 目标坐标系
);
console.log(longitude, latitude, '纯打卡包转换成百度地图后经纬度');
let myGeo = new BMap.Geocoder();
myGeo.getLocation(new BMap.Point(longitude, latitude), result => {
if (result) {
resolve({
longitude,
latitude,
address: result.address,
});
} else {
reject({
type: '2', //详细地址解析失败
errorMessage: i18n.t('addressResolveFail'),
});
}
});
},
() => {
reject({
type: '1', //授权失败
errorMessage: i18n.t('userRefuseRight'),
});
}
);
});
}
上线至今,没有反馈gps授权问题了。