中國氣象局面向網絡媒體、手機廠商、第三方氣象服務機構等用戶,經過 web 方式提供數據氣象服務的官方載體。web
在一週前已經申請到appid,可是苦於沒有C#版的key 的算法,一直驗證不經過,通過幾天查詢資料,如今提供一份C#版的HMAC-SHA1的加密算法算法
比較簡單,分項給你們,你們能夠參考一下。json
string GetKey(string appid, string privateKey, string areaId, string date, string type) { //使用SHA1的HMAC HMAC hmac = HMACSHA1.Create(); var publicKey = "http://webapi.weather.com.cn/data/?areaid={0}&type={1}&date={2}&appid={3}"; var data = System.Text.Encoding.UTF8.GetBytes(string.Format(publicKey, areaId, type, date, appid)); //密鑰 var key = System.Text.Encoding.UTF8.GetBytes(privateKey); hmac.Key = key; //對數據進行簽名 var signedData = hmac.ComputeHash(data); return Convert.ToBase64String(signedData); }
類型和接口已經修改,請看最新的代碼:api
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; //項目添加System.Runtime.Serialization引用 using System.Runtime.Serialization.Json; using System.Security.Cryptography; using System.Web; namespace MvcApplication1 { public class Weather { //天氣編碼對應表 private Dictionary<string, string> weatherInfo = new Dictionary<string, string>(); //風力編碼對應表 private Dictionary<string, string> WindInfo = new Dictionary<string, string>(); //風力方向對應表 private Dictionary<string, string> WindInfoDir = new Dictionary<string, string>(); private DataContractJsonSerializer ser; private byte[] buff = new byte[5 * 1024]; public Weather() { #region 初始化編碼表 weatherInfo.Add("00", "晴"); weatherInfo.Add("01", "多雲"); weatherInfo.Add("02", "陰"); weatherInfo.Add("03", "陣雨"); weatherInfo.Add("04", "雷陣雨"); weatherInfo.Add("05", "雷陣雨伴有冰雹"); weatherInfo.Add("06", "雨夾雪"); weatherInfo.Add("07", "小雨"); weatherInfo.Add("08", "中雨"); weatherInfo.Add("09", "大雨"); weatherInfo.Add("10", "暴雨"); weatherInfo.Add("11", "大暴雨"); weatherInfo.Add("12", "特大暴雨"); weatherInfo.Add("13", "陣雪"); weatherInfo.Add("14", "小雪"); weatherInfo.Add("15", "中雪"); weatherInfo.Add("16", "大雪"); weatherInfo.Add("17", "暴雪"); weatherInfo.Add("18", "霧"); weatherInfo.Add("19", "凍雨"); weatherInfo.Add("20", "沙塵暴"); weatherInfo.Add("21", "小到中雨"); weatherInfo.Add("22", "中到大雨"); weatherInfo.Add("23", "大到暴雨"); weatherInfo.Add("24", "暴雨到大暴雨"); weatherInfo.Add("25", "大暴雨到特大暴雨"); weatherInfo.Add("26", "小到中雪"); weatherInfo.Add("27", "中到大雪"); weatherInfo.Add("28", "大到暴雪"); weatherInfo.Add("29", "浮塵"); weatherInfo.Add("30", "揚沙"); weatherInfo.Add("31", "強沙塵暴"); weatherInfo.Add("53", "霧霾"); weatherInfo.Add("99", "無"); WindInfoDir.Add("0", "無持續風向"); WindInfoDir.Add("1", "東北風"); WindInfoDir.Add("2", "東風"); WindInfoDir.Add("3", "東南風"); WindInfoDir.Add("4", "南風"); WindInfoDir.Add("5", "西南風"); WindInfoDir.Add("6", "西風"); WindInfoDir.Add("7", "西北風"); WindInfoDir.Add("8", "北風"); WindInfoDir.Add("9", "旋轉風"); WindInfo.Add("0", "微風"); WindInfo.Add("1", "3-4級"); WindInfo.Add("2", "4-5級"); WindInfo.Add("3", "5-6級"); WindInfo.Add("4", "6-7級"); WindInfo.Add("5", "7-8級"); WindInfo.Add("6", "8-9級"); WindInfo.Add("7", "9-10級"); WindInfo.Add("8", "10-11級"); WindInfo.Add("9", "11-12級"); #endregion ser = new DataContractJsonSerializer(typeof(WeatherJson)); } public void RefreshWeather() { bool update = false; //string baseurl = ""; string baseurl = "http://open.weather.com.cn/data/?areaid={0}&type={1}&date={2}&appid={3}"; var cityCode = "101180901"; //指數:index_f(基礎接口);index_v(常規接口) 3天預報:forecast_f(基礎接口);forecast_v(常規接口) var weatherType = "forecast_f"; var appID = "appID"; var private_key = "private_key"; string url = GetSmartWeatherApi(baseurl, cityCode, weatherType, DateTime.Now.ToString("yyyyMMddHHmm"), appID, private_key); int l = 0; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.UserAgent = @"Mozilla/5.0 (Windows; U; Windows NT 6.0; zh-CN; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4"; //從指定的URL中獲取天氣信息(JSON數據) HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream rs = response.GetResponseStream(); l = rs.Read(buff, 0, buff.Length); rs.Close(); } catch (Exception ex) { //網絡鏈接失敗; } //反序列化爲實體 var mStream = new MemoryStream(buff, 0, l); WeatherJson w; try { w = (WeatherJson)ser.ReadObject(mStream); if (w != null) { foreach (var item in w.f.f1) { item.fa_des = weatherInfo.ContainsKey(item.fa) ? weatherInfo[item.fa] : string.Empty; item.fb_des = weatherInfo.ContainsKey(item.fb) ? weatherInfo[item.fb] : string.Empty; item.fe_des = WindInfoDir.ContainsKey(item.fe) ? WindInfoDir[item.fe] : string.Empty; item.ff_des = WindInfoDir.ContainsKey(item.ff) ? WindInfoDir[item.ff] : string.Empty; item.fg_des = WindInfo.ContainsKey(item.fg) ? WindInfo[item.fg] : string.Empty; item.fh_des = WindInfo.ContainsKey(item.fh) ? WindInfo[item.fh] : string.Empty; } } } catch (System.Runtime.Serialization.SerializationException) { //反序列化失敗 throw; } //獲取天氣預報 foreach (var item in w.f.f1) { string weather = (item.fa == item.fb) ? item.fa_des : item.fa_des + "轉" + item.fb_des; string temperature = item.fc + "℃ ~ " + item.fd + "℃"; string wind = item.fg == "0" ? item.fg_des : item.fe_des + " " + item.fg_des; } } private string GetSmartWeatherApi(string _baseUrl, string _areaId, string _type, string _date, string _appID, string _privateKey) { string publicKey = string.Format(_baseUrl, _areaId, _type, _date, _appID); string fullUrl = string.Format(_baseUrl, _areaId, _type, _date, _appID.Substring(0, 6)); fullUrl = string.Format("{0}&key={1}", fullUrl, GetSmartWeatherKeyCode(publicKey, _privateKey)); return fullUrl; } private string GetSmartWeatherKeyCode(string _publicKey, string _privateKey) { //使用SHA1的HMAC HMAC hmac = HMACSHA1.Create(); Byte[] data = System.Text.Encoding.UTF8.GetBytes(_publicKey); //密鑰 Byte[] key = System.Text.Encoding.UTF8.GetBytes(_privateKey); hmac.Key = key; //對數據進行簽名 var signedData = hmac.ComputeHash(data); string keyCode = Convert.ToBase64String(signedData); keyCode = System.Web.HttpUtility.UrlEncode(keyCode); return keyCode; } } #region 天氣實體類,用於獲取氣象局json數據反序列化 public class WeatherJson { /// <summary> /// 城市 /// </summary> public WeatherC c { get; set; } /// <summary> /// 預報 /// </summary> public WeatherF f { get; set; } /// <summary> /// 實況 /// </summary> public WeatherL l { get; set; } /// <summary> /// 指數 /// </summary> public WeatherI i { get; set; } } /// <summary> /// 實況,type=observe /// 示例: /// "l":{ /// "l1":8" /// "l2":"38" /// "l3":"6" /// "l4":"3" /// "l7":"11:00" /// } /// </summary> public class WeatherL { /// <summary> /// 當前溫度(攝氏度) /// </summary> public string l1 { get; set; } /// <summary> /// 當前溼度(單位%) /// </summary> public string l2 { get; set; } /// <summary> /// 當前風力(單位是級,無需根據風力編碼表取值,直接顯示便可) /// </summary> public string l3 { get; set; } /// <summary> /// 當前風向編號 /// </summary> public string l4 { get; set; } /// <summary> /// 實況發佈時間 /// </summary> public string l7 { get; set; } } /// <summary> /// 指數,type=index /// 示例: /// "i":[ /// { /// "i1":"ct", /// "i2":"穿衣指數", /// "i3":"" , /// "i4":"熱」, /// "i5":"天氣熱,建議着短裙、短褲、短薄外套、T 恤等夏季服裝。" /// }, /// ] /// </summary> public class WeatherI { /// <summary> /// 指數簡稱 /// </summary> public string i1 { get; set; } /// <summary> /// 指數中文名稱 /// </summary> public string i2 { get; set; } /// <summary> /// 指數中文別名 /// </summary> public string i3 { get; set; } /// <summary> /// 指數級別 /// </summary> public string i4 { get; set; } /// <summary> /// 指數內容 /// </summary> public string i7 { get; set; } } /// <summary> /// 預報,城市信息,type=forecast3d /// </summary> public class WeatherC { /// <summary> /// 區域 ID /// </summary> public string c1 { get; set; } /// <summary> /// 城市英文名 /// </summary> public string c2 { get; set; } /// <summary> /// 城市英文名 /// </summary> public string c3 { get; set; } /// <summary> /// 城市所在市英文名 /// </summary> public string c4 { get; set; } /// <summary> /// 城市所在市中文名 /// </summary> public string c5 { get; set; } /// <summary> /// 城市所在省英文名 /// </summary> public string c6 { get; set; } /// <summary> /// 城市所在省中文名 /// </summary> public string c7 { get; set; } /// <summary> /// 城市所在國家英文名 /// </summary> public string c8 { get; set; } /// <summary> /// 城市所在國家中文名 /// </summary> public string c9 { get; set; } /// <summary> /// 城市級別 /// </summary> public string c10 { get; set; } /// <summary> /// 城市區號 /// </summary> public string c11 { get; set; } /// <summary> /// 城市區號 /// </summary> public string c12 { get; set; } /// <summary> /// 經度 /// </summary> public string c13 { get; set; } /// <summary> /// 緯度 /// </summary> public string c14 { get; set; } /// <summary> /// 海拔 /// </summary> public string c15 { get; set; } /// <summary> /// 雷達站號 /// </summary> public string c16 { get; set; } } /// <summary> /// 預報,type=forecast3d /// </summary> public class WeatherF { /// <summary> /// 預報發佈時間 /// </summary> public string f0 { get; set; } /// <summary> /// 3天的天氣預報 /// </summary> public WeatherF1[] f1 { get; set; } } public class WeatherF1 { /// <summary> /// 白每天氣現象編號 /// </summary> public string fa { get; set; } public string fa_des { get; set; } /// <summary> /// 晚上天氣現象編號 /// </summary> public string fb { get; set; } public string fb_des { get; set; } /// <summary> /// 白每天氣溫度(攝氏度) /// </summary> public string fc { get; set; } /// <summary> /// 晚上天氣溫度(攝氏度) /// </summary> public string fd { get; set; } /// <summary> /// 白天風向編號 /// </summary> public string fe { get; set; } public string fe_des { get; set; } /// <summary> /// 晚上風向編號 /// </summary> public string ff { get; set; } public string ff_des { get; set; } /// <summary> /// 白天風力編號 /// </summary> public string fg { get; set; } public string fg_des { get; set; } /// <summary> /// 晚上風力編號 /// </summary> public string fh { get; set; } public string fh_des { get; set; } /// <summary> /// 日出日落時間(中間用|分割) /// </summary> public string fi { get; set; } } #endregion }