1. 开发前的准备(下面无先后顺序)
2. 后端开发(下面有先后顺序)
public ResponseResult getAccessToken() {
String accessTokenStr = redisHelper.getStr("access_token_expires_in");
if (StringUtils.isNotEmpty(accessTokenStr)) {
logger.info("access_token已缓存:" + accessTokenStr);
return new ResponseResult(ResponseResult.SUCCESS, "成功", accessTokenStr);
}
//h5AccessTokenUrl:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
String url = h5AccessTokenUrl.replace("APPID", "appId").replace("APPSECRET", "appSecret");
String result = HttpRequest.get(url).timeout(6000).execute().body();
logger.info("获取accessToken的返回:" + result);
if (StringUtils.isEmpty(result)) {
return new ResponseResult(ResponseResult.ERROR_400,"获取accessToken失败");
}
JSONObject data = JSON.parseObject(result);
if (data.containsKey("access_token")) {
//说明返回成功
if (data.containsKey("expires_in")) {
//微信官方的默认过期时间应该是7200秒,我们这里设置一定要小于7200秒,但是不能太小,请求太频繁,会被微信拦截掉
redisHelper.setStr("access_token_expires_in", data.getString("access_token"), 3600, TimeUnit.SECONDS);
}
return new ResponseResult(ResponseResult.SUCCESS, "成功", data.getString("access_token"));
}
if (data.containsKey("errcode")) {
return new ResponseResult(ResponseResult.ERROR_400, data.getString("errmsg"));
}
return new ResponseResult(ResponseResult.ERROR_400, "获取accessToken失败");
}
public ResponseResult getJsApiTicket() {
String jsApiTicketStr = redisHelper.getStr("jsapi_ticket_expires_in");
if (StringUtils.isNotEmpty(jsApiTicketStr)) {
logger.info("jsapi_ticket已缓存:" + jsApiTicketStr);
return new ResponseResult(ResponseResult.SUCCESS, "成功", jsApiTicketStr);
}
ResponseResult responseResult = this.getAccessToken();
if (ResponseResult.SUCCESS != responseResult.getCode() || null == responseResult.getData()) {
return new ResponseResult(ResponseResult.ERROR_400, "获取TICKET失败");
}
String accessToken = String.valueOf(responseResult.getData());
//h5JsApiTicketUrl:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
String url = h5JsApiTicketUrl.replace("ACCESS_TOKEN", accessToken);
String result = HttpRequest.get(url).timeout(6000).execute().body();
logger.info("获取jsApiTicket的返回:" + result);
if (StringUtils.isEmpty(result)) {
return new ResponseResult(ResponseResult.ERROR_400,"获取TICKET失败");
}
JSONObject data = JSON.parseObject(result);
if (0 != data.getIntValue("errcode") && !data.containsKey("ticket")) {
return new ResponseResult(ResponseResult.ERROR_400,"获取TICKET失败");
}
//说明返回成功
if (data.containsKey("expires_in")) {
//微信官方的默认过期时间应该是7200秒,我们这里设置一定要小于7200秒,但是不能太小,请求太频繁,会被微信拦截掉
redisHelper.setStr("jsapi_ticket_expires_in", data.getString("ticket"), 3600, TimeUnit.SECONDS);
}
return new ResponseResult(ResponseResult.SUCCESS,"成功", data.getString("ticket"));
}
public ResponseResult getH5Signature(String hrefURL) {
ResponseResult responseResult = this.getJsApiTicket();
if (ResponseResult.SUCCESS != responseResult.getCode() || null == responseResult.getData()) {
return new ResponseResult(ResponseResult.ERROR_400,"获取签名失败");
}
String jsApiTicket = String.valueOf(responseResult.getData());
String nonceStr = StringUtil.getRandom(10);
//需要注意的是,这里的时间戳是秒级时间戳(10位),不是毫秒级(13位)
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
try {
String url = URLDecoder.decode(hrefURL, "UTF-8");
String signature = DigestUtil.sha1Hex("jsapi_ticket=" + jsApiTicket + "&noncestr=" + nonceStr + "×tamp=" + timestamp + "&url=" + url);
logger.info("获取到的signature:" + signature);
if (StringUtils.isEmpty(signature)) {
return new ResponseResult(ResponseResult.ERROR_400,"获取签名失败");
}
Map<String, Object> data = new HashMap<>(4);
data.put("appId", h5AppId);
data.put("nonceStr", nonceStr);
data.put("timestamp", timestamp);
data.put("signature", signature);
logger.info("data数据:" + JSONUtil.toJsonStr(data));
return new ResponseResult(ResponseResult.SUCCESS,"成功", data);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new ResponseResult(ResponseResult.ERROR_400,"未知错误");
}
3. 前端开发
引入jweixin.js
import jweixin from '@/common/jweixin';
import wechat from '@/utils/wechat'
在onLoad()中初始化(获取经纬度)
onLoad() {
//如果是打开地图,点击的时候调用this.lcationHandleH5_01('open')
this.lcationHandleH5_01('init');
}
以下是代码实现
async lcationHandleH5_01(flag) {
const _this = this;
console.log('是否是微信客户端', wechat.isWechat());
if (!wechat.isWechat()) {
_this.$mHelper.toast('请在微信客户端打开');
return;
}
const hrefURL = window.location.href;
const signURL = encodeURIComponent(hrefURL.indexOf("#") > -1 ? hrefURL.split('#')[0] : hrefURL);
wechat.getH5Sign(signURL).then(res => {
console.log('wechat.getH5Sign()结果', res);
_this.lcationHandleH5_02(flag, res);
}).catch(err => {
_this.$mHelper.toast(`${err}`);
});
},
lcationHandleH5_02(flag, signData) {
const _this = this;
jweixin.config({
debug: true,
...signData,
jsApiList: ['openLocation', 'getLocation']
});
jweixin.error(err => {
console.error('jweixin配置出错======>', err);
});
jweixin.ready(() => {
if ('init' === flag) {
_this.lcationHandleH5_02_init();
} else {
_this.lcationHandleH5_02_choose();
}
});
},
lcationHandleH5_02_init() {
const _this = this;
jweixin.getLocation({
//type: 'gcj02', //wgs84返回gps坐标,gcj02返回可用于wx.getLocation 的坐标
success(res) {
console.log('jweixin.getLocation结果========>', JSON.stringify(res));
wechat.formatLocationH5(res.latitude, res.longitude).then(res3 => {
_this.curAddress = res3;
}).catch(err3 => {
_this.$mHelper.toast(`${err3}`);
});
},
fail(err) {
console.error('获取位置信息失败=======>', err);
_this.$mHelper.toast(`${err}`);
}
});
},
lcationHandleH5_02_choose() {
const _this = this;
jweixin.getLocation({
//type: 'gcj02', //wgs84返回gps坐标,gcj02返回可用于wx.getLocation 的坐标
success(res) {
jweixin.openLocation({
latitude: res.latitude,
longitude: res.longitude,
name: '我的位置',
success(res2) {
console.log('获取位置信息成功=======>', res2);
wechat.formatLocationH5(res2.latitude, res2.longitude).then(res3 => {
_this.curAddress = res3;
}).catch(err3 => {
_this.$mHelper.toast(`${err3}`);
});
},
fail(err2) {
console.error('获取位置信息失败=======>', err2);
_this.$mHelper.toast(`${err2}`);
}
});
},
fail(err) {
console.error('获取位置信息失败=======>', err);
_this.$mHelper.toast(`${err}`);
}
});
}
下面是wechat.js
import jweixin from '@/common/jweixin.js';
import constData from '@/static/const/serverConfig.json';
import wxMap from '@/common/qqmap-wx-jssdk.min.js';
import helper from '@/utils/helper.js';
import store from '@/store/index.js';
import {http} from '@/utils/request';
import {getH5Signature, parseH5LatLng} from '@/api/basicApi';
/* eslint-disable */
//判断是否公众号(微信H5)
const isWechat = () => {
// #ifdef H5
const ua = window.navigator.userAgent.toLowerCase();
//注意,下面的判断不能用===判断,只能用==判断
return ua.match(/micromessenger/i) == 'micromessenger'
// #endif
};
//获取H5签名
const getH5Sign = hrefURL => new Promise((resolve, reject) => {
const _this = this;
http.get(getH5Signature, {hrefURL}).then(res => {
console.log('查询到的签名结果', JSON.stringify(res));
if (200 === res.code) {
resolve(res.data);
} else {
_this.$mHelper.toast('初始化位置信息失败', 2000);
reject('初始化位置信息失败');
}
}).catch(err => {
reject(`初始化位置信息失败:${err}`);
});
});
//格式化位置
const formatLocationH5 = (latitude, longitude) => new Promise((resolve, reject) => {
const _this = this;
if (!latitude || !longitude) {
reject('参数不能为空');
}
http.get(parseH5LatLng, {lat: latitude, lng: longitude}).then(res => {
console.log('解析经纬度返回结果', JSON.stringify(res));
if (200 === res.code) {
resolve(res.data);
} else {
_this.$mHelper.toast('解析位置信息失败', 2000);
reject('解析位置信息失败');
}
}).catch(err => {
reject(`解析位置信息失败:${err}`);
});
});
export default {
isWechat,
getH5Sign,
formatLocationH5
};
3. 后端开发-解析经纬度获取位置信息(H5解析经纬度在后端)
public ResponseResult parseH5LatLng(String lat, String lng) {
if (StringUtils.isEmpty(lat) || StringUtils.isEmpty(lng)) {
return new ResponseResult(ResponseResult.ERROR_400,"经纬度不能为空");
}
try {
//txApiMapUrl:https://apis.map.qq.com/ws/geocoder/v1/?coord_type=5&get_poi=0&output=json&key=API_KEY&location=LOCATION_LATLNG
String url = txApiMapUrl.replace("API_KEY", txApiKey).replace("LOCATION_LATLNG", URLEncoder.encode(lat + "," + lng, "UTF-8"));
String result = HttpRequest.get(url).timeout(6000).execute().body();
if (StringUtils.isEmpty(result)) {
return new ResponseResult(ResponseResult.ERROR_400,"解析位置失败");
}
JSONObject jsonObject = JSON.parseObject(result);
if (null == jsonObject || 0 != jsonObject.getIntValue("status") || null == jsonObject.get("result")) {
return new ResponseResult(ResponseResult.ERROR_400,"解析位置失败");
}
JSONObject data = JSON.parseObject(jsonObject.getString("result"));
Map<String, Object> dataMap = new HashMap<>(5);
JSONObject location = JSON.parseObject(data.getString("location"));
dataMap.put("latitude", location.getBigDecimal("lat"));
dataMap.put("longitude", location.getBigDecimal("lng"));
dataMap.put("fullAddress", data.getString("address"));
JSONObject addressComponent = JSON.parseObject(data.getString("address_component"));
dataMap.put("address", addressComponent.getString("district") + addressComponent.getString("street"));
return new ResponseResult(ResponseResult.SUCCESS,"成功", dataMap);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new ResponseResult(ResponseResult.ERROR_400,"位置错误");
}