微信公众号获取GPS并计算距离及IP地址信息

6 篇文章 0 订阅
3 篇文章 0 订阅

IP地址获取

NG配置

所有经过的NG链路都需要配置以下内容。原因是因为

location / {
            proxy_pass http://yun.baidu.com/baiduyunapp;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

JAVA代码获取IP

  1. 获取入口。
@Component
@Slf4j
public class HttpInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        RequestContextParam requestContextParam = new RequestContextParam();
        requestContextParam.setIpAddr(IpUtils.getIpAddr(request));
        RequestContextUtils.setContext(requestContextParam);
        return super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
        RequestContextUtils.removeContext();
    }
}
  1. 实际获取类IpUtils。
public class IpUtils {
    /**
     * 获取访问用户的客户端IP(适用于公网与局域网).
     */
    public static final String getIpAddr(final HttpServletRequest request)
            throws Exception {
        if (request == null) {
            throw (new Exception("getIpAddr method HttpServletRequest Object is null"));
        }
        String ipString = request.getHeader("x-forwarded-for");
        if (StringUtils.isEmpty(ipString) || "unknown".equalsIgnoreCase(ipString)) {
            ipString = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ipString) || "unknown".equalsIgnoreCase(ipString)) {
            ipString = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isEmpty(ipString) || "unknown".equalsIgnoreCase(ipString)) {
            ipString = request.getRemoteAddr();
        }

        // 多个路由时,取第一个非unknown的ip
        final String[] arr = ipString.split(",");
        for (final String str : arr) {
            if (!"unknown".equalsIgnoreCase(str)) {
                ipString = str;
                break;
            }
        }

        return ipString;
    }

    public static boolean internalIp(String ip) {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }

    private static boolean internalIp(byte[] addr) {
        if (StringUtils.isNull(addr) || addr.length < 2) {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0) {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4) {
                    return true;
                }
            case SECTION_5:
                switch (b1) {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }

    /**
     * 将IPv4地址转换成字节
     *
     * @param text IPv4地址
     * @return byte 字节
     */
    public static byte[] textToNumericFormatV4(String text) {
        if (text.length() == 0) {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try {
            long l;
            int i;
            switch (elements.length) {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                        return null;
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                        return null;
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                        return null;
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i) {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                        return null;
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i) {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                            return null;
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        } catch (NumberFormatException e) {
            return null;
        }
        return bytes;
    }

    public static String getHostIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
        }
        return "127.0.0.1";
    }

    public static String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
        }
        return "未知";
    }
}
  1. 其他辅助类。
public class RequestContextUtils {

    private static final ThreadLocal<RequestContextParam> context = new ThreadLocal<>();

    public static void setContext(RequestContextParam contextParam) {
        context.set(contextParam);
    }

    public static RequestContextParam getContext() {
        return context.get();
    }

    public static void removeContext() {
        context.remove();
    }
}

微信公众号GPS获取及坐标系转换

通过微信公众号获取GPS坐标,如果要计算该坐标与某个位置的距离。需要做以下操作。

  1. 将某个位置通过百度GPS解析成经纬度。
  2. 将公众号GPS坐标转换为百度坐标系。
  3. 只有保证以上两点在同一个坐标系才能计算距离。
    相关类及参数如下。

百度地图公共类


@Component("baiduMapUtils")
public class BaiduMapUtils {

    @Value("${baiduMaps.url}")
    private String url;

    @Value("${baiduMaps.ak}")
    private String ak;

    /**
     * 逆地理编码
     */
    public static final String REVERSE_GEOCODING = "reverse_geocoding/v3/";

    /**
     * 地理编码
     */
    public static final String GEOCODING = "geocoding/v3/";

    /**
     * 坐标转换
     */
    public static final String GEOCONV = "geoconv/v1/";



    /**
     * IP地理位置解析
     */
    public static final String IP_LOCATION = "location/ip";



