免費接口很少有一直比較穩定的,經過簡單調查,這里選用了心知天氣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();
}