前一段時間公司有個項目需要用到短信通知,然後我買了個阿里雲的短信進行短信接口的開發。但是項目是在XP系統上運行所以項目必須是.net3.5的框架才行,但是阿里給出的短信dll只能在.net4.0及其以上版本使用,這就很尷尬了,幸好阿里給出了關於http的java例子,於是我照着java代碼試着寫出了C#調用阿里雲http的方法。言歸正傳,上代碼!!!
public class SendShort
{
/// <summary>
/// 短信接口C#調用方法
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string GetHtmlFormUrl(string url)
{
string strRet = null;
if (url == null || url.Trim().ToString() == "")
{
return strRet;
}
string targeturl = url.Trim().ToString();
try
{
HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(targeturl);
hr.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
hr.Method = "GET";
hr.Timeout = 30 * 60 * 1000;
WebResponse hs = hr.GetResponse();
Stream sr = hs.GetResponseStream();
StreamReader ser = new StreamReader(sr, Encoding.Default);
strRet = MessageHandle(ser.ReadToEnd());
}
catch (Exception ex)
{
strRet = "短信發送失敗!"+ex.Message;
}
return strRet;
}
/// <summary>
/// 驗證手機號碼是否合法
/// </summary>
/// <param name="str_handset"></param>
/// <returns></returns>
public static bool IsHandset(string str_handset)
{
return System.Text.RegularExpressions.Regex.IsMatch(str_handset, @"^1[3|4|5|7|8][0-9]\d{8}$");
}
/// <summary>
/// 短信驗證碼
/// </summary>
/// <param name="mobile"></param>
/// <param name="code"></param>
/// <returns></returns>
public static string SignDemo(string mobile, int code)
{
string accessKeyId = "你的accessKeyId ";
string accessSecret = "你的accessSecret ";
string nowDate = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'");//GTM時間
Dictionary<string, string> keyValues = new Dictionary<string, string>();//聲明一個字典
//1.系統參數
keyValues.Add("SignatureMethod", "HMAC-SHA1");
keyValues.Add("SignatureNonce", Guid.NewGuid().ToString());
keyValues.Add("AccessKeyId", accessKeyId);
keyValues.Add("SignatureVersion", "1.0");
keyValues.Add("Timestamp", nowDate);
keyValues.Add("Format", "Json");//可換成xml
//2.業務api參數
keyValues.Add("Action", "SendSms");
keyValues.Add("Version", "2017-05-25");
keyValues.Add("RegionId", "cn-hangzhou");
keyValues.Add("PhoneNumbers", mobile);
keyValues.Add("SignName", "你的簽名");
keyValues.Add("TemplateParam", "{\"code\":\"" + code + "\"}");
keyValues.Add("TemplateCode", "你的模板編號");
keyValues.Add("OutId", "123");
//3.去除簽名關鍵字key
if (keyValues.ContainsKey("Signature"))
{
keyValues.Remove("Signature");
}
//4.參數key排序
Dictionary<string, string> ascDic = keyValues.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value.ToString());
//5.構造待簽名的字符串
StringBuilder builder = new StringBuilder();
foreach (var item in ascDic)
{
if (item.Key == "SignName")
{
}
else
{
builder.Append("&").Append(specialUrlEncode(item.Key)).Append("=").Append(specialUrlEncode(item.Value));
}
if (item.Key == "RegionId")
{
builder.Append("&").Append(specialUrlEncode("SignName")).Append("=").Append(specialUrlEncode(keyValues["SignName"]));
}
}
string sorteQueryString = builder.ToString().Substring(1);
StringBuilder stringToSign = new StringBuilder();
stringToSign.Append("GET").Append("&");
stringToSign.Append(specialUrlEncode("/")).Append("&");
stringToSign.Append(specialUrlEncode(sorteQueryString));
string Sign = MySign(accessSecret + "&", stringToSign.ToString());
//6.簽名最後也要做特殊URL編碼
string signture = specialUrlEncode(Sign);
//最終打印出合法GET請求的URL
string url = "http://dysmsapi.aliyuncs.com/?Signature=" + signture + builder;
string result = GetHtmlFormUrl(url);
return result;
}
/// <summary>
/// URL編碼
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string specialUrlEncode(string temp)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < temp.Length; i++)
{
string t = temp[i].ToString();
string k = HttpUtility.UrlEncode(t, Encoding.UTF8);
if (t == k)
{
stringBuilder.Append(t);
}
else
{
stringBuilder.Append(k.ToUpper());
}
}
return stringBuilder.ToString().Replace("+", "%20").Replace("*", "%2A").Replace("%7E", "~");
}
/// <summary>
/// HMACSHA1簽名
/// </summary>
/// <param name="accessSecret"></param>
/// <param name="stringToSign"></param>
/// <returns></returns>
public static string MySign(string accessSecret, string stringToSign)
{
try
{
var hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(accessSecret));
var dataBuffer = Encoding.UTF8.GetBytes(stringToSign);
var hashBytes = hmacsha1.ComputeHash(dataBuffer);
string stringbyte = BitConverter.ToString(hashBytes, 0).Replace("-", string.Empty).ToLower();
byte[] bytes = strToToHexByte(stringbyte);
return Convert.ToBase64String(bytes);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 字符串轉16進制字節數組
/// </summary>
/// <param name="hexString"></param>
/// <returns></returns>
private static byte[] strToToHexByte(string hexString)
{
hexString = hexString.Replace(" ", "");
if ((hexString.Length % 2) != 0)
hexString += " ";
byte[] returnBytes = new byte[hexString.Length / 2];
for (int i = 0; i < returnBytes.Length; i++)
returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return returnBytes;
}
/// <summary>
/// 消息處理機制
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static string MessageHandle(string str)
{
MessageModel message = JsonConvert.DeserializeObject<MessageModel>(str);
string result = "";
switch (message.Code)
{
case "OK":
result = "短信發送成功!";
break;
case "isp.RAM_PERMISSION_DENY":
result = "RAM權限DENY";
break;
case "isv.OUT_OF_SERVICE":
result = "業務停機";
break;
case "isv.PRODUCT_UN_SUBSCRIPT":
result = "未開通雲通信產品的阿里雲客戶";
break;
case "isv.PRODUCT_UNSUBSCRIBE":
result = "產品未開通";
break;
case "isv.ACCOUNT_NOT_EXISTS":
result = "賬戶不存在";
break;
case "isv.ACCOUNT_ABNORMAL":
result = "賬戶異常 ";
break;
case "isv.SMS_TEMPLATE_ILLEGAL":
result = "短信模板不合法";
break;
case "isv.SMS_SIGNATURE_ILLEGAL":
result = "短信簽名不合法";
break;
case "isv.INVALID_PARAMETERS":
result = "參數異常";
break;
case "isv.MOBILE_NUMBER_ILLEGAL":
result = "非法手機號";
break;
case "isv.MOBILE_COUNT_OVER_LIMIT":
result = "手機號碼數量超過限制";
break;
case "isv.TEMPLATE_MISSING_PARAMETERS":
result = "模板缺少變量";
break;
case "isv.BUSINESS_LIMIT_CONTROL":
result = "業務限流";
break;
case "isv.INVALID_JSON_PARAM":
result = "JSON參數不合法,只接受字符串值";
break;
case "isv.PARAM_LENGTH_LIMIT":
result = "參數超出長度限制";
break;
case "isv.PARAM_NOT_SUPPORT_URL":
result = "不支持URL";
break;
case "isv.AMOUNT_NOT_ENOUGH":
result = "賬戶餘額不足";
break;
case "isv.TEMPLATE_PARAMS_ILLEGAL":
result = "模板變量裏包含非法關鍵字";
break;
}
return result;
}
}
寫簽名時廢了我好幾天的勁兒,怎麼就是跟阿里生成出來的簽名不一樣,一直查看自己的代碼,覺得自己的有問題,後來請教了阿里的技術人員,原來是他們在網站上貼出的簽名例子有一段是錯誤的,哎,害的我廢了半天勁兒,老以爲C#的簽名和java的不一樣呢!其實真的有一點不一樣,特別要注意,C#SHA1簽名簽出來的字母是大寫的,而java的是小寫的,所以一定要轉換一下。