文章来源: https://www.jianshu.com/p/c39a2c72dc65?from=singlemessage

利用位置服务获取特定设备和用户之间的距离:

用户位置: 微信H5, 用微信api的方式获取用户当前所在位置, 获取到的是: WGS84 (地理坐标系统)方式的坐标 【目前基本上所有定位空间位置的设备都使用这种坐标系统,例如手机的GPS系统。】

设备位置: 设备所在坐标用的是腾讯api https://lbs.qq.com/tool/getpoint/index.html 获取的坐标

直接计算有误差, 需要转化一下

WGS84转化为腾讯坐标示例:

$lon = '116.4303894043';
$lat = '39.914321899414';

$a = 6378245.0;
$ee = 0.00669342162296594323;
$pi = pi();
$res = gps84_To_Gcj02($lat, $lon);

var_dump($res);

function gps84_To_Gcj02($lat, $lon)
{
    global $a, $ee, $pi;
    $dLat = transformLat($lon - 105.0, $lat - 35.0);
    $dLon = transformLon($lon - 105.0, $lat - 35.0);
    $radLat = $lat / 180.0 * $pi;
    $magic = sin($radLat);
    $magic = 1 - $ee * $magic * $magic;
    $sqrtMagic = sqrt($magic);

    $dLat = ($dLat * 180.0) / (($a * (1 - $ee)) / ($magic * $sqrtMagic) * $pi);
    $dLon = ($dLon * 180.0) / ($a / $sqrtMagic * cos($radLat) * $pi);
    $mgLat = $lat + $dLat;
    $mgLon = $lon + $dLon;
    return array($mgLat, $mgLon);
}

function transformLat($x, $y)
{
    global $pi;
    $ret = -100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 0.1 * $x * $y
        + 0.2 * sqrt(abs($x));
    $ret += (20.0 * sin(6.0 * $x * $pi) + 20.0 * sin(2.0 * $x * $pi)) * 2.0 / 3.0;
    $ret += (20.0 * sin($y * $pi) + 40.0 * sin($y / 3.0 * $pi)) * 2.0 / 3.0;
    $ret += (160.0 * sin($y / 12.0 * $pi) + 320 * sin($y * $pi / 30.0)) * 2.0 / 3.0;
    return $ret;
}

function transformLon($x, $y)
{
    global $pi;
    $ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 0.1 * $x * $y + 0.1
        * sqrt(abs($x));
    $ret += (20.0 * sin(6.0 * $x * $pi) + 20.0 * sin(2.0 * $x * $pi)) * 2.0 / 3.0;
    $ret += (20.0 * sin($x * $pi) + 40.0 * sin($x / 3.0 * $pi)) * 2.0 / 3.0;
    $ret += (150.0 * sin($x / 12.0 * $pi) + 300.0 * sin($x / 30.0
                * $pi)) * 2.0 / 3.0;
    return $ret;
}

腾讯:逆地址解析(坐标位置描述)

https://lbs.qq.com/service/webService/webServiceGuide/webServiceGcoder

坐标转换: https://lbs.qq.com/service/webService/webServiceGuide/webServiceTranslate

坐标拾取器: https://lbs.qq.com/tool/getpoint/index.html

<?php

namespace MainModuleCommon;

use KIFCoreConfig;
use KIFCurl;
use KIFDataResultWrapper;

/**
 * 腾讯地图API
 */
class LbsQQ {

    const API = 'https://apis.map.qq.com';

    /**
     * 根据坐标 返回 地区信息
     * @param $lon
     * @param $lat
     * @return ResultWrapper
     * @throws Exception
     */
    static public function getAddressByLocation($lon, $lat){
        $api = '/ws/geocoder/v1/';
        $data = [
            'location' => $lat.','.$lon,
            'get_poi' => 0,
        ];
        $rs = self::request($api, $data);
        return $rs;
    }

    /**
     * 签名
     * @param $api
     * @param array $data
     * @return array
     * @throws Exception
     */
    static protected function sign($api, $data = []){
        $lbs = Config::getInstance()->get('lbs_qq');
        $app_id = $lbs['AppID'];
        $app_key = $lbs['AppKey'];
        $data['key'] = $app_id;
        //签名步骤一:按字典序排序参数
        ksort($data);
        //签名步骤二:生成签名字符串 在string后加入KEY
        $buffs = array();
        foreach ($data as $k => $v) {
            if($v===''){
                continue;
            }
            if(is_array($v)){
                $v = json_encode($v);
            }
            $buffs[] = $k.'='.$v;
        }
        $string = $api.'?'.implode('&', $buffs).$app_key;
        //签名步骤三:MD5加密
        $string = md5($string);
        $data['sig'] = $string;
        return $data;
    }


    /**
     * @param $api
     * @param $data
     * @return ResultWrapper
     * @throws Exception
     */
    static protected function request($api, $data){
        $data = self::sign($api, $data);
        $api = self::API.$api.'?'.http_build_query($data);
        $objCurl        = new Curl($api);
        $rs = $objCurl->get();
        if (!$rs){
            return ResultWrapper::fail('请求失败');
        }
        $rs = json_decode($rs, true);
        if ($rs['status']!==0){
            return ResultWrapper::fail('ERROR['.$rs['status'].']:'.$rs['message']);
        }
        return ResultWrapper::success($rs['result']);
    }
}