和风天气官方没有C#版本的签名生成算法,自己写了个。
需要使用NuGet安装Newtonsoft.Json。
/// <summary>
/// 和风天气签名生成算法-C#版本
/// </summary>
/// <param name="parameters"></param>
/// <param name="secret">和风天气用户key</param>
/// <returns></returns>
public static string GetSignature(IDictionary<string, string> parameters, string secret)
{
// 先将参数以其参数名的字典序升序进行排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
IEnumerator<KeyValuePair<string, string>> iterator = sortedParams.GetEnumerator();
// 遍历排序后的字典,将所有参数按"key=value"格式拼接在一起
StringBuilder basestring = new StringBuilder();
while (iterator.MoveNext())
{
string key = iterator.Current.Key;
string value = iterator.Current.Value;
if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(value))
{
basestring.Append(key).Append("=").Append(value).Append("&");
}
}
//移除字符串中最后一个"&" 并拼接key
string unencryptedSign = RemoveLastChar(basestring.ToString(), "&")+ secret;
// 使用MD5对待签名串求签
MD5 md5 = MD5.Create();
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(unencryptedSign));
//base64转码
string result = Convert.ToBase64String(bytes);
return result.ToString();
}
/// <summary>
/// 移除字符串末尾指定字符
/// </summary>
/// <param name="str">需要移除的字符串</param>
/// <param name="value">指定字符</param>
/// <returns>移除后的字符串</returns>
public static string RemoveLastChar(string str, string value)
{
int _finded = str.LastIndexOf(value);
if (_finded != -1)
{
return str.Substring(0, _finded);
}
return str;
}
/// <summary>
/// 加密签名认证方式获取json数据
/// </summary>
/// <param name="location"></param>
/// <param name="id"></param>
/// <param name="key"></param>
/// <param name="type"></param>
/// <param name="paid"></param>
/// <returns></returns>
public static JToken GetJToken(string location, string id, string key, ApiType type, bool paid)
{
string timestamp = DateTimeHelper.DateTimeToStamp(DateTime.Now).ToString();
IDictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("location", location);
parameters.Add("username", id);
parameters.Add("t", timestamp);
string sign = GetSignature(parameters, key);
string httpUrl = string.Format(GetApiUrl(type, paid) + "location={0}&username={1}&t={2}&sign={3}", location, id, timestamp, sign);
string jsonStr = WeatherRequest(httpUrl);
JToken token = JObject.Parse(jsonStr)["HeWeather6"][0] as JToken; //转换为JToken
return token;
}
/// <summary>
/// 天气数据类型
/// </summary>
public enum ApiType
{
/// <summary>
/// 城市
/// </summary>
City,
/// <summary>
/// 常规天气数据集合
/// </summary>
Weather,
/// <summary>
/// 实况天气
/// </summary>
WeatherNow,
/// <summary>
/// 逐小时预报
/// </summary>
WeatherHourly,
/// <summary>
/// 3-10天天气预报
/// </summary>
WeatherForecast,
/// <summary>
/// 生活指数
/// </summary>
LifeStyle,
/// <summary>
/// 空气质量数据集合
/// </summary>
Air,
/// <summary>
/// 日出日落
/// </summary>
Sun,
}
/// <summary>
/// 获取API URL
/// </summary>
/// <param name="type">API类型</param>
/// <param name="isPaid">是否付费</param>
/// <returns></returns>
public static string GetApiUrl(ApiType type, bool isPaid)
{
string httpUrl = "";
if(isPaid)
httpUrl = "https://api.heweather.com/s6/";
else
httpUrl = "https://free-api.heweather.com/s6/";
string apiUrl = "";
switch (type)
{
case ApiType.City:
apiUrl = "https://search.heweather.com/find?";
break;
case ApiType.Weather:
apiUrl = httpUrl + "weather?";
break;
case ApiType.WeatherNow:
apiUrl = httpUrl + "weather/now?";
break;
case ApiType.WeatherHourly:
apiUrl = httpUrl + "weather/hourly?";
break;
case ApiType.WeatherForecast:
apiUrl = httpUrl + "weather/forecast?";
break;
case ApiType.LifeStyle:
apiUrl = httpUrl + "weather/lifestyle?";
break;
case ApiType.Air:
apiUrl = "https://api.heweather.com/s6/air?parameters";
break;
case ApiType.Sun:
apiUrl = httpUrl + "solar/sunrise-sunset?";
break;
}
return apiUrl;
}