    /**
     * 根据详细地址获取百度坐标点
     *      地址详细至 省 市 区/县 街道 门牌号
     * @param address 地址
     * @return  { lng: 经度, lat: 纬度 }
     */
    public JSONObject getCoordinate(String address) throws InterfaceServiceException {
        StringBuilder sb = new StringBuilder();
        sb.append("ak=");
        sb.append(ak);
        sb.append("&address=");
        sb.append(address);
        sb.append("&output=json");
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(url.concat(GEOCODING), sb.toString()));
        if (jsonObject.getInteger("status") != 0) {
            throw new InterfaceServiceException(RetCode.SYSTEM_ERROR.getCode(), "获取百度坐标点失败");
        }
        return jsonObject.getJSONObject("result").getJSONObject("location");
    }

    /**
     * 根据百度坐标 获取详细地址
     * @param lng 经度
     * @param lat 纬度
     * @return 地址详细至 省 市 区/县 街道 门牌号
     */
    public String getAddress(double lng, double lat) throws InterfaceServiceException {
        StringBuilder sb = new StringBuilder();
        sb.append("ak=");
        sb.append(ak);
        sb.append("&output=json");
        sb.append("&location=");
        sb.append(lat);
        sb.append(",");
        sb.append(lng);
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(url.concat(REVERSE_GEOCODING), sb.toString()));
        if (jsonObject.getInteger("status") != 0) {
            throw new InterfaceServiceException(RetCode.SYSTEM_ERROR.getCode(), "百度坐标获取详细地址失败");
        }
        return jsonObject.getJSONObject("result").getString("formatted_address");
    }

    /**
     * 其他坐标转换为百度坐标
     * @param lng 经度
     * @param lat 纬度
     * @param type
     *     默认 1:GPS设备获取的角度坐标,WGS84坐标;
     *         2:GPS获取的米制坐标、sogou地图所用坐标;
     *         3:google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标,国测局(GCJ02)坐标;
     *         4:3中列表地图坐标对应的米制坐标;
     *         5:百度地图采用的经纬度坐标;
     *         6:百度地图采用的米制坐标;
     *         7:mapbar地图坐标;
     *         8:51地图坐标
     * @return { lng: 经度, lat: 纬度 }
     */
    public JSONObject changeCoordinate(double lng, double lat, Integer type) throws InterfaceServiceException {
        StringBuilder sb = new StringBuilder();
        sb.append("ak=");
        sb.append(ak);
        sb.append("&coords=");
        sb.append(lng);
        sb.append(",");
        sb.append(lat);
        if (StringUtils.isNotEmpty(type)) {
            sb.append("&from");
            sb.append(type);
        }
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(url.concat(GEOCONV), sb.toString()));
        if (jsonObject.getInteger("status") != 0) {
            throw new InterfaceServiceException(RetCode.SYSTEM_ERROR.getCode(), "其他坐标转换为百度坐标失败");
        }
        // 取第一个匹配到的坐标点
        JSONObject result = jsonObject.getJSONArray("result").getJSONObject(0);
        JSONObject data = new JSONObject();
        data.put("lng", result.get("x"));
        data.put("lat", result.get("y"));
        return data;
    }
    /**
     * 两坐标直线距离计算 Sphere坐标系计算
     * @param lngFrom 起点经度
     * @param latFrom  起点纬度
     * @param lngTo   终点经度
     * @param latTo    终点经度
     * @return double 两坐标直线距离(单位:m) 误差 0.1m
     */
    public double getDistance(double lngFrom, double latFrom, double lngTo, double latTo) {
        GlobalCoordinates source = new GlobalCoordinates(latFrom, lngFrom);
        GlobalCoordinates target = new GlobalCoordinates(latTo, lngTo);
        return new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.Sphere, source, target).getEllipsoidalDistance();
    }


    /**
     * 根据百度坐标 获取详细地址
     * @param lng 经度
     * @param lat 纬度
     * @return 地址详细至 省 市 区/县 街道 门牌号
     */
    public JSONObject getAddressDivision(double lng, double lat) throws InterfaceServiceException {
        StringBuilder sb = new StringBuilder();
        sb.append("ak=");
        sb.append(ak);
        sb.append("&output=json");
        sb.append("&location=");
        sb.append(lat);
        sb.append(",");
        sb.append(lng);
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(url.concat(REVERSE_GEOCODING), sb.toString()));
        if (jsonObject.getInteger("status") != 0) {
            throw new InterfaceServiceException(RetCode.SYSTEM_ERROR.getCode(), "百度坐标获取详细地址失败");
        }
        return jsonObject.getJSONObject("result").getJSONObject("addressComponent");
    }



    /**
     * 通过ip地址获取地址信息
     * @param ip ip地址
     * @return
     * {
     *     address: "北京市",    #简要地址信息
     *     address_detail:    #结构化地址信息
     *     {
     *         city: "北京市",    #城市
     *         city_code: 131,    #百度城市代码
     *         province: "北京市",    #省份
     *     },
     *     point:    #当前城市中心点
     *     {
     *         x: "116.39564504",    #当前城市中心点经度
     *         y: "39.92998578"    #当前城市中心点纬度
     *     }
     * }
     * @throws InterfaceServiceException
     */
    public JSONObject getIPLocation(String ip) throws InterfaceServiceException {
        StringBuilder sb = new StringBuilder();
        sb.append("ak=");
        sb.append(ak);
        sb.append("&ip=");
        sb.append(ip);
        sb.append("&coor=bd09ll");
        JSONObject jsonObject = JSONObject.parseObject(HttpUtils.sendGet(url.concat(IP_LOCATION), sb.toString()));
        if (jsonObject.getInteger("status") != 0) {
            throw new InterfaceServiceException(RetCode.SYSTEM_ERROR.getCode(), "获取百度IP解析失败");
        }
        return jsonObject.getJSONObject("content");
    }
}

