• .net core 使用阿里云短信发送SMS


    阿里云官方的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 = 3;
     23         private bool AutoRetry = true;
     24         private const string SEPARATOR = "&";
     25         private int TimeoutInMilliSeconds = 100000;
     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 = 1;
     54                 var reply = await HttpGetAsync(url);
     55                 while (500 <= 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(1)));
    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 (-1 == 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 > 0)
    165                 sb.Remove(strIndex - 1, 1);
    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) >= 0)
    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", "111111");
     3                         var sms = new SmsObject
     4                         {
     5                             Mobile = "18812345678",
     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}");
  • 相关阅读:
    最强PostMan使用教程
    Fiddler模拟post四种请求数据
    关于Spring集成Quartz的concurrent属性
    数据事务四种隔离机制和七种传播行为
    eclipse properties 文件查看和编辑插件
    RabbitMq的整理 exchange、route、queue关系
    MySQL关闭查询缓存(QC)的两种方法
    Map集合的四种遍历方式
    springBoot使用外部Tomcat启动项目
    解决tomcat闪退问题
  • 原文地址:https://www.cnblogs.com/kulend/p/8807716.html
Copyright © 2020-2023  润新知