Browse Source

短信相关接口与模型

dev_wp
wangping 3 months ago
parent
commit
136ff1f656
  1. 42
      src/1.datas/ATS.NonCustodial.Domain/Entities/Admins/AppSMS.cs
  2. 12
      src/2.services/ATS.NonCustodial.Application/Impl/Admins/AuthService.cs
  3. 170
      src/2.services/ATS.NonCustodial.Application/Impl/Admins/SMSService.cs
  4. 7
      src/3.contracts/ATS.NonCustodial.Application.Contracts/Interfaces/Admins/Auth/IAuthService.cs
  5. 36
      src/3.contracts/ATS.NonCustodial.Application.Contracts/Interfaces/Admins/SMS/ISMSService.cs

42
src/1.datas/ATS.NonCustodial.Domain/Entities/Admins/AppSMS.cs

@ -0,0 +1,42 @@
using ATS.NonCustodial.Domain.Shared.AggRootEntities;
using ATS.NonCustodial.Domain.Shared.Constants;
using ATS.NonCustodial.Domain.Shared.Enums;
using ATS.NonCustodial.Shared.Common.Enums;
using ATS.NonCustodial.Shared.Common.Enums.IM;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Numerics;
namespace ATS.NonCustodial.Domain.Entities.Admins
{
[Table("app_sms")]
public class AppSMS: EntityFull
{
public AppSMS()
{ }
public AppSMS(long id)
{
Id = id;
}
public string phone { get; set; } = string.Empty;
public string content { get; set; } = string.Empty;
public string? code { get; set; }
public DateTime sendTime { get; set; }
public DateTime expiresTime { get; set; }
public bool isUsed { get; set; } = false;
public DateTime? useTime { get; set; }
public string ipAddress { get; set; } = string.Empty;
public string type { get; set; } = "default";
}
}

12
src/2.services/ATS.NonCustodial.Application/Impl/Admins/AuthService.cs

@ -35,6 +35,7 @@ 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
{
@ -387,6 +388,17 @@ namespace ATS.NonCustodial.Application.Impl.Admins
return result;
}
/// <summary>
/// 根据身份证号获取电话号码
/// </summary>
/// <param name="phone"></param>
/// <returns></returns>
public async Task<IResultOutput> GetPhoneByIDCard(string idCard)
{
var user = await _appUserRepository.FindAsync(a => a.ChatPersonType == ChatPersonTypeEnum.SupervisedPerson && a.IdCard == idCard);
return ResultOutput.Ok(user?.Phone);
}
#region Private
/// <summary>

170
src/2.services/ATS.NonCustodial.Application/Impl/Admins/SMSService.cs

@ -0,0 +1,170 @@
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
{
/// <summary>
/// 短信服务
/// </summary>
[DynamicApi(Area = "admin")]
public class SMSService : AdminAppServiceBase, ISMSService, IDynamicApi
{
private readonly IEfRepository<AppSMS?, long> _appSMSRepository;
public SMSService(
IEfRepository<AppSMS?, long> appSMSRepository)
{
_appSMSRepository = appSMSRepository;
}
/// <summary>
/// 发送验证码
/// </summary>
/// <param name="phone"></param>
/// <param name="ipAddress"></param>
/// <param name="type"></param>
/// <returns></returns>
[HttpGet]
[AllowAnonymous]
public async Task<IResultOutput> 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);
}
/// <summary>
/// 校验验证码
/// </summary>
/// <param name="phoneNumber"></param>
/// <param name="code"></param>
/// <param name="type"></param>
/// <returns></returns>
public async Task<bool> 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;
}
/// <summary>
/// 发送前校验
/// </summary>
/// <param name="phone"></param>
/// <returns></returns>
public async Task<bool> 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
/// <summary>
/// 发送短信
/// </summary>
/// <param name="phone"></param>
/// <param name="msg"></param>
/// <returns></returns>
private bool SendSMS(string phone, string msg)
{
return true;
}
#endregion
}
}

7
src/3.contracts/ATS.NonCustodial.Application.Contracts/Interfaces/Admins/Auth/IAuthService.cs

@ -79,5 +79,12 @@ namespace ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Auth
/// <param name="user">用户信息</param>
/// <returns></returns>
Task<string> GetToken(AuthLoginOutput? user);
/// <summary>
/// 根据身份证号获取电话号码
/// </summary>
/// <param name="phone"></param>
/// <returns></returns>
Task<IResultOutput> GetPhoneByIDCard(string idCard);
}
}

36
src/3.contracts/ATS.NonCustodial.Application.Contracts/Interfaces/Admins/SMS/ISMSService.cs

@ -0,0 +1,36 @@
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Auth.Input;
using ATS.NonCustodial.Application.Contracts.Interfaces.Admins.Auth.Output;
using ATS.NonCustodial.Domain.Shared.Enums;
using ATS.NonCustodial.Shared.Captcha.Dto;
using ATS.NonCustodial.Shared.Common.Dtos;
using ATS.NonCustodial.Shared.Common.UnifiedResults;
namespace ATS.NonCustodial.Application.Contracts.Interfaces.Admins.SMS
{
public interface ISMSService
{
/// <summary>
/// 发送验证码
/// </summary>
/// <param name="phone"></param>
/// <returns></returns>
Task<IResultOutput> SendCheckCodeSMS(string phone, string ipAddress = "", string type = "CheckCode");
/// <summary>
/// 校验验证码
/// </summary>
/// <param name="phoneNumber"></param>
/// <param name="code"></param>
/// <param name="type"></param>
/// <returns></returns>
Task<bool> CheckCodeAsync(string phoneNumber, string code, string type = "default");
/// <summary>
/// 发送前校验
/// </summary>
/// <param name="phone"></param>
/// <returns></returns>
Task<bool> CanSendCodeAsync(string phone);
}
}
Loading…
Cancel
Save