通用功能提取

This commit is contained in:
马梓彭 2026-03-30 20:47:40 +08:00
parent 653ee3da0a
commit 16b000add2
7 changed files with 115 additions and 101 deletions

View File

@ -2,7 +2,6 @@ using YD_Event.Application.AppUser.Dtos;
using YD_Event.Application.Auth;
using YD_Event.Core.Entities;
using AppUserEntity = YD_Event.Core.Entities.AppUser;
using YD_Event.Core.Infrastructure.Aliyun.Ocr;
using YD_Event.Core.Enum;
using Mapster;
@ -16,17 +15,14 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
private readonly ISqlSugarRepository<AppUserEntity> _appUserRep;
private readonly ISqlSugarClient _db;
private readonly AuthManager _authManager;
private readonly OcrService _ocrService;
public AppUserService(ISqlSugarRepository<AppUserEntity> appUserRep,
ISqlSugarClient db,
AuthManager authManager,
OcrService ocrService) : base(appUserRep)
AuthManager authManager) : base(appUserRep)
{
_appUserRep = appUserRep;
_db = db;
_authManager = authManager;
_ocrService = ocrService;
}
/// <summary>
@ -317,53 +313,5 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
await _appUserRep.UpdateAsync(entity);
}
/// <summary>
/// 识别身份证信息
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("member/recognize/idcard")]
[DisplayName("OCR识别身份证")]
public async Task<IdCardRecognitionResult> RecognizeIdCard([FromBody] AthleteOcrInput input)
{
// 输入验证
if (string.IsNullOrWhiteSpace(input.ImageUrl))
{
throw Oops.Bah("护照图片URL不能为空");
}
// URL格式验证(简单的格式检查)
if (!input.ImageUrl.StartsWith("http://") && !input.ImageUrl.StartsWith("https://"))
{
throw Oops.Bah("请输入有效的图片URL地址");
}
return await _ocrService.RecognizeIdCardAsync(input.ImageUrl);
}
/// <summary>
/// 识别护照信息
/// </summary>
/// <param name="input">护照图片URL输入</param>
/// <returns>护照识别结果</returns>
[HttpPost("member/recognize/passport")]
[DisplayName("OCR识别护照")]
public async Task<PassportRecognitionResult> RecognizePassport([FromBody] AthleteOcrInput input)
{
// 输入验证
if (string.IsNullOrWhiteSpace(input.ImageUrl))
{
throw Oops.Bah("护照图片URL不能为空");
}
// URL格式验证(简单的格式检查)
if (!input.ImageUrl.StartsWith("http://") && !input.ImageUrl.StartsWith("https://"))
{
throw Oops.Bah("请输入有效的图片URL地址");
}
return await _ocrService.RecognizePassportAsync(input.ImageUrl);
}
#endregion
}

View File

@ -4,7 +4,7 @@ using YD_Event.Core.Enum;
using SqlSugar;
using Easy.Core;
namespace YD_Event.Application.AppUser.Dtos;
namespace YD_Event.Application.Common.Dtos;
/// <summary>
/// OCR识别输入

View File

@ -0,0 +1,13 @@
#nullable enable
using System.ComponentModel.DataAnnotations;
namespace YD_Event.Application.Common.Dtos;
public class SendVerificationCodeInput
{
[Required(ErrorMessage = "手机号不能为空")]
[RegularExpression(@"^1[3456789]\d{9}$", ErrorMessage = "手机号格式不正确")]
public string Phone { get; set; } = null!;
public string? Code { get; set; }
}

View File

@ -0,0 +1,50 @@
using YD_Event.Application.Common.Dtos;
using CoreOcrService = YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrService;
using YD_Event.Core.Infrastructure.Aliyun.Ocr;
namespace YD_Event.Application.Common;
[ApiDescriptionSettings("通用服务")]
public class OcrService : IDynamicApiController, ITransient
{
private readonly CoreOcrService _ocrService;
public OcrService(CoreOcrService ocrService)
{
_ocrService = ocrService;
}
[HttpPost("recognize/idcard")]
[DisplayName("OCR识别身份证")]
public async Task<IdCardRecognitionResult> RecognizeIdCard([FromBody] AthleteOcrInput input)
{
if (string.IsNullOrWhiteSpace(input.ImageUrl))
{
throw Oops.Bah("图片URL不能为空");
}
if (!input.ImageUrl.StartsWith("http://") && !input.ImageUrl.StartsWith("https://"))
{
throw Oops.Bah("请输入有效的图片URL地址");
}
return await _ocrService.RecognizeIdCardAsync(input.ImageUrl);
}
[HttpPost("recognize/passport")]
[DisplayName("OCR识别护照")]
public async Task<PassportRecognitionResult> RecognizePassport([FromBody] AthleteOcrInput input)
{
if (string.IsNullOrWhiteSpace(input.ImageUrl))
{
throw Oops.Bah("图片URL不能为空");
}
if (!input.ImageUrl.StartsWith("http://") && !input.ImageUrl.StartsWith("https://"))
{
throw Oops.Bah("请输入有效的图片URL地址");
}
return await _ocrService.RecognizePassportAsync(input.ImageUrl);
}
}

View File

