免费接口很少有一直比较稳定的,经过简单调查,这里选用了心知天气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();
}