调用腾讯地图 WebService 跨域踩坑记

最近需要使用腾讯地图 WebService 的搜索服务,使用关键字查找符合条件的位置。

所有的腾讯地图开发者都配置完毕,官方说是支持 Get 和 Jsonp 的请求方式,但是前端调用接口的时候却是频频报错。

为此我还在腾讯地图开发者论坛发布了相关的帖子,结果也没什么回应,最终的解决方案为后端调用。

搜索服务官方说明文档: http://lbs.qq.com/webservice_v1/guide-suggestion.html

接口为:https://apis.map.qq.com/ws/place/v1/suggestion

必传参数有:

  • keyword 搜索关键字
  • region 搜索范围
  • key 开发者key

初次尝试:axios

本人前端使用的是 Vue,安装了 axios,因此请求最方便的就是 axios:

axios.get(`https://apis.map.qq.com/ws/place/v1/suggestion?
keyword=${this.searchWord}&region=${this.region}&key=${this.mapKey}`).then(res => {
  console.log(res)
})
1
2
3
4

结果,控制台报了一个错

Uncaught (in promise) Error: Network Error
1

然后,我打开 Network 看请求的内容,发现只发送了一个 OPTIONS 请求,返回的状态码是200,但 responseText却是:

{status: 407, message: "不被支持的请求方法"}
1

结果,没有发送 GET 请求,由于 axios 实现 CORS 的时候回先发一个 OPTIONS 请求,而这个接口不支持 OPTIONS 请求,接下来的 GET 请求也就不会继续发送。

参考:http://www.ruanyifeng.com/blog/2016/04/cors.html

再次尝试:jquery.get

好吧,既然 axios 会发送 OPTIONS 请求,那我就不用 axios 好了,就试了试 jquery:

$.get(`https://apis.map.qq.com/ws/place/v1/suggestion?keyword=${this.searchWord}&region=${this.formData.transit_from_detail.from}&key=${this.mapKey}`,
res => {
  console.log(res)
  this.searchList = res
})
1
2
3
4
5

结果,控制台直接报跨域:

Failed to load https://apis.map.qq.com/ws/place/v1/suggestion?keyword=0&region=%E6%A5%9A%E9%9B%84&key=XXXXXX: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
1

直接在浏览器中输入URL可以输出结果,说明接口是没错的,传递的数据也正确。

最后尝试:jsonp

好吧,看来 ajax 请求是行不通了,那就试试 jsonp 吧。

不想使用 jquery 的 jsonp,就专门下载了一个 jsonp 的库:

yarn add jsonp
1

使用起来很简单:

import jsonp from 'jsonp'
...

jsonp(`https://apis.map.qq.com/ws/place/v1/suggestion?
keyword=${this.searchWord}&region=${this.formData.transit_from_detail.from}&key=${this.mapKey}`, null, (err, data) => {
  if (err) {
    console.error(err.message)
  } else {
    console.log(data)
  }
})
1
2
3
4
5
6
7
8
9
10
11

结果,报了个 Unexpected token : 的错误。

打开 Network 看了下,返回的是一个 json,并没有用 callback 包装返回,因此出错。看样子,腾讯地图 API 也是够了,接口做到这份上。

参考:

https://blog.csdn.net/m0_38082783/article/details/73331602

https://blog.csdn.net/qq_31915745/article/details/72867784

后端解决

前端没辙了,只能用后端的解决方案了:

<?php
namespace app\tmap\controller;

class Index
{
  public function index()
  {
    $key = $_GET['key'];
    $region = $_GET['region'];
    $keyword = $_GET['keyword'];
    $url = 'https://apis.map.qq.com/ws/place/v1/suggestion?keyword='.$keyword.'&key='.$key.'&region='.$region;
    $data = curl_get_contents($url);
    return json_decode($data);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

前端再次调用接口测试:

this.axiosBaseApi.get(`/tmap?keyword=${this.searchWord}&region=${this.formData.transit_from_detail.from}&key=${this.mapKey}`).then(res => {
  console.log(res)
})
1
2
3

这下终于没问题了,返回

{"status":0,"message":"query ok","count":10,"data":[{"id":"3027664732897233347","title":"古风驿站","address":"云南省楚雄彝族自治州楚雄市土司府斜对面","category":"旅游景点:风景名胜","type":0,"location":{"lat":25.05641,"lng":101.51787},"adcode":532301,"province":"云南省","city":"楚雄彝族自治州","district":"楚雄市"},{"id":"11638730082929375227","title":"银帆酒店","address":"云南省楚雄彝族自治州楚雄市小庙东区商铺D153","category":"酒店宾馆:旅馆招待所","type":0,"location":{"lat":25.06146,"lng":101.52207},"adcode":532301,"province":"云南省","city":"楚雄彝族自治州","district":"楚雄市"}],"request_id":"1437989316977476096"}
1

总结:腾讯地图 API 做得真是够烂的,而在微信中开发应用有很多限制,要接入微信城市服务还必须得使用腾讯地图!

MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress | Hosted by Coding Pages