using ATS.NonCustodial.Application.Base; using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Auth; using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Auth.Input; using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Auth.Output; using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.SMS; using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.User; using ATS.NonCustodial.Application.Contracts.Interfaces.Logs.LoginLog.Input; using ATS.NonCustodial.Domain.Entities.Admins; using ATS.NonCustodial.Domain.Entities.Business; using ATS.NonCustodial.Domain.Entities.Business.EarlyWarning; using ATS.NonCustodial.Domain.Shared.Enums; using ATS.NonCustodial.Domain.Shared.OrmRepositories.Basic.EfCore; using ATS.NonCustodial.DynamicApi; using ATS.NonCustodial.DynamicApi.Attributes; using ATS.NonCustodial.Shared.Captcha.Dto; using ATS.NonCustodial.Shared.Common.Attributes; using ATS.NonCustodial.Shared.Common.Auth; using ATS.NonCustodial.Shared.Common.Constants; using ATS.NonCustodial.Shared.Common.Dtos; using ATS.NonCustodial.Shared.Common.Enums; using ATS.NonCustodial.Shared.Common.UnifiedResults; using ATS.NonCustodial.Shared.Configurations.Options; using ATS.NonCustodial.Shared.Extensions; using ATS.NonCustodial.Shared.Helpers; using ATS.NonCustodial.Shared.Helpers.Core.Hash; using ATS.NonCustodial.Shared.Helpers.Http; using ATS.NonCustodial.Shared.Tools.Captcha; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using NPOI.SS.Formula.Functions; using NPOI.Util; using StackExchange.Profiling; using System.Diagnostics; using System.Security.Claims; using static System.Runtime.InteropServices.JavaScript.JSType; namespace ATS.NonCustodial.Application.Impl.Admins { /// /// 短信服务 /// [DynamicApi(Area = "admin")] public class SMSService : AdminAppServiceBase, ISMSService, IDynamicApi { private readonly IEfRepository _appSMSRepository; public SMSService( IEfRepository appSMSRepository) { _appSMSRepository = appSMSRepository; } /// /// 发送验证码 /// /// /// /// /// [HttpGet] [AllowAnonymous] public async Task SendCheckCodeSMS(string phone, string ipAddress = "", string type = "CheckCode") { // 检查是否可以发送(一分钟内只能发送一次) if (!await CanSendCodeAsync(phone)) { return ResultOutput.NotOk("请求过于频繁,请稍后再试"); } // 生成随机验证码(6位数字) var random = new Random(); var code = random.Next(100000, 999999).ToString(); // 创建验证码记录 var addSMS = new AppSMS { phone = phone, code = code, sendTime = DateTime.UtcNow, expiresTime = DateTime.UtcNow.AddMinutes(5), // 5分钟有效期 ipAddress = ipAddress, type = type }; // 发送短信 var sendResult = SendSMS(phone, code); if (!sendResult) { return ResultOutput.NotOk("短信发送失败,请稍后重试"); } var sms = await _appSMSRepository.InsertAsync(addSMS); return ResultOutput.Ok(true); } /// /// 校验验证码 /// /// /// /// /// public async Task CheckCodeAsync(string phoneNumber, string code, string type = "default") { var now = DateTime.UtcNow; // 查找有效的验证码 var validCode = await _appSMSRepository.AsQueryable() .Where(v => v.phone == phoneNumber && v.code == code && v.type == type && !v.isUsed && v.expiresTime > now) .OrderByDescending(v => v.sendTime) .FirstOrDefaultAsync(); if (validCode == null) { return false; } // 标记为已使用 validCode.isUsed = true; validCode.useTime = now; await _appSMSRepository.UpdateAsync(validCode); return true; } /// /// 发送前校验 /// /// /// public async Task CanSendCodeAsync(string phone) { var oneMinuteAgo = DateTime.UtcNow.AddMinutes(-1); // 检查一分钟内是否有发送记录 var recentCode = await _appSMSRepository.AsQueryable() .Where(v => v.phone == phone && v.sendTime > oneMinuteAgo) .OrderByDescending(v => v.sendTime) .FirstOrDefaultAsync(); return recentCode == null; } #region Private /// /// 发送短信 /// /// /// /// private bool SendSMS(string phone, string msg) { return true; } #endregion } }