微信接口调用百度地图api实现微信公众号打卡
Posted 远方f
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信接口调用百度地图api实现微信公众号打卡相关的知识,希望对你有一定的参考价值。
前言
因最近给的需求要在微信公众号完成考勤打卡,刚开始说根据员工连接公司的wifi去判断,网上查了下java好像没得这个功能,所以只能选择在地图来完成。
本人也是第一次接触微信公众号,所以刚开始动手比较困难,好在经过一番摸索还是完成了。这里记录下自己的地图方案。
准备工作
既然是微信公众号肯定是基于微信接口的,也不用想的那么复杂,其实就是基于前台weui样式+微信js接口。下面详细说明步骤。
首先需要在公众号设置功能设置中配置微信公众号js接口安全域名
按流程把文件放在项目工程静态资源下
另外在基本配置中查看开发者密码后设置IP白名单,否则后续调用jssdk会报自身IP不在白名单内的错误
获取微信接口回调的数据
public class GetWeChatUtil { public static final String wechat_token_url = "https://api.weixin.qq.com/cgi-bin/token" public static final String wechat_appid = "xxx"; public static final String wechat_secret = "xxx"; public static final String wechat_token_grant_type = "client_credential"; public static final String wechat_jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"; public static final String wechat_jsapi_ticket_type = "jsapi"; public static Map<String,Object> getWeChatToken(){ Map<String,Object> map = new HashMap<>(); try { Map<String,String> params = new HashMap<String, String>(); String ss = HttpConnectionUtil.httpsSendPost(wechat_token_url+"?grant_type="+wechat_token_grant_type
+"&appid="+wechat_appid+"&secret="+wechat_secret, null, "", "UTF-8", null); System.out.println("----获取token返回信息:"+ss); JSONObject json = JSONObject.parseObject(ss); if(json.containsKey("access_token")){ map.put("token", json.get("access_token")); map.put("expires", json.get("expires_in")); } } catch (Exception e) { e.printStackTrace(); } return map; } public static Map<String,Object> getJsapiTicket(String token) { Map<String,Object> map = new HashMap<String, Object>(); try { Map<String,String> params = new HashMap<>(); params.put("access_token", token); params.put("type", "jsapi"); String ss = HttpConnectionUtil.httpsSendPost(wechat_jsapi_ticket_url + "?access_token=" + token + "&type=" + wechat_jsapi_ticket_type, null, "", "UTF-8", null); System.out.println("----获取JsapiTicket返回信息:"+ss); JSONObject json = JSONObject.parseObject(ss); if (json.getIntValue("errcode") == 0) { map.put("ticket", json.get("ticket")); map.put("expires", json.get("expires_in")); } }catch (Exception e) { e.printStackTrace(); } return map; } public static Map<String, String> sign(String jsapi_ticket, String url) { Map<String, String> ret = new HashMap<>(); String nonce_str = create_nonce_str(); String timestamp = create_timestamp(); String string1; String signature = ""; string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "×tamp=" + timestamp + "&url=" + url; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret.put("url", url); ret.put("jsapi_ticket", jsapi_ticket); ret.put("nonceStr", nonce_str); ret.put("timestamp", timestamp); ret.put("signature", signature); return ret; } private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } private static String create_nonce_str() { return UUID.randomUUID().toString(); } private static String create_timestamp() { return Long.toString(System.currentTimeMillis() / 1000); } }
返回给前端调用微信接口必要参数
@Resource private RedisTemplate<String,String> redisTemplate; @RequestMapping("getwechatparams") @ResponseBody public Map<String,String> getParams(@RequestParam String url) { if (redisTemplate.opsForValue().get("token") == null) { Map<String,Object> map = GetWeChatUtil.getWeChatToken(); if (map.get("token") != null) { redisTemplate .opsForValue() .set("token", map.get("token").toString(), Long.parseLong(map.get("expires").toString()), TimeUnit.SECONDS); } } System.out.println("-----getWeToken:"+redisTemplate.opsForValue().get("token")); if (redisTemplate.opsForValue().get("ticket") == null) { Map<String,Object> mm = GetWeChatUtil.getJsapiTicket(redisTemplate.opsForValue().get("token")); if (mm.get("ticket") != null) { redisTemplate .opsForValue() .set("ticket", mm.get("ticket").toString(), Long.parseLong(mm.get("expires").toString()), TimeUnit.SECONDS); } } System.out.println("-----getWeTicket:"+redisTemplate.opsForValue().get("ticket")); String weTicket = redisTemplate.opsForValue().get("ticket"); Map<String, String> ret = GetWeChatUtil.sign(weTicket, url); ret.put("appId", GetWeChatUtil.wechat_appid); return ret; }
前端百度地图显示
这里就只贴显示地图的关键性代码
1 <script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=ak密匙"></script> 2 <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> 3 4 <div id="allmap" style="width: 100%; height: 410px;"></div>
这里需要调用wx.getLocation()回调成功后的参数res中存放的是当前自身的GPS经纬度坐标,需要将GPS坐标系通过百度接口转换成百度坐标系
$(function () { $.ajax({ async: false, url: "/getwechatparams", type: "POST", data: { "url": window.location.href }, dataType: "json", success: function (bal) { wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来 appId: bal.appId, // 必填,公众号的唯一标识 timestamp: bal.timestamp, // 必填,生成签名的时间戳 nonceStr: bal.nonceStr, // 必填,生成签名的随机串 signature: bal.signature,// 必填,签名,见附录1 jsApiList: [\'openLocation\', \'getLocation\'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function () { wx.getLocation({ // 获取微信接口中的当前坐标经纬度 type: \'wgs84\', // GPS坐标 success: function (res) { //alert("gps转换前:" + res.longitude + "," + res.latitude) var lnggg = \'\'; // 经度 var lattt = \'\'; // 纬度 var coordinate = \'\'; // 签到地点坐标 $.ajax({ async: false, url: "/get/location", data: { "longitude": res.longitude, "latitude": res.latitude }, dataType: \'json\', success: function (responseData) { lnggg = responseData.obj.lng; lattt = responseData.obj.lat; }, error: function (responseData) { alert(responseData.msg); } }); // 百度地图API功能 var map = new BMap.Map("allmap"); map.enableScrollWheelZoom(true); //alert("gps转换后" + lnggg + \',\' + lattt); var point = new BMap.Point(lnggg, lattt); var geo = new BMap.Geocoder(); geo.getLocation(point, function (rs) { var addComp = rs.addressComponents; var address = addComp.city + addComp.district + addComp.street; // 当前自身详情街道地址 //alert(address) }); var geolocation = new BMap.Geolocation(); geolocation.getCurrentPosition(function (r) { r.point.lng = lnggg; r.point.lat = lattt; //alert("r.point.lng:" + r.point.lng + ",r.point.lat:" + r.point.lat); if (this.getStatus() == BMAP_STATUS_SUCCESS) { var mk = new BMap.Marker(r.point); // 创建标注 map.addOverlay(mk); // 将标注小红点添加到地图中 map.centerAndZoom(r.point, 16); // 缩放级别16 map.panTo(r.point); coordinate = "116.40213223,40.10213223"; // 签到地点坐标 var arr = coordinate.split(","); var lon = arr[0]; var latt = arr[1]; var pointAttendance = new BMap.Point(lon, latt); r.point.lng = lon; r.point.lat = latt; var mk2 = new BMap.Marker(r.point); var label = new BMap.Label("显示的文字", {offset: new BMap.Size(20, -10)}); mk2.setLabel(label); map.addOverlay(mk2); map.addOverlay(pointAttendance); mk2.setAnimation(BMAP_ANIMATION_BOUNCE); // 点跳动,没反应 circle = new BMap.Circle(pointAttendance, 200, { fillColor: "blue", strokeWeight: 1, fillOpacity: 0.2, strokeOpacity: 0.2 });// 显示签到点的位置(半径为200米的一个圆) map.addOverlay(circle); //计算当前位置与考勤点距离 var distance = map.getDistance(pointAttendance, point).toFixed(2); //alert("距离为" + distance); } else { switch (this.getStatus()) { case 2: $.alert("位置结果未知 获取位置失败...", "加载地图失败", function () {}); break; case 3: $.alert("导航结果未知 获取位置失败...", "加载地图失败", function () {}); break; case 4: $.alert("非法密钥 获取位置失败...", "加载地图失败", function () {}); break; case 5: $.alert("非法请求位置 获取位置失败...", "加载地图失败", function () {}); break; case 6: $.alert("sorry 当前没有权限 获取位置失败...", "加载地图失败", function () {}); break; case 7: $.alert("sorry 服务不可用 获取位置失败...", "加载地图失败", function () {}); break; case 8: $.alert("sorry 请求超时 获取位置失败...", "加载地图失败", function () {}); break; } } }, { enableHighAccuracy: true }) }, error: function () { $.alert("请检查GPS网络是否正常", "加载地图失败", function () {}); } } ); }); } }); });
GPS坐标系转百度坐标系
@RequestMapping("get/location") @ResponseBody public AjaxResponse getLocation(String longitude, String latitude) { try { Map<String, String> mapLocation = ScHttpRequestUtil.getWpsToBaiduLocation(longitude, latitude); return new AjaxResponse().setObj(mapLocation); } catch (IOException e) { log.error("{[]}", e); return new AjaxResponse().setMsg("地址解析错误请重试!"); } } public static synchronized Map<String, String> getWpsToBaiduLocation(String longitude, String latitude) throws IOException { BufferedReader br = null; StringBuffer sb = new StringBuffer(); URL url = new URL("http://api.map.baidu.com/ag/coord/convert?from=0&to=4&x=" + longitude + "&y=" + latitude); br = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); String str = null; while ((str = br.readLine()) != null) { sb.append(str); } Map<String,String> map = (Map<String, String>) JSON.parse(sb.toString()); Base64.Decoder decoder = Base64.getDecoder(); String lng = new String(decoder.decode(map.get("x")), "utf-8"); String lat = new String(decoder.decode(map.get("y")), "utf-8"); Map<String, String> mapLocation = new HashMap<>(); map.put("lng", lng); map.put("lat", lat); return map; }
至此,基于微信接口实现百度地图的功能就完成了
以上是关于微信接口调用百度地图api实现微信公众号打卡的主要内容,如果未能解决你的问题,请参考以下文章