2020最新 使用阿里雲的簡訊服務傳送簡訊
在給客戶開發一個資訊傳送功能的時候,需要涉及到簡訊的傳送,簡訊傳送一般不同的廠商提供的介面不同,處理方式也不太一樣,之前用的一個廠商的,提供了一個封裝類就很容易傳送短息,因此都是基於HTTP協議做的一個資料傳送而已,接觸阿里雲的簡訊伺服器後,發現阿里雲還增加了非常多的引數,其中包括一些祕鑰和簽名的內容。簡訊傳送由於比較敏感原因,大多數應用場景是驗證碼或者一些固定的資訊提醒,因此廠商都要求客戶按預定的模板來傳送,這樣限制了簡訊的應用場景,只能根據業務進行訊息定製了。本篇隨筆主要介紹阿里雲的簡訊服務的傳送處理。
1、簡訊傳送的處理介紹
在簡訊傳送中,阿里雲提供自己的SDK封裝,以降低使用的難度,不過需要引入它提供的SDK類庫;本篇隨筆主要介紹基於HTTP方式進行自行的封裝處理,這部分程式碼我從網上摘錄並進行一定的調整,測試成功。
使用阿里雲的簡訊服務,需要註冊登入自己的阿里雲控制檯,然後進入AccessKeys的處理介面
然後系統會提示需要建立一個新的Key(如果沒有的話就建立,否則使用已有的即可)
這裡我們獲取到AccessKey ID 和Access Key Secret兩個關鍵資訊,需要用在資料簽名的裡面的。
另外我們需要建立一個SignName,也就是簽名,一般為我們簡訊提示的公司名稱,如【廣州愛奇迪】這樣的字樣。
簡訊是基於模板的,阿里雲不能傳送隨意的內容,因此只能基於模板傳送,如驗證碼或者業務訊息,有點類似微信的模板訊息了,因此裡面可以新增變數傳送的。
記得我以前寫過一個關於動態變數的資訊傳送的文章《一個包含動態變數的簡訊模板設計分析》,就是介紹如何處理變數模板訊息的。
阿里雲預設提供了一些基礎模板,如下所示。
一般我們業務可能還需要定製一些業務訊息,那麼需要稽核通過才可以使用新增的模板訊息。
簡訊的傳送可以利用API介面進行傳送,如下所示是它的API說明
如果需要採集使用者的回覆資訊,如一些隨訪記錄,那麼需要做一個介面的處理,如下所示。
傳送簡訊的API介面詳細說明如下所示。
其實請求資訊比上面列出的資訊多很多,包括祕鑰和資料加密資訊等的處理,下面詳細給出程式碼說明。
2、模板訊息傳送
有了上面的資訊介紹,我們大概瞭解了簡訊訊息傳送的處理規則了。
實際上,傳送資訊的時候,我們可能需要新增很多引數資訊,如下程式碼所示。
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秒就可以收到驗證碼資訊的提示了,如下所示。
以上就是簡訊訊息的傳送,希望對使用阿里雲簡訊服務的開發人員有所幫助,輔助類直接就可以使用了。
【阿里雲】2020雙十一優惠:https://www.aliyun.com/1111/new?userCode=fggt3m9n
相關文章
- Laravel 極簡使用傳送簡訊 支援阿里雲、騰訊雲Laravel阿里
- Jave Web阿里雲簡訊服務傳送驗證碼Web阿里
- 阿里雲簡訊傳送 sdk阿里
- java 阿里雲簡訊傳送Java阿里
- .net core 使用阿里雲簡訊傳送SMS阿里
- 阿里雲平臺傳送簡訊阿里
- 阿里雲簡訊服務阿里
- springboot 專案使用阿里雲簡訊服務傳送手機驗證碼Spring Boot阿里
- 阿里雲簡訊服務使用代理的坑阿里
- 阿里雲簡訊服務的使用-----獲取簡訊驗證碼阿里
- Laravel6 使用騰訊雲簡訊-傳送簡訊Laravel
- 【故障公告】騰訊雲簡訊服務故障造成無法傳送手機簡訊
- Laravel 阿里雲簡訊服務包Laravel阿里
- 使用 Python 傳送簡訊?Python
- 普歌-騰訊雲簡訊+使用node傳送簡訊(3種方法API、SDK)、封裝工具、搭建web服務、寫介面、呼叫介面傳送簡訊、時效性判斷(上)API封裝Web
- 為何選擇阿里雲 簡訊服務阿里
- hyperf 使用阿里雲簡訊阿里
- 阿里雲簡訊服務實現網站手機簡訊驗證碼阿里網站
- ThinkPHP5.1 接入阿里雲簡訊服務 (原大魚最新版) 指導PHP阿里
- 簡訊傳送機的實現
- 郵件和簡訊傳送
- SpringBoot 實現傳送簡訊Spring Boot
- Laravel SMS 簡訊傳送包Laravel
- 阿里雲訊息服務使用教程阿里
- Laravel 簡訊擴充套件包 - 目前支援簡訊服務商:阿里雲 / 雲片網 / 騰訊雲 / 簡訊寶 / 賽郵雲 /SendCloud/ 互億無線(支援全網簡訊擴充套件)Laravel套件阿里Cloud
- go-zero之阿里發簡訊服務Go阿里
- 使用阿里簡訊(防止薅羊毛、限制傳送次數)直接複製直接用阿里
- 106傳送簡訊有哪些平臺?
- 二十一章 PHP傳送簡訊PHP
- 【親測可用】阿里雲簡訊阿里
- laravel-sms 實現阿里雲手機傳送簡訊驗證碼及校驗Laravel阿里
- PHP 擴充套件包教程學習分享 -- 阿里雲簡訊服務 SDKPHP套件阿里
- [Python]實現簡訊驗證碼的傳送Python
- Laravel6 使用騰訊雲簡訊-新增簡訊模板Laravel
- Laravel6 使用騰訊雲簡訊-修改簡訊模板Laravel
- 路飛學城專案之整合騰訊雲簡訊服務、簡訊驗證碼介面
- 騰訊雲sdk 支援 騰訊雲簡訊 Laravel Notification [最新版]Laravel
- 如何透過文字服務轉發在iPad和Mac上傳送和接收簡訊iPadMac