@ -0,0 +1,38 @@
using Microsoft.Extensions.Caching.Memory;
using YD_Event.Application.Common.Dtos;
using YD_Event.Application.Sms;
namespace YD_Event.Application.Common;
[ApiDescriptionSettings("通用服务")]
public class SmsService : IDynamicApiController, ITransient
{
private readonly AliyunSmsService _smsService;
private readonly IMemoryCache _memoryCache;
public SmsService(AliyunSmsService smsService, IMemoryCache memoryCache)
{
_smsService = smsService;
_memoryCache = memoryCache;
}
[HttpPost("sms/sendVerificationCode")]
[DisplayName("发送短信验证码")]
[AllowAnonymous]
public async Task SendVerificationCode([FromBody] SendVerificationCodeInput input)
{
var limitCacheKey = $"sms:code:limit:{input.Phone}";
if (_memoryCache.TryGetValue(limitCacheKey, out _))
{
throw Oops.Bah("发送太频繁,请稍后再试");
}
string code = input.Code ?? new Random().Next(100000, 999999).ToString();
await _smsService.SendVerificationCode(input.Phone, code);
var codeCacheKey = $"sms:code:{input.Phone}";
_memoryCache.Set(codeCacheKey, code, TimeSpan.FromMinutes(5));
_memoryCache.Set(limitCacheKey, "1", TimeSpan.FromMinutes(1));
}
}

View File

@ -35,22 +35,6 @@ public class MerchantCertificationService : BaseService<MerchantCertification>,
_smsService = smsService;
}
/// <summary>
/// 发送验证码
/// </summary>
[DisplayName("发送验证码")]
[HttpPost("sendVerificationCode")]
[AllowAnonymous]
public async Task SendVerificationCode([FromQuery] string phone)
{
if (string.IsNullOrWhiteSpace(phone) || !System.Text.RegularExpressions.Regex.IsMatch(phone, @"^1[3456789]\d{9}$"))
throw Oops.Bah("手机号格式不正确");
var code = new Random().Next(100000, 999999).ToString();
_memoryCache.Set($"verification_code_{phone}", code, TimeSpan.FromMinutes(5));
await _smsService.SendVerificationCodeAsync(phone, code);
}
/// <summary>
/// 提交单位认证
/// </summary>
@ -58,7 +42,7 @@ public class MerchantCertificationService : BaseService<MerchantCertification>,
[HttpPost("submitCertification")]
public async Task SubmitCertification(SubmitCertificationInput input)
{
if (!_memoryCache.TryGetValue($"verification_code_{input.ContactPhone}", out string? cachedCode) || cachedCode != input.VerificationCode)
if (!_memoryCache.TryGetValue($"sms:code:{input.ContactPhone}", out string? cachedCode) || cachedCode != input.VerificationCode)
{
throw Oops.Bah("验证码错误或已过期");
}
@ -98,7 +82,7 @@ public class MerchantCertificationService : BaseService<MerchantCertification>,
await _repository.UpdateAsync(certification);
}
_memoryCache.Remove($"verification_code_{input.ContactPhone}");
_memoryCache.Remove($"sms:code:{input.ContactPhone}");
}
/// <summary>

View File

@ -107,20 +107,6 @@
<param name="input"></param>
<returns></returns>
</member>
<member name="M:YD_Event.Application.AppUser.AppUserService.RecognizeIdCard(YD_Event.Application.AppUser.Dtos.AthleteOcrInput)">
<summary>
识别身份证信息
</summary>
<param name="input"></param>
<returns></returns>
</member>
<member name="M:YD_Event.Application.AppUser.AppUserService.RecognizePassport(YD_Event.Application.AppUser.Dtos.AthleteOcrInput)">
<summary>
识别护照信息
</summary>
<param name="input">护照图片URL输入</param>
<returns>护照识别结果</returns>
</member>
<member name="T:YD_Event.Application.AppUser.Dtos.AppUserPageInput">
<summary>
普通用户分页查询输入
@ -386,16 +372,6 @@
审核备注
</summary>
</member>
<member name="T:YD_Event.Application.AppUser.Dtos.AthleteOcrInput">
<summary>
OCR识别输入
</summary>
</member>
<member name="P:YD_Event.Application.AppUser.Dtos.AthleteOcrInput.ImageUrl">
<summary>
图片URL
</summary>
</member>
<member name="T:YD_Event.Application.Auth.AuthManager">
<summary>
用户授权信息
@ -2774,6 +2750,16 @@
生成自定义 Token
</summary>
</member>
<member name="T:YD_Event.Application.Common.Dtos.AthleteOcrInput">
<summary>
OCR识别输入
</summary>
</member>
<member name="P:YD_Event.Application.Common.Dtos.AthleteOcrInput.ImageUrl">
<summary>
图片URL
</summary>
</member>
<member name="T:YD_Event.Application.Coupon.CouponService">
<summary>
优惠券服务
@ -6468,11 +6454,6 @@
单位认证管理
</summary>
</member>
<member name="M:YD_Event.Application.Merchant.MerchantCertificationService.SendVerificationCode(System.String)">
<summary>
发送验证码
</summary>
</member>
<member name="M:YD_Event.Application.Merchant.MerchantCertificationService.SubmitCertification(YD_Event.Application.Merchant.Dtos.SubmitCertificationInput)">
<summary>
提交单位认证