微信小程序设备位置上报:BD09 与 WGS84 的那点事
小程序里要做设备位置上报,最常见的坑不是 API 调用,而是坐标系对不上。这里把链路讲清楚,并给一个「失败就静默降级」的稳妥写法。
1. 三种坐标系
- WGS84:GPS 原始坐标(境外地图、部分后端存储用);
- GCJ-02:国测局加密,俗称「火星坐标」。微信
wx.getLocation默认返回的就是它; - BD09:百度在 GCJ-02 上再加密一层。百度地图必须用 BD09。
也就是说:小程序拿到的是 GCJ-02,如果你要把点打到百度地图上,得先转 BD09;如果你的后端/地图用的是 WGS84,就得反向解密回 WGS84。别直接混用,否则偏移几百米。
2. 取位置并上报 MQTT
wx.getLocation({
type: 'gcj02',
success(res) {
const { longitude, latitude } = res;
const [bdLng, bdLat] = gcj02ToBd09(longitude, latitude); // 转 BD09
mqttPublish({ lng: bdLng, lat: bdLat, ts: Date.now() });
},
fail() {
// 静默降级:拿不到位置也别卡住业务流程
mqttPublish({ lng: 0, lat: 0, ts: Date.now() });
}
});
3. 静默降级的理由
设备可能在地下室、没授权定位、或系统定位服务被关。这些情况 fail 很正常。直接弹错或中断上报反而不好——所以约定 0,0 表示「未知位置」,后端照常接收,只是地图上不标点。这样链路永远不断。
别忘了:wx.getLocation需要在小程序后台配置requiredPrivateInfos并完成隐私保护指引审核,否则真机会调不起来。
4. GCJ-02 → BD09 转换
function gcj02ToBd09(lng, lat) {
const x = lng, y = lat;
const z = Math.sqrt(x*x + y*y) + 0.00002 * Math.sin(y * Math.PI);
const theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI);
return [z * Math.cos(theta) + 0.0065, z * Math.sin(theta) + 0.006];
}
← 返回首页