阿里云官方的skd(aliyun-net-sdk-core,aliyun-net-sdk-dysmsapi)在dnc中发送短信会出错,nuget上的包貌似也一样不管用。直接改下sdk当然也可以,但就发个短信,官方的sdk实在是有点繁杂,其实可以简单化,一个类就搞定。

  1. using Newtonsoft.Json;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Security.Cryptography;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using System.Web;
  11.  
  12. namespace Vino.Core.Communication.SMS
  13. {
  14. public class AliyunSmsSender : ISmsSender
  15. {
  16. private string RegionId = "cn-hangzhou";
  17. private string Version = "2017-05-25";
  18. private string Action = "SendSms";
  19. private string Format = "JSON";
  20. private string Domain = "dysmsapi.aliyuncs.com";
  21.  
  22. private int MaxRetryNumber = ;
  23. private bool AutoRetry = true;
  24. private const string SEPARATOR = "&";
  25. private int TimeoutInMilliSeconds = ;
  26.  
  27. private string AccessKeyId;
  28. private string AccessKeySecret;
  29.  
  30. public AliyunSmsSender(string accessKeyId, string accessKeySecret)
  31. {
  32. this.AccessKeyId = accessKeyId;
  33. this.AccessKeySecret = accessKeySecret;
  34. }
  35.  
  36. /// <summary>
  37. /// 发送短信
  38. /// </summary>
  39. public async Task<(bool success, string response)> Send(SmsObject sms)
  40. {
  41. var paramers = new Dictionary<string, string>();
  42. paramers.Add("PhoneNumbers", sms.Mobile);
  43. paramers.Add("SignName", sms.Signature);
  44. paramers.Add("TemplateCode", sms.TempletKey);
  45. paramers.Add("TemplateParam", JsonConvert.SerializeObject(sms.Data));
  46. paramers.Add("OutId", sms.OutId);
  47. paramers.Add("AccessKeyId", AccessKeyId);
  48.  
  49. try
  50. {
  51. string url = GetSignUrl(paramers, AccessKeySecret);
  52.  
  53. int retryTimes = ;
  54. var reply = await HttpGetAsync(url);
  55. while ( <= reply.StatusCode && AutoRetry && retryTimes < MaxRetryNumber)
  56. {
  57. url = GetSignUrl(paramers, AccessKeySecret);
  58. reply = await HttpGetAsync(url);
  59. retryTimes++;
  60. }
  61.  
  62. if (!string.IsNullOrEmpty(reply.response))
  63. {
  64. var res = JsonConvert.DeserializeObject<Dictionary<string, string>>(reply.response);
  65. if (res != null && res.ContainsKey("Code") && "OK".Equals(res["Code"]))
  66. {
  67. return (true, response: reply.response);
  68. }
  69. }
  70.  
  71. return (false, response: reply.response);
  72. }
  73. catch (Exception ex)
  74. {
  75. return (false, response: ex.Message);
  76. }
  77. }
  78.  
  79. private string GetSignUrl(Dictionary<string, string> parameters, string accessSecret)
  80. {
  81. var imutableMap = new Dictionary<string, string>(parameters);
  82. imutableMap.Add("Timestamp", FormatIso8601Date(DateTime.Now));
  83. imutableMap.Add("SignatureMethod", "HMAC-SHA1");
  84. imutableMap.Add("SignatureVersion", "1.0");
  85. imutableMap.Add("SignatureNonce", Guid.NewGuid().ToString());
  86. imutableMap.Add("Action", Action);
  87. imutableMap.Add("Version", Version);
  88. imutableMap.Add("Format", Format);
  89. imutableMap.Add("RegionId", RegionId);
  90.  
  91. IDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(imutableMap, StringComparer.Ordinal);
  92. StringBuilder canonicalizedQueryString = new StringBuilder();
  93. foreach (var p in sortedDictionary)
  94. {
  95. canonicalizedQueryString.Append("&")
  96. .Append(PercentEncode(p.Key)).Append("=")
  97. .Append(PercentEncode(p.Value));
  98. }
  99.  
  100. StringBuilder stringToSign = new StringBuilder();
  101. stringToSign.Append("GET");
  102. stringToSign.Append(SEPARATOR);
  103. stringToSign.Append(PercentEncode("/"));
  104. stringToSign.Append(SEPARATOR);
  105. stringToSign.Append(PercentEncode(canonicalizedQueryString.ToString().Substring()));
  106.  
  107. string signature = SignString(stringToSign.ToString(), accessSecret + "&");
  108.  
  109. imutableMap.Add("Signature", signature);
  110.  
  111. return ComposeUrl(Domain, imutableMap);
  112. }
  113.  
  114. private static string FormatIso8601Date(DateTime date)
  115. {
  116. return date.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
  117. }
  118.  
  119. /// <summary>
  120. /// 签名
  121. /// </summary>
  122. public static string SignString(string source, string accessSecret)
  123. {
  124. using (var algorithm = new HMACSHA1(Encoding.UTF8.GetBytes(accessSecret.ToCharArray())))
  125. {
  126. return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(source.ToCharArray())));
  127. }
  128. }
  129.  
  130. private static string ComposeUrl(string endpoint, Dictionary<String, String> parameters)
  131. {
  132. StringBuilder urlBuilder = new StringBuilder("");
  133. urlBuilder.Append("http://").Append(endpoint);
  134. if (- == urlBuilder.ToString().IndexOf("?"))
  135. {
  136. urlBuilder.Append("/?");
  137. }
  138. string query = ConcatQueryString(parameters);
  139. return urlBuilder.Append(query).ToString();
  140. }
  141.  
  142. private static string ConcatQueryString(Dictionary<string, string> parameters)
  143. {
  144. if (null == parameters)
  145. {
  146. return null;
  147. }
  148. StringBuilder sb = new StringBuilder();
  149.  
  150. foreach (var entry in parameters)
  151. {
  152. String key = entry.Key;
  153. String val = entry.Value;
  154.  
  155. sb.Append(HttpUtility.UrlEncode(key, Encoding.UTF8));
  156. if (val != null)
  157. {
  158. sb.Append("=").Append(HttpUtility.UrlEncode(val, Encoding.UTF8));
  159. }
  160. sb.Append("&");
  161. }
  162.  
  163. int strIndex = sb.Length;
  164. if (parameters.Count > )
  165. sb.Remove(strIndex - , );
  166.  
  167. return sb.ToString();
  168. }
  169.  
  170. public static string PercentEncode(string value)
  171. {
  172. StringBuilder stringBuilder = new StringBuilder();
  173. string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
  174. byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(value);
  175. foreach (char c in bytes)
  176. {
  177. if (text.IndexOf(c) >= )
  178. {
  179. stringBuilder.Append(c);
  180. }
  181. else
  182. {
  183. stringBuilder.Append("%").Append(
  184. string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
  185. }
  186. }
  187. return stringBuilder.ToString();
  188. }
  189.  
  190. private async Task<(int StatusCode, string response)> HttpGetAsync(string url)
  191. {
  192. HttpClientHandler handler = new HttpClientHandler();
  193. handler.Proxy = null;
  194. handler.AutomaticDecompression = DecompressionMethods.GZip;
  195.  
  196. using (var http = new HttpClient(handler))
  197. {
  198. http.Timeout = new TimeSpan(TimeSpan.TicksPerMillisecond * TimeoutInMilliSeconds);
  199. HttpResponseMessage response = await http.GetAsync(url);
  200. return ((int)response.StatusCode, await response.Content.ReadAsStringAsync());
  201. }
  202. }
  203. }
  204. }

