// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 // // 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 // // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! using Admin.NET.Core.Service; using Admin.NET.Core; using Furion.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Extensions.Options; using Dm.util; using Aop.Api.Domain; using Furion.FriendlyException; using Furion.DataValidation; using static QRCoder.PayloadGenerator; using System.Net; using Org.BouncyCastle.Asn1.Ocsp; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Furion.DynamicApiController; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using Yitter.IdGenerator; using Lazy.Captcha.Core; using Furion; namespace FZCZTB.NET.SYSService.MSM; /// /// 政采短信服务 /// [AllowAnonymous] [ApiDescriptionSettings("FZCAPISYS",Order = 149)] public class ZCSMSService : IDynamicApiController,ITransient { private readonly SMSConfigOptions _smsOptions; private readonly SysCacheService _sysCacheService; private readonly ICaptcha _captcha; public ZCSMSService(IOptions smsOptions, SysCacheService sysCacheService, ICaptcha captcha ) { _smsOptions = smsOptions.Value; _sysCacheService = _sysCacheService; _captcha = captcha; } /// /// 根据藏用模版格式化短信内容 会自动贴上标签 /// /// 需要替换的内容,用于替换末班内容的code部分 /// [NonAction] public string FormartMessage(string? Code, string Key = "VCode") { var Temp= _smsOptions.lingKai.Templates.Where(x => x.TemplateCode == Key).FirstOrDefault(); if ( Temp != null ) { if(Code != null) { return Temp.Content.replace("${code}", Code) + Temp.SignName; } else return Temp.Content+Temp.SignName; } if (Code == null) Oops.Oh("短信内容为空"); return Code; } /// /// 发送短信 /// /// 要替换的内容 [NonAction] public async Task SendSMSAsync(string Content,string Phone) { if (!Phone.TryValidate(ValidationTypes.PhoneNumber).IsValid) throw Oops.Oh("请正确填写手机号码"); if( string.IsNullOrEmpty(Content)) throw Oops.Oh("请填写正确的手机号码"); string postdata1 = "CorpID=" + _smsOptions.lingKai.Number + "&Pwd=" + _smsOptions.lingKai.AccountPassPassword + "&Mobile=" + Phone + "&Content="+ Content + "&SendTime="; string code = (string)await HttpPost(_smsOptions.lingKai.Url, postdata1); var data = Convert.ToInt64(code); if (data > 0) { return ; } Oops.Oh($"发送短信失败,错误码{data}"); } /// /// 获取验证码 🔖 /// /// [AllowAnonymous] [SuppressMonitor] [DisplayName("获取验证码")] public dynamic GetCaptcha() { var codeId = YitIdHelper.NextId().ToString(); var captcha = _captcha.Generate(codeId); var expirySeconds = App.GetOptions()?.ExpirySeconds ?? 60; return new { Id = codeId, Img = captcha.Base64, ExpirySeconds = expirySeconds }; } /// /// 校验短信验证码 /// /// /// [AllowAnonymous] [DisplayName("校验短信验证码")] public bool VerifyCode(SmsVerifyCodeInput input) { var verifyCode = _sysCacheService.Get($"{CacheConst.KeyPhoneVerCode}{input.Phone}"); if (string.IsNullOrWhiteSpace(verifyCode)) throw Oops.Oh("验证码不存在或已失效,请重新获取!"); if (verifyCode != input.Code) throw Oops.Oh("验证码错误!"); return true; } /// /// 发送验证短信,要要验证码 需要输入校验,避免电脑攻击 /// /// 电话号码 /// 图片校验数据 /// 检验的ID /// [AllowAnonymous] [DisplayName("发送验证码")] public async Task SendSMS([Required] string phoneNumber , [Required] string VerifyCode, [Required] string VerifyCodeId) { if (!phoneNumber.TryValidate(ValidationTypes.PhoneNumber).IsValid) throw Oops.Oh("请正确填写手机号码"); // 校验验证码 if (!_captcha.Validate(VerifyCodeId, VerifyCode)) throw Oops.Oh(ErrorCodeEnum.D0008); _captcha.Generate(VerifyCodeId); // 生成随机验证码 var random = new Random(); var verifyCode = random.Next(100000, 999999); var templateParam = new { code = verifyCode }; var code= FormartMessage(verifyCode.toString()); await SendSMSAsync(code, phoneNumber); _sysCacheService.Set($"{CacheConst.KeyPhoneVerCode}{phoneNumber}", verifyCode, TimeSpan.FromSeconds(_smsOptions.lingKai.VerifyTimeOut)); await Task.CompletedTask; } /// /// 发送验证码 /// /// 链接 /// 验证码 /// private async Task HttpPost(string Url, string postDataStr) { //HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url); //request.Method = "POST"; //request.ContentType = "application/x-www-form-urlencoded;charset=gb2312"; //byte[] postData = Encoding.GetEncoding("gb2312").GetBytes(postDataStr); //request.ContentLength = postData.Length; //Stream myRequestStream = request.GetRequestStream(); //myRequestStream.Write(postData, 0, postData.Length); //myRequestStream.Close(); //HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); //Stream myResponseStream = response.GetResponseStream(); //StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("gb2312")); //string retString = myStreamReader.ReadToEnd(); //myStreamReader.Close(); //myResponseStream.Close(); //return retString; // 创建 HttpClient 实例 using var httpClient = new HttpClient(); // 准备要发送的内容,设置编码和内容类型 var content = new StringContent(postDataStr, Encoding.GetEncoding("gb2312"), "application/x-www-form-urlencoded"); // 发送 POST 请求 var response = await httpClient.PostAsync(Url, content); // 确保请求成功,若失败则抛出异常 response.EnsureSuccessStatusCode(); // 读取响应内容 return await response.Content.ReadAsStringAsync(); } }