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
}
}