SmsObject.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. namespace Vino.Core.Communication.SMS
  6. {
  7. public class SmsObject
  8. {
  9. /// <summary>
  10. /// 手机号
  11. /// </summary>
  12. public string Mobile { set; get; }
  13.  
  14. /// <summary>
  15. /// 签名
  16. /// </summary>
  17. public string Signature { get; set; }
  18.  
  19. /// <summary>
  20. /// 模板Key
  21. /// </summary>
  22. public string TempletKey { set; get; }
  23.  
  24. /// <summary>
  25. /// 短信数据
  26. /// </summary>
  27. public IDictionary<string, string> Data { set; get; }
  28.  
  29. /// <summary>
  30. /// 业务ID
  31. /// </summary>
  32. public string OutId { set; get; }
  33. }
  34. }

调用方法

  1. IDictionary<string, string> data = new Dictionary<string, string>();
  2. data.Add("code", "");
  3. var sms = new SmsObject
  4. {
  5. Mobile = "",
  6. Signature = "我的签名",
  7. TempletKey = "模板ID",
  8. Data = data,
  9. OutId = "OutId"
  10. };
  11.  
  12. var res = await new AliyunSmsSender(accessKeyId, accessKeySecret).Send(sms);
  13. Debug.WriteLine($"发送结果:{res.success}");
  14. Debug.WriteLine($"Response:{res.response}");

