java微信获取经纬度转换为高德坐标小结

最近一直在做微信公众号的开发,其中涉及到定位商家地理位置,我方所用的地图控件是腾讯地图,通过地址定位 CityService获取商家的位置信息和经纬度,这里的经纬度是腾讯经纬度。(当然也是可以使用高德地图或者其他地图的),获取到经纬度lat和lon。

而通过微信接口获取实时地理位置的经纬度,实质上得到的是GPS坐标,并不是(高德、百度、google系)经纬度。如果直接用之前保存好的商家经纬度和微信接口获得到的经纬度(gps坐标)进行距离计算,会产生大概500m的差距,打个比方说,就是两个数据单位不统一。通过微信接口获取到的经纬度(gps坐标)还需要一步处理,将GPS坐标转化为经纬度,将转化后的经纬度和商家经纬度通过计算可以获得正常的距离(有误差,但是误差比较小)。

以下是部分代码(供参考):

1. 微信接口获取经纬度(GPS坐标)

后端:

//微信获取地理位置

HttpServletRequest request = ThreadContextHolder.getRequest();

String url = request.getRequestURL().toString();

if (request.getQueryString() !=null) {

url += "?" + request.getQueryString();

}

String jsapi_ticket = WeixinConfig.getJSAPITicketInstance();

Map<String, String> map = SignUtil.sign(jsapi_ticket, url);

this.putData("appId", WeixinConfig.getAppId());

this.putData("timestamp", map.get("timestamp"));

this.putData("nonceStr", map.get("nonceStr"));

this.putData("signature", map.get("signature"));

 

附:

SignUtil

public class SignUtil {

    @SuppressWarnings("rawtypes")

public static void main(String[] args) {

        String jsapi_ticket = "jsapi_ticket";

 

        // 注意 URL 一定要动态获取,不能 hardcode

        String url = "http://example.com";

        Map<String, String> ret = sign(jsapi_ticket, url);

        for (Map.Entry entry : ret.entrySet()) {

            System.out.println(entry.getKey() +", " + entry.getValue());

        }

    };

 

    public static Map<String, String> sign(String jsapi_ticket, String url) {

        Map<String, String> ret = new HashMap<String, String>();

        String nonce_str = CommonUtil.create_nonce_str();

        String timestamp = CommonUtil.create_timestamp();

        String string1;

        String signature = "";

 

        //注意这里参数名必须全部小写,且必须有序

        string1 = "jsapi_ticket=" + jsapi_ticket +

                  "&noncestr=" + nonce_str +

                  "×tamp=" + timestamp +

                  "&url=" + url;

//        System.out.println("string1:"+string1);

        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;

    }

 

    public static String create_timestamp() {

     Date date = new Date();

     DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");

     return format.format(date);

        //return Long.toString(System.currentTimeMillis() / 1000);

    }

}

 

public static StringgetJSAPITicketInstance(){

if(js_api_ticket ==null ||js_api_ticket.equals("")){

String result = WeixinUtil.getJSApiTicket(getTokenInstance());

JsAPITicket jsApiTicket = JSONObject.parseObject(result, JsAPITicket.class);

js_api_ticket = jsApiTicket.getTicket();

int expiresIn = jsApiTicket.getExpires_in() * 1000 - 300;

TimerTask timerTask = new TimerTask() {

@Override

public void run() {

js_api_ticket = null;

}

};

Timer timer = new Timer();

timer.schedule(timerTask, expiresIn);

}

return js_api_ticket;

}

 

public static StringgetJSApiTicket(String accessToken) {

String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN",

accessToken);

JSONObject jsonObject = httpRequest(requestUrl, "GET", null);

// 如果请求成功

if (null != jsonObject) {

 

try {

jsonObject.getString("ticket");

} catch (JSONException e) {

// 获取token失败

log.error("获取ticket失败 errcode:{} errmsg:{}",

jsonObject.getInt("errcode"),

jsonObject.getString("errmsg"));

jsonObject = new JSONObject();

}

}

return jsonObject.toString();

}

前端:

<script src="js/jquery-1.8.0.min.js"></script>

<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

<script type="text/javascript">

var userLatitude = 0;

var userLongitude = 0;

         //圆周率   

 

wx.config({

    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。

    appId: '${appId }', // 必填,公众号的唯一标识

    timestamp: '${timestamp }', // 必填,生成签名的时间戳

    nonceStr: '${nonceStr }', // 必填,生成签名的随机串

    signature: '${signature }',// 必填,签名,见附录1

    jsApiList: ['checkJsApi', 'onMenuShareTimeline',

'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo',

'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem',

'showAllNonBaseMenuItem', 'translateVoice', 'startRecord',

'stopRecord', 'onRecordEnd', 'playVoice', 'pauseVoice',

'stopVoice', 'uploadVoice', 'downloadVoice', 'chooseImage',

'previewImage', 'uploadImage', 'downloadImage',

'getNetworkType', 'openLocation', 'getLocation',

'hideOptionMenu', 'showOptionMenu', 'closeWindow',

'scanQRCode', 'chooseWXPay', 'openProductSpecificView',

'addCard', 'chooseCard', 'openCard'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2

});

  

  

  wx.ready(function(){

    // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

  wx.getLocation({

    success: function (res) {

    userLatitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90

    userLongitude= res.longitude; // 经度,浮点数,范围为180 ~ -180。

         var speed = res.speed;// 速度,以米/每秒计

         var accuracy = res.accuracy;// 位置精度

      }

  });

  });

  

  wx.error(function(res){

  alert(location.href.split('#')[0]);

    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。

alert(res.errMsg);

});

</script>

附:

对微信接口获取经纬度(GPS坐标)的监听

function lisner(){

    if(userLatitude && userLongitude){

//获取到GPS坐标后,停止监听事件+调用方法

     clearInterval(lisnerID);

     getPosition(userLongitude,userLatitude);

}

}

var lisnerID = setInterval(lisner,100);

 

 

GPS坐标转化为高德系经纬度

function getPosition(yy,xx) {

        var url = "http://restapi.amap.com/v3/assistant/coordinate/convert?locations="

+yy+","+xx+"&coordsys=gps&output=json&key=你的key";

        $.ajax({

            url: url,

            success: function(data,status,xhr) {

                realuserLatitude = data.locations.split(",")[1];

                realuserLongitude = data.locations.split(",")[0];

            },

            dataType: 'jsonp'

        });

    }

微信JS-SDK坐标位置转换为百度地图坐标

function getBaiduPosition(yy,xx) {

        var url ="http://api.map.baidu.com/geoconv/v1/?coords="+yy+","+xx+"&from=1&to=5&ak=PCPa5VCFfVj7yXR40WWQnSKUPF3W96y8";

        $.ajax({

            url: url,

            success: function(data,status,xhr) {

                realuserLatitude = data.result[0].y;

                realuserLongitude = data.result[0].x;

            },

            dataType: 'jsonp'

        });

    }

realuserLatitude 和realuserLongitude 为转化后的经纬度。


高德key获取:



参考链接:

https://www.cnblogs.com/zsy/p/5492799.html

http://lbsbbs.amap.com/forum.php?mod=viewthread&tid=724&highlight=%E5%9D%90%E6%A0%87%E8%BD%AC%E6%8D%A2(如何将非高德坐标转换为高德坐标系)

http://www.storyday.com/wp-content/uploads/2008/09/latlung_dis.html(经纬度计算小工具)

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值