C# 阿里云短信接口调用(不使用SDK,单文件完成)
支持单条和批量发送短信
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tech.CoreUtility;
using Tech.WebApi;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Net;
using System.Security.Cryptography;
namespace Tech.TC.BLL
{
/// <summary>
/// 【相关文档】
/// RPC调用机制:https://help.aliyun.com/document_detail/315526.htm?spm=a2c4g.11186623.0.0.46b027b5vlfd0X
/// 发送短信文档: https://help.aliyun.com/document_detail/419273.htm?spm=a2c4g.11186623.0.0.34374198G2b44u
/// 短信接口文档:https://help.aliyun.com/document_detail/419298.html?spm=5176.25163407.help.dexternal.774dbb6eylDOx0
/// </summary>
public static class AliyunSmsHelper
{
/// <summary>
/// 阿里云访问密钥
/// </summary>
public static string AccessKeyId = WorkBench.WebConfig["AccessKeyID"]; //用户标识
public static string AccessKeySecret = WorkBench.WebConfig["AccessKeySecret"]; //用户密钥
public static string SignName = WorkBench.WebConfig["SignName"]; //
private static readonly string Separator = "&";
public static string Url = "http://dysmsapi.aliyuncs.com?"; //短信接口地址
/// <summary>
/// 发送短信
/// </summary>
/// <param name="phone">手机号码</param>
/// <param name="signName">短信签名</param>
/// <param name="templateCode">模板编号</param>
/// <param name="templateParam">模板变量</param>
/// <returns></returns>
public static string SendSms(string phone, string signName, string templateCode, string templateParam)
{
var dic = new Dictionary<string, string>();
//公共请求参数
dic.Add("Action", "SendSms");
dic.Add("Version", "2017-05-25");
dic.Add("Format", "JSON");
dic.Add("AccessKeyId", AccessKeyId);
dic.Add("SignatureNonce", Guid.NewGuid().ToString());
dic.Add("Timestamp", DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'"));
dic.Add("SignatureMethod", "HMAC-SHA1");
dic.Add("SignatureVersion", "1.0");
//请求参数
dic.Add("PhoneNumbers", phone);
dic.Add("SignName", signName);
dic.Add("TemplateCode", templateCode);
dic.Add("TemplateParam", templateParam);
//接口签名
var signature = GetSignature(dic, "GET", AccessKeySecret);
dic.Add("Signature", signature);
var parms = "";
foreach (var pair in dic) parms += pair.Key + "=" + PercentEncode(pair.Value) + "&"; //参数值需用阿里云约定编码方式进行编码
parms = parms.TrimEnd('&');
return HttpGet(Url + parms);
}
/// <summary>
/// 批量发送短信
/// </summary>
/// <param name="phone">手机号码</param>
/// <param name="signName">短信签名</param>
/// <param name="templateCode">模板编号</param>
/// <param name="templateParam">模板变量</param>
/// <returns></returns>
public static string SendBatchSms(List<string> phones, string templateCode, string templateParam)
{
var dic = new Dictionary<string, string>();
//公共请求参数
dic.Add("Action", "SendBatchSms");
dic.Add("Version", "2017-05-25");
dic.Add("Format", "JSON");
dic.Add("AccessKeyId", AccessKeyId);
dic.Add("SignatureNonce", Guid.NewGuid().ToString());
dic.Add("Timestamp", DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'"));
dic.Add("SignatureMethod", "HMAC-SHA1");
dic.Add("SignatureVersion", "1.0");
//请求参数
var signs = new string[phones.Count];
Array.Fill<string>(signs, SignName);
dic.Add("PhoneNumberJson", phones.ToJson());
dic.Add("SignNameJson", signs.ToJson());
dic.Add("TemplateCode", templateCode);
dic.Add("TemplateParamJson", templateParam);
//接口签名
var signature = GetSignature(dic, "GET", AccessKeySecret);
dic.Add("Signature", signature);
var parms = "";
foreach (var pair in dic) parms += pair.Key + "=" + PercentEncode(pair.Value) + "&"; //参数值需用阿里云约定编码方式进行编码
parms = parms.TrimEnd('&');
return HttpGet(Url + parms);
}
/// <summary>
/// 发起网络请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string HttpGet(string url)
{
var encode = Encoding.UTF8;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "text/html, application/xhtml+xml, */*";
var response = (HttpWebResponse)request.GetResponse();
var rs = response.GetResponseStream();
var sr = new StreamReader(rs, encode);
var result = sr.ReadToEnd();
sr.Close();
rs.Close();
return result;
}
/// <summary>
/// 签名算法
/// </summary>
/// <param name="signedParams"></param>
/// <param name="method"></param>
/// <param name="secret"></param>
/// <returns></returns>
public static string GetSignature(
Dictionary<string, string> signedParams,
string method,
string secret)
{
var list = signedParams.Keys.ToList();
list.Sort(StringComparer.Ordinal); //排序
var builder = new StringBuilder();
foreach (var key in list)
if (signedParams[key] != null)
builder.Append("&").Append(PercentEncode(key)).Append("=").Append(PercentEncode(signedParams[key]));
var builder2 = new StringBuilder();
builder2.Append(method);
builder2.Append(Separator);
builder2.Append(PercentEncode("/"));
builder2.Append(Separator);
builder2.Append(PercentEncode(builder.ToString().Substring(1)));
byte[] hash = { };
using (var fromName = CryptoConfig.CreateFromName("HMACSHA1") as KeyedHashAlgorithm)
{
if (fromName != null)
{
fromName.Key = Encoding.UTF8.GetBytes(secret + Separator);
hash = fromName.ComputeHash(Encoding.UTF8.GetBytes(builder2.ToString().ToCharArray()));
}
}
return Convert.ToBase64String(hash);
}
/// <summary>
/// 编码
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static string PercentEncode(string value)
{
if (value == null)
return null;
var stringBuilder = new StringBuilder();
var str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
foreach (char ch in Encoding.UTF8.GetBytes(value))
if (str.IndexOf(ch) >= 0)
stringBuilder.Append(ch);
else
stringBuilder.Append("%").Append(string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)ch));
return stringBuilder.ToString().Replace("+", "%20").Replace("*", "%2A").Replace("%7E", "~");
}
public static string ToForm(IDictionary filter)
{
if (filter == null)
return string.Empty;
var dictionary = filter.Keys.Cast<string>().ToDictionary(key => key, key => filter[key]);
var dicOut = new Dictionary<string, string>();
TileDict(dicOut, dictionary);
var values = new List<string>();
foreach (var keyValuePair in dicOut)
if (!string.IsNullOrEmpty(keyValuePair.Value))
values.Add(PercentEncode(keyValuePair.Key) + "=" + PercentEncode(keyValuePair.Value));
return string.Join("&", values.ToArray());
}
internal static void TileDict(Dictionary<string, string> dicOut, object obj, string parentKey = "")
{
if (obj == null)
return;
if (typeof(IDictionary).IsAssignableFrom(obj.GetType()))
{
foreach (var keyValuePair in ((IDictionary)obj).Keys.Cast<string>()
.ToDictionary(key => key, key => ((IDictionary)obj)[key]))
{
var parentKey1 = parentKey + "." + keyValuePair.Key;
if (keyValuePair.Value != null)
TileDict(dicOut, keyValuePair.Value, parentKey1);
}
}
else if (typeof(IList).IsAssignableFrom(obj.GetType()))
{
var num = 1;
foreach (var obj1 in (IEnumerable)obj)
{
TileDict(dicOut, obj1, parentKey + "." + num.ToSafeString());
++num;
}
}
else if (obj.GetType() == typeof(byte[]))
{
dicOut.Add(parentKey.TrimStart('.'), Encoding.UTF8.GetString((byte[])obj));
}
else
{
dicOut.Add(parentKey.TrimStart('.'), obj.ToSafeString(""));
}
}
public static string ToSafeString(this object obj, string defaultStr = null)
{
if (obj == null)
return defaultStr;
try
{
return obj.ToString();
}
catch
{
return defaultStr;
}
}
}
}
调用方式如下:
AliyunSmsHelper.SendBatchSms(list, "SMS_xxxxxxx", count);
参考文档:
C# 阿里云短信接口调用(不使用SDK,单文件完成)_c#阿里云 验证短信发送-CSDN博客
我也是参考他的,他没有写批量发送