.net core 使用阿里云短信发送SMS的更多相关文章

  1. Abp 添加阿里云短信发送

    ABP中有短信发送接口ISmsSender public interface ISmsSender { Task<string> SendAsync(string number, stri ...

  2. 2018阿里云短信发送DEMO接入简单实例

    以下更新2018-04-2309:57:54 后续不再更新, 基本类: app/SignatureHelper.php <?php namespace aliyun_mns; /** * 签名助 ...

  3. 阿里云短信发送服务SDK-Python3

    本文提供阿里云的短信发送服务SDK,使用Python3实现. # -*- coding: utf-8 -*- # pip install requests import requests import ...

  4. spring boot集成阿里云短信发送接收短信回复功能

    1.集成阿里云通信发送短信: 在pom.xml文件里添加依赖 <!--阿里短信服务--> <dependency> <groupId>com.aliyun</ ...

  5. tp5阿里云短信发送

    到阿里云下载php版demo,下完整版的,不是轻量级的; 框架  :TP5 把下载下来的文件放到extend里面 文件名:alimsg 里面的文件 import('alimsg.api_demo.Sm ...

  6. java 阿里云短信发送

    记录自己的足迹,学习的路很长,一直在走着呢~ 第一步登录阿里云的控制台,找到此处: 点击之后就到此页面,如果发现账号有异常或者泄露什么,可以禁用或者删除  AccessKey: 此处方便测试,所以就新 ...

  7. ABP框架中短信发送处理,包括阿里云短信和普通短信商的短信发送集成

    在一般的系统中,往往也有短信模块的需求,如动态密码的登录,系统密码的找回,以及为了获取用户手机号码的短信确认等等,在ABP框架中,本身提供了对邮件.短信的基础支持,那么只需要根据自己的情况实现对应的接 ...

  8. 阿里云短信服务开发报错Java.lang.NoClassDefFoundError:com/aliyuncs/exceptions/ClientException

    手机app获取短信验证码功能时候,遇到的问题.使用的是阿里云的短信服务,下载平台demo时运行不报错,但是在service层调用的时候报错 Java.lang.NoClassDefFoundError ...

  9. 阿里云短信验证解决方案(java版)(redis存储)

    最近搞了一个互联网项目的注册,需要写一个手机号验证(由于之前没有轮子,只能自己摸索了); 1:基本思路: 1>购买了阿里云短信服务->下载阿里云短信发送demo(java版); 2> ...

随机推荐

  1. NGUI_Texture

    六.UITexture:在屏幕上显示一张图片,和Sprite类似,但是UITexture会单独消耗一个DrawCall去渲染, 会单独加载进内存,会增加内存的开销. 1.使用UITexture时要遵循 ...

  2. 原生js实现简单的全屏滚动

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. DOM生成XML文档

    import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuil ...

  4. Notes:一致性哈希算法

    业务场景: 存在三个专门提供缓存服务的服务器,前端所需要的图片等静态资源被缓存于这三个服务器其中之一. 但是如何提高查找图片的速度呢? 可以采用哈希算法. 常规意义上的哈希算法: 通过hash(图片名 ...

  5. echarts地图的引用

    最近是跟echarts杠上了 所在公司是搞数据的 所以身为前端的我 就必须使用echarts将数据展示出来 ,进公司一周 ,前前后后大概用了八九种echarts图,我举得最难的就是引用的地图,因为刚开 ...

  6. 设计模式之 原型模式详解(clone方法源码的简单剖析)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 原型模式算是JAVA中最简单 ...

  7. lua向文件中写入数据,进行记录

    function readfile(path) local file = io.open(path, "r") if file then local content = file: ...

  8. Mysql加密解密随机函数

    MD5(str) md5加密 SELECT MD5('hello') 5d41402abc4b2a76b9719d911017c592 sha(str) sha加密 SELECT SHA('hello ...

  9. 论C++的智能指针

    一.简介   参考这篇博客,并且根据<C++ Primer>中相关知识,我总结了C++关于智能指针方面的内容.   为了解决内存泄漏的问题,便出现了智能指针.STL提供的智能指针有:aut ...

  10. 高校学生征信系统Postmortem结果

    Postmortem结果 设想和目标 1 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件需要解决的问题是当前高校学生征信系统建设薄弱的问题,我们试图建立 ...