QqMapHelper.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <?php
  2. namespace common\helpers\map;
  3. use common\helpers\CurlHelper;
  4. use Yii;
  5. class QqMapHelper
  6. {
  7. const HOST = 'https://apis.map.qq.com'; // 请求域名
  8. const TYPE_WS = '/ws/'; // api请求类型
  9. const KEY = 'GKRBZ-GJSKB-DASUY-N7XDN-3SNI7-KHFCK'; // 腾讯地图key
  10. const SECRET = 'cmQJc7AVEhc3FNoZfSX6WrTvL72Ycf0e'; // 签名密钥
  11. /**
  12. * 腾讯地图key
  13. *
  14. * @var string
  15. */
  16. protected static $key = '';
  17. /**
  18. * 签名密钥
  19. *
  20. * @var string
  21. */
  22. protected static $secret = '';
  23. /**
  24. * 获取腾讯地图配置
  25. *
  26. * @return void
  27. */
  28. protected static function getQQMapConfig()
  29. {
  30. $config = Yii::$app->services->setting->platform->get('map');
  31. self::$key = $config['qq_jsapi_key'] ? $config['qq_jsapi_key'] : self::KEY;
  32. self::$secret = $config['qq_jsapi_secret'] ? $config['qq_jsapi_secret'] : self::SECRET;
  33. }
  34. /**
  35. * 地址解析(由文字地址到经纬度的转换能力,并同时提供结构化的省市区地址信息)
  36. * @Author: lun
  37. * @DateTime: 2023/7/20 0020 14:13
  38. * @Copyright: copyright (c) 2021 广东七件事集团
  39. * @param $address
  40. * @return mixed
  41. */
  42. public static function Geocoder($address)
  43. {
  44. static::getQQMapConfig();
  45. $require = self::TYPE_WS . 'geocoder/v1';
  46. $url = self::HOST . $require;
  47. $params['address'] = $address;
  48. $params['key'] = self::$key;
  49. $params['sig'] = self::getSign($require, $params);
  50. $response = CurlHelper::get($url, $params);
  51. return $response;
  52. }
  53. /**
  54. * 经纬度转为地址
  55. * @Author: lun
  56. * @DateTime: 2023/7/21 0021 14:36
  57. * @Copyright: copyright (c) 2021 广东七件事集团
  58. * @param $latitude
  59. * @param $longitude
  60. * @return mixed
  61. */
  62. public static function ReverseGeocoder($latitude, $longitude)
  63. {
  64. static::getQQMapConfig();
  65. $require = self::TYPE_WS . 'geocoder/v1';
  66. $url = self::HOST . $require;
  67. $params['location'] = $latitude . ',' . $longitude;
  68. // $params['get_poi'] = 1;
  69. $params['key'] = self::$key;
  70. $params['sig'] = self::getSign($require, $params);
  71. $response = CurlHelper::get($url, $params);
  72. return $response;
  73. }
  74. /**
  75. * 周边搜索(作用于店铺)
  76. * 示例:https://apis.map.qq.com/ws/place/v1/explore?boundary=nearby(40.040394,116.273523,1000)&policy=1&page_size=10&page_index=1&key=OB4BZ-D4W3U-*****
  77. * @Author:lun
  78. * @Date:2025-01-14 14:13
  79. * @Copyright:copyright(c)2024 广东七件事集团
  80. * @param $latitude
  81. * @param $longitude
  82. * @param $radius
  83. * @param $auto_extend
  84. * @return mixed
  85. */
  86. public static function explore($latitude, $longitude, $radius = 500, $auto_extend = 1)
  87. {
  88. static::getQQMapConfig();
  89. $require = self::TYPE_WS . 'place/v1/explore';
  90. $url = self::HOST . $require;
  91. $params['boundary'] = "nearby({$latitude},{$longitude},{$radius},{$auto_extend})";
  92. $params['key'] = self::$key;
  93. $params['sig'] = self::getSign($require, $params);
  94. // 对所有参数进行URL编码
  95. foreach ($params as $key => $value) {
  96. $params[$key] = urlencode($value);
  97. }
  98. $response = CurlHelper::get($url, $params, ['x-legacy-url-decode' => 'no']);
  99. $data['result'] = $response['data'] ?? [];
  100. return $data;
  101. }
  102. /**
  103. * 周边搜索(作用于路标,此功能相对实用)
  104. * @Author:lun
  105. * @Date:2025-01-14 16:27
  106. * @Copyright:copyright(c)2024 广东七件事集团
  107. * @param $latitude
  108. * @param $longitude
  109. * @param $radius
  110. * @param $auto_extend
  111. * @return array|mixed
  112. */
  113. public static function here($latitude, $longitude, $radius = 1000, $auto_extend = 1)
  114. {
  115. static::getQQMapConfig();
  116. $require = self::TYPE_WS . 'place/v1/here';
  117. $url = self::HOST . $require;
  118. $params['boundary'] = "nearby({$latitude},{$longitude},{$radius},{$auto_extend})";
  119. $params['key'] = self::$key;
  120. $params['sig'] = self::getSign($require, $params);
  121. // 对所有参数进行URL编码
  122. foreach ($params as $key => $value) {
  123. $params[$key] = urlencode($value);
  124. }
  125. $response = CurlHelper::get($url, $params, ['x-legacy-url-decode' => 'no']);
  126. $data['result'] = $response['data'] ?? [];
  127. return $data;
  128. }
  129. /**
  130. * 根据ip获取定位
  131. * @Author: lun
  132. * @DateTime: 2023/7/20 0020 14:43
  133. * @Copyright: copyright (c) 2021 广东七件事集团
  134. * @param $ip
  135. * @return mixed
  136. */
  137. public static function Iplocation($ip)
  138. {
  139. static::getQQMapConfig();
  140. $require = self::TYPE_WS . 'location/v1/ip';
  141. $url = self::HOST . $require;
  142. $params['address'] = $ip;
  143. $params['key'] = self::$key;
  144. $params['sig'] = self::getSign($require, $params);
  145. $response = CurlHelper::get($url, $params);
  146. return $response;
  147. }
  148. /**
  149. * 生成get请求签名
  150. * @Author: lun
  151. * @DateTime: 2023/7/20 0020 11:44
  152. * @Copyright: copyright (c) 2021 广东七件事集团
  153. * @param $require
  154. * @param array $params
  155. * @return string
  156. */
  157. public static function getSign($require, array $params)
  158. {
  159. $str = $require . '?';
  160. ksort($params); // 对键进行升序排序
  161. foreach ($params as $key => $value) {
  162. $str .= $key . '=' . $value . '&';
  163. }
  164. $str = trim($str, '&') . self::$secret;
  165. return strtolower(md5($str));
  166. }
  167. /**
  168. * 获取距离经纬度最近的地标
  169. * @Author:lun
  170. * @Date:2025-01-14 17:44
  171. * @Copyright:copyright(c)2024 广东七件事集团
  172. * @param $latitude
  173. * @param $longitude
  174. * @return array|mixed
  175. */
  176. public static function getNearPlace($latitude, $longitude)
  177. {
  178. $places = self::here($latitude, $longitude);// 获取附近的地点
  179. $current_distance = 0;// 当前距离
  180. $min_key = 0;// 最小距离的key
  181. if (!empty($places['result'])) {
  182. // 腾讯接口返回的_distance(与boundary传入的经纬度的距离,单位:米)参数距离不准确,所以需要重新计算
  183. foreach ($places['result'] as $key => $place) {
  184. $distance = self::getDistance($latitude, $longitude, $place['location']['lat'], $place['location']['lng']);
  185. if ($key == 0) {
  186. $current_distance = $distance;
  187. $min_key = $key;
  188. } else {
  189. if ($distance < $current_distance) {
  190. $current_distance = $distance;// 取最小的
  191. $min_key = $key;
  192. }
  193. }
  194. }
  195. }
  196. return $places['result'][$min_key] ?? [];
  197. }
  198. /**
  199. * 计算两个经纬度之间的距离,单位:米
  200. * @Author:lun
  201. * @Date:2025-01-14 16:29
  202. * @Copyright:copyright(c)2024 广东七件事集团
  203. * @param $lat1
  204. * @param $lon1
  205. * @param $lat2
  206. * @param $lon2
  207. * @return float|int
  208. */
  209. public static function getDistance($lat1, $lon1, $lat2, $lon2) {
  210. $R = 6371000; // 地球半径,单位为米
  211. // 将角度转换为弧度
  212. $lat1 = deg2rad($lat1);
  213. $lon1 = deg2rad($lon1);
  214. $lat2 = deg2rad($lat2);
  215. $lon2 = deg2rad($lon2);
  216. // 计算纬度和经度的差值
  217. $dlat = $lat2 - $lat1;
  218. $dlon = $lon2 - $lon1;
  219. // 哈弗赛因公式
  220. $a = sin($dlat/2) * sin($dlat/2) + cos($lat1) * cos($lat2) * sin($dlon/2) * sin($dlon/2);
  221. $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
  222. // 计算距离
  223. $distance = $R * $c;
  224. return $distance;
  225. }
  226. }