C#不調用阿里短信dll,如何使用http接口實現短信發送

  前一段時間公司有個項目需要用到短信通知,然後我買了個阿里雲的短信進行短信接口的開發。但是項目是在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的是小寫的,所以一定要轉換一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章