How I Built a Mood‑Tracking Mini‑Program with Fuzzy Location, Backend Reverse Geocoding, and Manual Map Selection
This article details the step‑by‑step development of a WeChat mini‑program that adds location‑based check‑ins, covering fuzzy location retrieval, moving reverse‑geocoding to the backend for key protection, the failed attempt at precise GPS, and the final hybrid approach of fuzzy auto‑location combined with manual map point selection.
Background
The "Mood Diary" WeChat mini‑program records daily moods and needed a geographic check‑in feature, prompting the author to document the implementation challenges.
Phase 1: Fuzzy Location
Without a privacy statement, only wx.getFuzzyLocation (exposed as uni.getFuzzyLocation in uni‑app) could be used, returning only latitude and longitude. The coordinates lack address details, requiring backend reverse‑geocoding.
uni.getFuzzyLocation({
type: 'gcj02',
success: (pos) => {
// pos = { latitude: 39.90, longitude: 116.40 }
// only coordinates, no city/district text
// need backend geocode API → "Beijing City, Chaoyang District, Wangjing Street"
}
})Limitation: Coordinates are coarse and may deviate noticeably, making precise map markers difficult.
Phase 2: Front‑end Direct Map SDK
After obtaining coordinates, the author initially integrated the Tencent Map JS SDK ( qqmap-wx-jssdk) on the front end to perform reverse‑geocoding.
import QQMapWX from 'qqmap-wx-jssdk'
const qqmap = new QQMapWX({
key: import.meta.env.VITE_TENCENT_MAP_KEY as string,
})
uni.getLocation({
type: 'gcj02',
success: (pos) => {
qqmap.reverseGeocoder({
location: { latitude: pos.latitude, longitude: pos.longitude },
success: (res) => {
const addr = res.result.address
const city = res.result.address_component.city
}
})
}
})Problem: The map API key is exposed in the client bundle, posing a significant security risk.
Phase 3: Moving Reverse Geocoding to the Backend
To hide the map service key, the reverse‑geocoding call was shifted to a backend endpoint that invokes the Tencent Map WebService API using a server‑side key.
async fn geocode(query, config) -> Result<HttpResponse> {
// call Tencent Map WebService API, key stored in backend env variable
let resp = client.get("https://apis.map.qq.com/ws/geocoder/v1/")
.query(&[("location", format!("{},{}", lat, lng)), ("key", config.tencent_map_key)])
.send().await?;
// ...
}Benefit: The map provider key remains only on the server; the front end never sees it. The trade‑off is an extra network request.
Phase 4: Attempting Precise Location
The author tried to request high‑accuracy GPS via wx.getLocation:
uni.getLocation({
type: 'gcj02',
isHighAccuracy: true, // GPS‑level precision
success: (pos) => {
// backend reverse‑geocode → "Beijing City, Chaoyang District, Jianguo Road 93"
}
})Review Result: Repeated submissions were rejected. Community sources indicated that personal developers face strict review for location‑heavy features, and a mood‑tracking app does not qualify as a “strong location‑dependent” scenario, making getLocation permission virtually unattainable.
Phase 5 (Current): Fuzzy Location + Manual Selection
Since precise GPS was infeasible, a compromise was adopted: if automatic fuzzy positioning is inaccurate, allow the user to manually adjust the point using wx.chooseLocation, which passes review more easily.
Current workflow:
用户点击“添加位置"
├── 自动定位 → getFuzzyLocation(返回经纬度)→ 后端 geocode API 逆地理编码 → 地址文本
└── 手动选择 → chooseLocation → 地图选点,直接返回坐标 + 地址Automatic positioning: Uses getFuzzyLocation to obtain coordinates; backend reverse‑geocoding returns an address such as "Nanjing City, Confucius Temple Gate".
Manual selection: Users pick a precise spot on the map via chooseLocation, which is considered user‑initiated and faces a lenient review.
The data model stores latitude and longitude as nullable fields; successful automatic or manual positioning writes the values, while failures or cancellations leave them null.
interface MoodRecord {
location: string // address text (auto: backend reverse‑geocode; manual: chooseLocation output)
locationCity: string // city name
latitude: number | null // null if positioning fails or is cancelled
longitude: number | null
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
