Abp 添加阿里云短信发送

ABP中有短信发送接口ISmsSender

public interface ISmsSender
{
  Task<string> SendAsync(string number, string message);
}

使用阿里云短信服务实现这个接口,使得能够通过阿里云短信服务发送通知短信

 ISmsSender一般是在Core项目中,所以实现类也放一起

 

首先是实现一个ISmsSender

  1 using Abp.Dependency;
  2 using Castle.Core.Logging;
  3 using System;
  4 using System.Threading.Tasks;
  5 using System.Collections.Generic;
  6 using System.Text;
  7 using System.Security.Cryptography;
  8 using System.Globalization;
  9 using System.Net.Http;
 10 using Newtonsoft.Json;
 11 using Microsoft.Extensions.Configuration;
 12 using MyCompany.MyProject.Configuration;
 13 using Microsoft.AspNetCore.Hosting;
 14 
 15 namespace MyCompany.MyProject.Identity
 16 {
 17     public class AliyunSmsSender : ISmsSender, ITransientDependency
 18     {
 19         public ILogger Logger { get; set; }
 20         string appkey ;
 21         string secret;
 22         string serverUrl = "dysmsapi.aliyuncs.com";
 23         string signName;
 24         string TemplateCode;
 25         private Dictionary<string, string> smsDict = new Dictionary<string, string>
 26         {
 27             { "RegionId", "cn-hangzhou" },
 28             { "Action", "SendSms" },
 29             { "Version", "2017-05-25" },
 30         };
 31         private readonly IConfigurationRoot configuration;
 32 
 33         public AliyunSmsSender(ILogger Logger, IHostingEnvironment env)
 34         {
 35             configuration = env.GetAppConfiguration();
 36             appkey = configuration["SmsConfiguration:AliSms:appkey"];
 37             secret = configuration["SmsConfiguration:AliSms:secret"];
 38             signName = configuration["SmsConfiguration:AliSms:SignName"];
 39             TemplateCode = configuration["SmsConfiguration:AliSms:TemplateCode"];
 40 
 41             smsDict.Add("SignName", signName);//签名
 42             smsDict.Add("TemplateCode", TemplateCode);//模板
 43             smsDict.Add("TemplateParam", "");//参数内容
 44             smsDict.Add("PhoneNumbers", "");//发送到的手机号
 45             
 46         }
 47         public async Task<string> SendAsync(string number, string message)
 48         {
 49             try
 50             {
 51                 smsDict["PhoneNumbers"] = number;
 52                 smsDict["TemplateParam"] = JsonConvert.SerializeObject(new { code = message });
 53                 var signatiure = new SignatureHelper();
 54                 string res = await signatiure.Request(appkey, secret, serverUrl, smsDict, logger: Logger);
 55                 Logger.Info("验证短信发送返回:" + res);
 56                 return res;
 57             }
 58             catch (Exception e)
 59             {
 60                 Logger.Error(e.Message);
 61                 throw;
 62             }
 63         }
 64 
 65         /// <summary>
 66         /// 签名助手
 67         /// https://help.aliyun.com/document_detail/30079.html?spm=5176.7739992.2.3.HM7WTG
 68         /// </summary>
 69         public class SignatureHelper
 70         {
 71             private const string ISO8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
 72             private const string ENCODING_UTF8 = "UTF-8";
 73             public static string PercentEncode(String value)
 74             {
 75                 StringBuilder stringBuilder = new StringBuilder();
 76                 string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
 77                 byte[] bytes = Encoding.GetEncoding(ENCODING_UTF8).GetBytes(value);
 78                 foreach (char c in bytes)
 79                 {
 80                     if (text.IndexOf(c) >= 0)
 81                     {
 82                         stringBuilder.Append(c);
 83                     }
 84                     else
 85                     {
 86                         stringBuilder.Append("%").Append(
 87                             string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
 88                     }
 89                 }
 90                 return stringBuilder.ToString();
 91             }
 92             public static string FormatIso8601Date(DateTime date)
 93             {
 94                 return date.ToUniversalTime().ToString(ISO8601_DATE_FORMAT, CultureInfo.CreateSpecificCulture("en-US"));
 95             }
 96 
 97             private static IDictionary<string, string> SortDictionary(Dictionary<string, string> dic)
 98             {
 99                 IDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(dic, StringComparer.Ordinal);
100                 return sortedDictionary;
101             }
102 
103             public static string SignString(string source, string accessSecret)
104             {
105                 using (var algorithm = new HMACSHA1())
106                 {
107                     algorithm.Key = Encoding.UTF8.GetBytes(accessSecret.ToCharArray());
108                     return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(source.ToCharArray())));
109                 }
110             }
111 
112 
113             public async Task<string> HttpGetAsync(string url, ILogger logger)
114             {
115                 string responseBody = string.Empty;
116                 using (var http = new HttpClient())
117                 {
118                     try
119                     {
120                         http.DefaultRequestHeaders.Add("x-sdk-client", "Net/2.0.0");
121                         var response = await http.GetAsync(url);
122                         response.EnsureSuccessStatusCode();
123                         responseBody = await response.Content.ReadAsStringAsync();
124                     }
125                     catch (HttpRequestException e)
126                     {
127                         Console.WriteLine("\nException !");
128                         Console.WriteLine("Message :{0} ", e.Message);
129                         throw;
130                     }
131                 }
132                 return responseBody;
133 
134             }
135 
136             public async Task<string> Request(string accessKeyId, string accessKeySecret, string domain, Dictionary<string, string> paramsDict, ILogger logger, bool security = false)
137             {
138                 var apiParams = new Dictionary<string, string>
139                 {
140                     { "SignatureMethod", "HMAC-SHA1" },
141                     { "SignatureNonce", Guid.NewGuid().ToString() },
142                     { "SignatureVersion", "1.0" },
143                     { "AccessKeyId", accessKeyId },
144                     { "Timestamp", FormatIso8601Date(DateTime.Now) },
145                     { "Format", "JSON" },
146                 };
147 
148                 foreach (var param in paramsDict)
149                 {
150                     if (!apiParams.ContainsKey(param.Key))
151                     {
152                         apiParams.Add(param.Key, param.Value);
153                     }
154                 }
155                 var sortedDictionary = SortDictionary(apiParams);
156                 string sortedQueryStringTmp = "";
157                 foreach (var param in sortedDictionary)
158                 {
159                     sortedQueryStringTmp += "&" + PercentEncode(param.Key) + "=" + PercentEncode(param.Value);
160                 }
161 
162                 string stringToSign = "GET&%2F&" + PercentEncode(sortedQueryStringTmp.Substring(1));
163                 string sign = SignString(stringToSign, accessKeySecret + "&");
164                 string signature = PercentEncode(sign);
165                 string url = (security ? "https" : "http") + $"://{domain}/?Signature={signature}{sortedQueryStringTmp}";
166                 string result;
167                 try
168                 {
169                     result = await HttpGetAsync(url, logger);
170                 }
171                 catch (Exception)
172                 {
173 
174                     throw;
175                 }
176                 return result;
177 
178             }
179         }
180     }
181 }

 

 

 然后在core项目的Mudule中配置注入关系

 

最后在配置文件中加上配置节点即可

"SmsConfiguration": {
    "AliSms": {
      "appkey": "",
      "secret": "",
      "SignName": "",
      "TemplateCode": ""
    }
  }

对应上appkey secret,签名,模板code

 

最后在需要调用的地方注入ISmsSender, 调用其SendAsync方法,传入手机号和内容即可。

posted @ 2019-04-10 19:52  turingguo  阅读(926)  评论(0编辑  收藏  举报