sunpengfei
2025-09-30 a6e5a2e630a4a1dcfd9def94c20bde6bec89f96f
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
using Aop.Api.Domain;
using Azure;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.FriendlyException;
using Furion.HttpRemote;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static System.Net.WebRequestMethods;
 
namespace ApiTools.Core
{
    public class AliyunSmsService : ISmsService, ITransient
    {
        private readonly IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog;
        private readonly IOptions<AliyunOptions> options;
        private readonly IHttpRemoteService httpRemoteService;
 
        public AliyunSmsService(
            IRepository<ThreeResourceLog, LogDbContextLocator> repThreeResourceLog,
            IOptions<AliyunOptions> options,
            IHttpRemoteService httpRemoteService)
        {
            this.repThreeResourceLog = repThreeResourceLog;
            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<SmsResponse> SendAsync(string phoneNumber, EnumSmsTemplateCode templateCode, object templateParam, CancellationToken cancellationToken)
        {
            AlibabaCloud.OpenApiClient.Models.Config config = new AlibabaCloud.OpenApiClient.Models.Config
            {
                AccessKeyId = options.Value.SMS.AccessKeyId,
                AccessKeySecret = options.Value.SMS.AccessSecret,
                Endpoint = "dysmsapi.aliyuncs.com"
            };
            var client = new AlibabaCloud.SDK.Dysmsapi20170525.Client(config);
            AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest
            {
                PhoneNumbers = phoneNumber,
                SignName = options.Value.SMS.SignName,
                TemplateCode = options.Value.SMS.TemplateCodes[templateCode.ToString()],
                TemplateParam = templateParam.ToJson()
            };
            var log = new ThreeResourceLog
            {
                Method = EnumResourceMethod.Get,
                Domain = "http://dysmsapi.aliyuncs.com",
                Request = "SendSms",
            };
            await repThreeResourceLog.InsertNowAsync(log);
            var stopwatch = Stopwatch.StartNew();
            var response = client.SendSmsWithOptions(sendSmsRequest, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
            log.UpdatedTime = DateTimeOffset.Now;
            stopwatch.Stop();
            log.ElapsedMilliseconds = stopwatch.ElapsedMilliseconds;
            log.IsSuccess = response.Body.Code == "OK";
            await repThreeResourceLog.UpdateNowAsync(log);
 
            var result = new SmsResponse
            {
                Status = log.IsSuccess
                    ? EnumSmsStatus.InProcess
                    : EnumSmsStatus.Fail,
                Code = response.Body.Code,
                Message = response.Body.Message,
                RequestId = response.Body.BizId
            };
            if (result.Status == EnumSmsStatus.Fail && result.Message.Contains("流控"))
            {
                result.Message = "操作频繁";
            }
 
            //var response2 = client.QuerySendDetailsWithOptions(new AlibabaCloud.SDK.Dysmsapi20170525.Models.QuerySendDetailsRequest
            //{
            //    PhoneNumber = phoneNumber,
            //    BizId = response1.Body.BizId,
            //    SendDate = DateTime.Now.ToString("yyyyMMdd"),
            //    PageSize = 20,
            //    CurrentPage = 1
            //}, new AlibabaCloud.TeaUtil.Models.RuntimeOptions());
            //Console.WriteLine();
 
            return result;
        }
 
        /// <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);
        }
    }
}