使用阿里雲的短信服務發送短信

在給客戶開發一個信息發送功能的時候,須要涉及到短信的發送,短信發送通常不一樣的廠商提供的接口不一樣,處理方式也不太同樣,以前用的一個廠商的,提供了一個封裝類就很容易發送短息,所以都是基於HTTP協議作的一個數據發送而已,接觸阿里雲的短信服務器後,發現阿里雲還增長了很是多的參數,其中包括一些祕鑰和簽名的內容。短信發送因爲比較敏感緣由,大多數應用場景是驗證碼或者一些固定的信息提醒,所以廠商都要求客戶按預約的模板來發送,這樣限制了短信的應用場景,只能根據業務進行消息定製了。本篇隨筆主要介紹阿里雲的短信服務的發送處理。html

一、短信發送的處理介紹

在短信發送中,阿里雲提供本身的SDK封裝,以下降使用的難度,不過須要引入它提供的SDK類庫;本篇隨筆主要介紹基於HTTP方式進行自行的封裝處理,這部分代碼我從網上摘錄並進行必定的調整,測試成功。api

使用阿里雲的短信服務,須要註冊登陸本身的阿里雲控制檯,而後進入AccessKeys的處理界面數組

而後系統會提示須要建立一個新的Key(若是沒有的話就建立,不然使用已有的便可)服務器

這裏咱們獲取到AccessKey ID 和Access Key Secret兩個關鍵信息,須要用在數據簽名的裏面的。微信

另外咱們須要建立一個SignName,也就是簽名,通常爲咱們短信提示的公司名稱,如【廣州愛奇迪】這樣的字樣。post

短信是基於模板的,阿里雲不能發送隨意的內容,所以只能基於模板發送,如驗證碼或者業務消息,有點相似微信的模板消息了,所以裏面能夠添加變量發送的。測試

記得我之前寫過一個關於動態變量的信息發送的文章《一個包含動態變量的短信模板設計分析》,就是介紹如何處理變量模板消息的。ui

阿里雲默認提供了一些基礎模板,以下所示。阿里雲

通常咱們業務可能還須要定製一些業務消息,那麼須要審覈經過才能夠使用新增的模板消息。編碼

短信的發送能夠利用API接口進行發送,以下所示是它的API說明

若是須要採集用戶的回覆信息,如一些隨訪記錄,那麼須要作一個接口的處理,以下所示。

 

發送短信的API接口詳細說明以下所示。

其實請求信息比上面列出的信息多不少,包括祕鑰和數據加密信息等的處理,下面詳細給出代碼說明。 

 

二、模板消息發送

 有了上面的信息介紹,咱們大概瞭解了短信消息發送的處理規則了。

實際上,發送信息的時候,咱們可能須要添加不少參數信息,以下代碼所示。

            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", SignName);
            keyValues.Add("TemplateParam", "{\"code\":\"" + code + "\"}");
            keyValues.Add("TemplateCode", templateCode);
            keyValues.Add("OutId", "123");

具體咱們來貼出不用SDK的短信發送輔助類,以下代碼所示。

    /// <summary>
    /// 阿里短信發送
    /// </summary>
    public class SmsHelper
    {
        private const string endpoint = "dysmsapi.aliyuncs.com";
        private const string AccessKeyId = "你的祕鑰鍵";
        private const string AccessKeySecret = "你的祕鑰值";
        private const string SignName = "廣州愛奇迪";

        /// <summary>
        /// 短信驗證碼
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="code"></param>
        /// <returns></returns>
        public static string SendSms(string mobile, int code, string templateCode = "SMS_126645400")
        {
            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", SignName);
            keyValues.Add("TemplateParam", "{\"code\":\"" + code + "\"}");
            keyValues.Add("TemplateCode", 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(AccessKeySecret + "&", stringToSign.ToString());
            //6.簽名最後也要作特殊URL編碼
            string signture = specialUrlEncode(Sign);

            //最終打印出合法GET請求的URL
            string url = string.Format("http://{0}/?Signature={1}{2}", endpoint, signture, builder);
            string result = GetHtmlFormUrl(url);
            return result;
        }


        /// <summary>
        /// 短信接口C#調用方法
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private 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.UTF8);

                strRet = MessageHandle(ser.ReadToEnd());
            }
            catch (Exception ex)
            {
                strRet = "短信發送失敗!" + ex.Message;
            }
            return strRet;
        }

        /// <summary>
        /// 驗證手機號碼是否合法
        /// </summary>
        /// <param name="mobile">電話號碼</param>
        /// <returns></returns>
        public static bool IsMobile(string mobile)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(mobile, @"^1[3|4|5|7|8][0-9]\d{8}$");
        }

        /// <summary>
        /// URL編碼
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private 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>
        private 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;
        }

    }

    internal class MessageModel
    {
        public string RequestId { get; set; }
        public string Code { get; set; }
        public string Message { get; set; }
    }

上面代碼不是我原創,聲明一下,我作了一些修改調整而已,方便輔助類的使用,咱們輸入咱們的企業的祕鑰鍵值,而後發送測試短信便可。

            string tel = "18620292076";
            string result = SmsHelper.SendSms(tel, 123456);
            Console.WriteLine(result);

發送測試,3~5秒就能夠收到驗證碼信息的提示了,以下所示。

 以上就是短信消息的發送,但願對使用阿里雲短信服務的開發人員有所幫助,輔助類直接就能夠使用了。

相關文章
相關標籤/搜索