微信接口調用百度地圖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;
}

 

至此,基於微信接口實現百度地圖的功能就完成了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM