利用JSONP跨域获取天气数据

免费接口很少有一直比较稳定的,经过简单调查,这里选用了心知天气API,免费版:400次/小时,也就是9600次/天。国内城市数据,天气实况,3天预报,6项生活指数。这个API的免费版已经提供了很多年了,应该算最长寿稳定的那批API了……

心知天气支持的全球城市

根据官方文档,心知天气API不仅支持API密钥Key的验证方式,也支持更安全的签名验证方式。

使用签名验证方式是通过HMAC-SHA1,对请求参数加密后得到的签名字串进行身份验证,避免了将API密钥key明文包含在请求中而造成泄露。签名的生成方式如下:

1. 构造验证参数字符串。

将请求参数按照参数名字典升序排列后,把所有参数param=value&连接起来,即类似URI中Query string的构造方式。目前支持的参数有:UNIX时间戳 ts(单位为秒),签名失效时间 ttl(可选)和用户ID uid。构造好的参数字符串例如:ts=1443079775&ttl=30&uid=U123456789

2. 使用HMAC-SHA1方式,以API密钥(key)对上一步生成的参数字符串进行加密。

常见程序语言通常会内置加密函数,或通过扩展库提供支持。例如在NodeJS中,您可以使用crypto模块中的中的createHmac函数,例如crypto.createHmac("sha1", key)

3. 将上一步生成的加密结果用base64编码,并做一个urlencode,得到签名sig。

例:假设key为"secret",步骤(1)中的参数例子加密后得到的结果应为:dTYeoN8WdOfW4PiwgEdLa0gWFzo=,做完urlencode最终得到的签名sig为:dTYeoN8WdOfW4PiwgEdLa0gWFzo%3d

4. 将上一步得到的签名sig附在参数字符串之后,作为请求的一个参数发送。

上述例子里,请求参数即为:
ts=1443079775&ttl=30&uid=U123456789&sig=dTYeoN8WdOfW4PiwgEdLa0gWFzo%3d

注意:签名失效时间参数 ttl 是可选参数。如果忽略这个参数,生成的签名有效期默认为1800秒(30分钟)。较短的有效期可以使签名更难被盗用。请求中的其它参数,例如location,language,不参与签名。

使用JSONP方式调用

在网页中直接调用API接口,而不通过服务器中转。在请求中使用callback参数指定回调函数的名字,使用签名验证方式,通过 script 的方式调用。

Ajax 的核心是通过 XmlHttpRequest 获取非本页内容,而 jsonp 的核心则是动态添加 <script> 标签来调用服务器提供的 js 脚本。

例子:

<script type="text/javascript" src="https://api.thinkpage.cn/v3/weather/now.json?
    location=beijing&ts=1443079775&ttl=30&uid=[your_uid]&sig=[your_signature]&callback=showWeather"><script>

返回结果:

showWeather({ 
    "results": [{ 
        "location": {
            "id": "WX4FBXXFKE4F",
            "name": "北京",
            ......
});

附完整代码:

// 关联DOM,显示天气数据
var showWeather = function (data) {
    document.getElementById('wtxt').innerHTML = data.text;
    document.getElementById('loca').innerHTML = data.location;
    document.getElementById('temp').innerHTML = data.temperature;
    document.getElementById('weather').style.background 
            = '#00A6FF url("../' + data.code + '.png") 10px 0 no-repeat';
}
// 将jsonp返回的复杂对象精简为只包含所需信息的对象,并存入cookie(假设页面无其他cookie内容)
var convertWeatherObj = function (data) {
    var weather = {
        'location': data.results[0].location.name,
        'code': data.results[0].now.code,
        'text': data.results[0].now.text,
        'temperature': data.results[0].now.temperature
    };
    showWeather(weather);
    document.cookie="weather="+ JSON.stringify(weather) +"; path=/;";
}
// 构造验证参数字符串,发送jsonp请求(需要引用CryptoJS插件进行编码)
var getWeather = function () {
    var time = Math.round(new Date().getTime()/1000);
    var str = "ts=" + time + "&ttl=30&uid=UB93202969";
    var hash = CryptoJS.HmacSHA1(str, "vvjmsobm15dhmwcw");
    var base = hash.toString(CryptoJS.enc.Base64);
    var sig = encodeURIComponent(base);
    var url = "https://api.thinkpage.cn/v3/weather/now.json?
           location=ip&callback=convertWeatherObj&" + str + "&sig=" + sig;
    var script = document.createElement('script');
    script.setAttribute('src', url);
    document.getElementsByTagName('body')[0].appendChild(script);
}
// 当前页面有cookie,则不再发送请求
if (document.cookie != '') {
    var objStr = document.cookie.substring(8);
    var weatherObj = JSON.parse(objStr);
    showWeather(weatherObj);
} else {
    getWeather();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,323评论 19 139
  • iOS网络架构讨论梳理整理中。。。 其实如果没有APIManager这一层是没法使用delegate的,毕竟多个单...
    yhtang阅读 10,652评论 1 23
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 13,850评论 6 13
  • 要么读书要么旅行,身体和心灵总要有个在路上。巧的是我以前既不喜欢读书,也不喜欢旅行。不喜欢读书,是因为大部分空闲时...
    _嗟乎阅读 2,144评论 0 0
  • 说明1:标准应用程序包括3类标准段空间:.text运行代段;.data全局变量等具有初始值的数据空间;.bss暂态...
    three_eyelid阅读 1,358评论 0 2