微信接口调用百度地图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 + "&timestamp=" + 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实现微信公众号打卡的主要内容,如果未能解决你的问题,请参考以下文章

微信公众平台开发利用百度接口,制作一键导航功能

关于微信公众平台调用百度地图导航

微信公众平台如何在开发模式下设置天气预报自动回复

微信小程序怎么破定位

微信JS-SDK之地理位置的获取与在线导航,集成百度地图实现在线地图搜索

微信域名检测接口原理,微信js接口域名该如何实现