使用方式

private void getGpsDistance(String applyNo, double longitude, double latitude, Xd ext) throws Exception {
        try {
            JSONObject addr = baiduMapUtils.changeCoordinate(longitude, latitude, 3);
            log.info("转换为百度坐标:{}", addr.toJSONString());
            if (addr != null) {
                ext.setLatitude(new BigDecimal(addr.getString("lat")));
                ext.setLongitude(new BigDecimal(addr.getString("lng")));
            }
            if (applyNo != null && ext.getLatitude() != null && ext.getLongitude() != null) {

                XdBusi e = 从数据库获取;

                BigDecimal bg = new BigDecimal(baiduMapUtil.getDistance(ext.getLongitude().doubleValue(),
                        ext.getLatitude().doubleValue(),
                        DoubleUtils.getValueNullToDouble(e.getLongitude()),
                        DoubleUtils.getValueNullToDouble(e.getLatitude())) + "").divide(new BigDecimal(1000));
                double distanceStore = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                ext.setGpsApplyDistance(distanceStore + "");

                XdMerchantStore store = 从数据库获取;
                JSONObject coordinate = baiduMapUtil.getCoordinate(store.getOfficeDetailAddr());

                String lng = coordinate.getString("lng");
                String lat = coordinate.getString("lat");
                BigDecimal bg2 = new BigDecimal(baiduMapUtils.getDistance(DoubleUtils.getValueNullToDouble(lng),
                        DoubleUtils.getValueNullToDouble(lat),
                        ext.getLongitude().doubleValue(),
                        ext.getLatitude().doubleValue()) + "").divide(new BigDecimal(1000));
                double distanceM = bg2.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                ext.setGpsStoreDistance(distanceM + "");
            }


            JSONObject addrJsonObject = baiduMapUtils.getAddressDivision(ext.getLongitude().doubleValue(),
                    ext.getLatitude().doubleValue());
            String province = addrJsonObject.getString("province");
            String city = addrJsonObject.getString("city");
            ext.setGpsProvince(province);
            ext.setGpsCity(city);
        } catch (Exception e) {
            log.error("获取替换gps信息异常", e);
        }
    }
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值