深度优先

这个家伙好懒,除了文章什么都没留下

0%

【.Net Core】使用阿里云短信发送SMS

转自:https://www.cnblogs.com/kulend/p/8807716.html

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace ali_iot_sdk.Sms
{
public class AliyunSmsSender
{
private string RegionId = "cn-hangzhou";
private string Version = "2017-05-25";
private string Action = "SendSms";
private string Format = "JSON";
private string Domain = "dysmsapi.aliyuncs.com";

private int MaxRetryNumber = 3;
private bool AutoRetry = true;
private const string SEPARATOR = "&";
private int TimeoutInMilliSeconds = 100000;

private string AccessKeyId;
private string AccessKeySecret;

public AliyunSmsSender(string accessKeyId, string accessKeySecret)
{
this.AccessKeyId = accessKeyId;
this.AccessKeySecret = accessKeySecret;
}

/// <summary>
/// 发送短信
/// </summary>
public async Task<(bool success, string response)> Send(SmsObject sms)
{
var paramers = new Dictionary<string, string>();
paramers.Add("PhoneNumbers", sms.Mobile);
paramers.Add("SignName", sms.Signature);
paramers.Add("TemplateCode", sms.TempletKey);
paramers.Add("TemplateParam", JsonConvert.SerializeObject(sms.Data));
paramers.Add("OutId", sms.OutId);
paramers.Add("AccessKeyId", AccessKeyId);

try
{
string url = GetSignUrl(paramers, AccessKeySecret);

int retryTimes = 1;
var reply = await HttpGetAsync(url);
while (500 <= reply.StatusCode && AutoRetry && retryTimes < MaxRetryNumber)
{
url = GetSignUrl(paramers, AccessKeySecret);
reply = await HttpGetAsync(url);
retryTimes++;
}

if (!string.IsNullOrEmpty(reply.response))
{
var res = JsonConvert.DeserializeObject<Dictionary<string, string>>(reply.response);
if (res != null && res.ContainsKey("Code") && "OK".Equals(res["Code"]))
{
return (true, response: reply.response);
}
}

return (false, response: reply.response);
}
catch (Exception ex)
{
return (false, response: ex.Message);
}
}

private string GetSignUrl(Dictionary<string, string> parameters, string accessSecret)
{
var imutableMap = new Dictionary<string, string>(parameters);
imutableMap.Add("Timestamp", FormatIso8601Date(DateTime.Now));
imutableMap.Add("SignatureMethod", "HMAC-SHA1");
imutableMap.Add("SignatureVersion", "1.0");
imutableMap.Add("SignatureNonce", Guid.NewGuid().ToString());
imutableMap.Add("Action", Action);
imutableMap.Add("Version", Version);
imutableMap.Add("Format", Format);
imutableMap.Add("RegionId", RegionId);

IDictionary<string, string> sortedDictionary = new SortedDictionary<string, string>(imutableMap, StringComparer.Ordinal);
StringBuilder canonicalizedQueryString = new StringBuilder();
foreach (var p in sortedDictionary)
{
canonicalizedQueryString.Append("&")
.Append(PercentEncode(p.Key)).Append("=")
.Append(PercentEncode(p.Value));
}

StringBuilder stringToSign = new StringBuilder();
stringToSign.Append("GET");
stringToSign.Append(SEPARATOR);
stringToSign.Append(PercentEncode("/"));
stringToSign.Append(SEPARATOR);
stringToSign.Append(PercentEncode(canonicalizedQueryString.ToString().Substring(1)));

string signature = SignString(stringToSign.ToString(), accessSecret + "&");

imutableMap.Add("Signature", signature);

return ComposeUrl(Domain, imutableMap);
}

private static string FormatIso8601Date(DateTime date)
{
return date.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
}

/// <summary>
/// 签名
/// </summary>
public static string SignString(string source, string accessSecret)
{
using (var algorithm = new HMACSHA1(Encoding.UTF8.GetBytes(accessSecret.ToCharArray())))
{
return Convert.ToBase64String(algorithm.ComputeHash(Encoding.UTF8.GetBytes(source.ToCharArray())));
}
}

private static string ComposeUrl(string endpoint, Dictionary<String, String> parameters)
{
StringBuilder urlBuilder = new StringBuilder("");
urlBuilder.Append("http://").Append(endpoint);
if (-1 == urlBuilder.ToString().IndexOf("?"))
{
urlBuilder.Append("/?");
}
string query = ConcatQueryString(parameters);
return urlBuilder.Append(query).ToString();
}

private static string ConcatQueryString(Dictionary<string, string> parameters)
{
if (null == parameters)
{
return null;
}
StringBuilder sb = new StringBuilder();

foreach (var entry in parameters)
{
String key = entry.Key;
String val = entry.Value;

sb.Append(HttpUtility.UrlEncode(key, Encoding.UTF8));
if (val != null)
{
sb.Append("=").Append(HttpUtility.UrlEncode(val, Encoding.UTF8));
}
sb.Append("&");
}

int strIndex = sb.Length;
if (parameters.Count > 0)
sb.Remove(strIndex - 1, 1);

return sb.ToString();
}

public static string PercentEncode(string value)
{
StringBuilder stringBuilder = new StringBuilder();
string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
byte[] bytes = Encoding.GetEncoding("UTF-8").GetBytes(value);
foreach (char c in bytes)
{
if (text.IndexOf(c) >= 0)
{
stringBuilder.Append(c);
}
else
{
stringBuilder.Append("%").Append(
string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
}
}
return stringBuilder.ToString();
}

private async Task<(int StatusCode, string response)> HttpGetAsync(string url)
{
HttpClientHandler handler = new HttpClientHandler();
handler.Proxy = null;
handler.AutomaticDecompression = DecompressionMethods.GZip;

using (var http = new HttpClient(handler))
{
http.Timeout = new TimeSpan(TimeSpan.TicksPerMillisecond * TimeoutInMilliSeconds);
HttpResponseMessage response = await http.GetAsync(url);
return ((int)response.StatusCode, await response.Content.ReadAsStringAsync());
}
}
}
}

SmsObject.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System.Collections.Generic;

namespace ali_iot_sdk.Sms
{
public class SmsObject
{
/// <summary>
/// 手机号
/// </summary>
public string Mobile { set; get; }

/// <summary>
/// 签名
/// </summary>
public string Signature { get; set; }

/// <summary>
/// 模板Key
/// </summary>
public string TempletKey { set; get; }

/// <summary>
/// 短信数据
/// </summary>
public IDictionary<string, string> Data { set; get; }

/// <summary>
/// 业务ID
/// </summary>
public string OutId { set; get; }
}
}

调用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void SendAsync()
{
string accessKeyId = "LTAI2LglnrYQISrK";
string accessKeySecret = "affQ6iY4CNEUaMXNtgd4Fnuhk5IiZW";
IDictionary<string, string> data = new Dictionary<string, string>();
data.Add("name", "xguan");
var sms = new SmsObject
{
Mobile = "15377011087",
Signature = "深度优先",
TempletKey = "模板ID",
Data = data,
OutId = "OutId"
};

var res = new AliyunSmsSender(accessKeyId, accessKeySecret).Send(sms).Result;
string str1 = ($"发送结果:{res.success}");
string str2 = ($"Response:{res.response}");
}