using Furion.FriendlyException;
|
using Furion.HttpRemote;
|
using Microsoft.AspNetCore.Http;
|
using Microsoft.Extensions.Options;
|
using System;
|
using System.Collections.Generic;
|
using System.Globalization;
|
using System.Linq;
|
using System.Security.Cryptography;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
|
namespace FlexJobApi.Core
|
{
|
public class AliyunSmsUtils
|
{
|
private readonly IOptions<AliyunOptions> options;
|
private readonly IHttpRemoteService httpRemoteService;
|
|
public AliyunSmsUtils(
|
IOptions<AliyunOptions> options,
|
IHttpRemoteService httpRemoteService)
|
{
|
this.options = options;
|
this.httpRemoteService = httpRemoteService;
|
}
|
|
/// <summary>
|
/// 发送短信
|
/// </summary>
|
/// <param name="phoneNumber">手机号码</param>
|
/// <param name="templateCode">模板代码</param>
|
/// <param name="templateParam">模板参数</param>
|
/// <param name="cancellationToken">取消令牌</param>
|
/// <returns></returns>
|
/// <exception cref="Oops"></exception>
|
public async Task SendAsync(string phoneNumber, EnumSmsTemplateCode templateCode, string templateParam, CancellationToken cancellationToken)
|
{
|
if (options.Value.SMS?.Enable != true)
|
{
|
return;
|
}
|
if (options.Value.SMS != null
|
&& options.Value.SMS.Version.IsNotNull()
|
&& options.Value.SMS.RegionId.IsNotNull()
|
&& options.Value.SMS.SignName.IsNotNull()
|
&& options.Value.SMS.AccessKeyId.IsNotNull()
|
&& options.Value.SMS.AccessSecret.IsNotNull())
|
{
|
var _templateCode = options.Value.SMS.TemplateCodes[templateCode.ToString()];
|
var _params = new Dictionary<string, string>
|
{
|
{"Action", "SendSms"},
|
{"Version", options.Value.SMS.Version},
|
{"RegionId", options.Value.SMS.RegionId},
|
{"PhoneNumbers", phoneNumber},
|
{"SignName", options.Value.SMS.SignName},
|
{"TemplateCode", _templateCode}
|
};
|
if (!string.IsNullOrWhiteSpace(templateParam))
|
{
|
_params.Add("TemplateParam", templateParam);
|
}
|
var timestamp = DateTime.Now.ToUniversalTime()
|
.ToString("yyyy-MM-dd'T'HH:mm:ss'Z'", CultureInfo.CreateSpecificCulture("en-US"));
|
|
_params.Add("AccessKeyId", options.Value.SMS.AccessKeyId);
|
_params.Add("Timestamp", timestamp);
|
_params.Add("Format", "JSON");
|
_params.Add("SignatureMethod", "HMAC-SHA1");
|
_params.Add("SignatureVersion", "1.0");
|
_params.Add("SignatureNonce", Guid.NewGuid().ToString());
|
|
//排序
|
var sortDic = new SortedDictionary<string, string>(_params, StringComparer.Ordinal);
|
|
//生成Url参数
|
var urlParams = "";
|
foreach (var dic in sortDic)
|
{
|
urlParams += $"{PercentEncode(dic.Key)}={PercentEncode(dic.Value)}&";
|
}
|
urlParams = urlParams.TrimEnd('&');
|
|
//签名
|
var stringToSign = $"GET&{PercentEncode("/")}&{PercentEncode(urlParams)}";
|
string signature = PercentEncode(ToHmacsha1(stringToSign, options.Value.SMS.AccessSecret + "&"));
|
|
var res = await httpRemoteService.GetAsStringAsync($"http://dysmsapi.aliyuncs.com/?Signature={signature}&{urlParams}");
|
var callback = res.JsonTo(new
|
{
|
Code = "",
|
Message = "",
|
RequestId = "",
|
BizId = ""
|
});
|
if (callback == null || callback.Code != "OK")
|
{
|
throw Oops.Oh(EnumErrorCodeType.s510, $"发送短信失败:{callback?.Message},请联系管理员");
|
}
|
}
|
}
|
|
/// <summary>
|
/// 排除敏感字符串
|
/// </summary>
|
/// <param name="value">文本</param>
|
/// <returns>排除后文本</returns>
|
private string PercentEncode(string value)
|
{
|
var stringBuilder = new StringBuilder();
|
var text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
|
var bytes = Encoding.GetEncoding("UTF-8").GetBytes(value);
|
foreach (var b in bytes)
|
{
|
var c = (char)b;
|
if (text.IndexOf(c) >= 0)
|
stringBuilder.Append(c);
|
else
|
stringBuilder.Append("%").Append(
|
string.Format(CultureInfo.InvariantCulture, "{0:X2}", (int)c));
|
}
|
return stringBuilder.ToString();
|
}
|
|
/// <summary>
|
/// HMAC-SHA1加密
|
/// </summary>
|
/// <param name="content"></param>
|
/// <param name="key"></param>
|
/// <returns></returns>
|
private static string ToHmacsha1(string content, string key)
|
{
|
var hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(key));
|
var bytes = hmacsha1.ComputeHash(Encoding.UTF8.GetBytes(content));
|
return Convert.ToBase64String(bytes);
|
}
|
}
|
}
|