From 16b000add2177263161e64d8d1a0019ecbb4fa9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E6=A2=93=E5=BD=AD?= Date: Mon, 30 Mar 2026 20:47:40 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E7=94=A8=E5=8A=9F=E8=83=BD=E6=8F=90?= =?UTF-8?q?=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppUser/AppUserService.cs | 54 +------------------ .../Dtos/OcrInput.cs} | 2 +- .../Common/Dtos/SendVerificationCodeInput.cs | 13 +++++ YD_Event.Application/Common/OcrService.cs | 50 +++++++++++++++++ YD_Event.Application/Common/SmsService.cs | 38 +++++++++++++ .../Merchant/MerchantCertificationService.cs | 20 +------ YD_Event.Application/YD_Event.Application.xml | 39 ++++---------- 7 files changed, 115 insertions(+), 101 deletions(-) rename YD_Event.Application/{AppUser/Dtos/AthleteDtos.cs => Common/Dtos/OcrInput.cs} (89%) create mode 100644 YD_Event.Application/Common/Dtos/SendVerificationCodeInput.cs create mode 100644 YD_Event.Application/Common/OcrService.cs create mode 100644 YD_Event.Application/Common/SmsService.cs diff --git a/YD_Event.Application/AppUser/AppUserService.cs b/YD_Event.Application/AppUser/AppUserService.cs index 308b546..c85858a 100644 --- a/YD_Event.Application/AppUser/AppUserService.cs +++ b/YD_Event.Application/AppUser/AppUserService.cs @@ -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, ITransient private readonly ISqlSugarRepository _appUserRep; private readonly ISqlSugarClient _db; private readonly AuthManager _authManager; - private readonly OcrService _ocrService; public AppUserService(ISqlSugarRepository appUserRep, ISqlSugarClient db, - AuthManager authManager, - OcrService ocrService) : base(appUserRep) + AuthManager authManager) : base(appUserRep) { _appUserRep = appUserRep; _db = db; _authManager = authManager; - _ocrService = ocrService; } /// @@ -317,53 +313,5 @@ public class AppUserService : BaseService, ITransient await _appUserRep.UpdateAsync(entity); } - /// - /// 识别身份证信息 - /// - /// - /// - [HttpPost("member/recognize/idcard")] - [DisplayName("OCR识别身份证")] - public async Task 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); - } - - /// - /// 识别护照信息 - /// - /// 护照图片URL输入 - /// 护照识别结果 - [HttpPost("member/recognize/passport")] - [DisplayName("OCR识别护照")] - public async Task 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 } diff --git a/YD_Event.Application/AppUser/Dtos/AthleteDtos.cs b/YD_Event.Application/Common/Dtos/OcrInput.cs similarity index 89% rename from YD_Event.Application/AppUser/Dtos/AthleteDtos.cs rename to YD_Event.Application/Common/Dtos/OcrInput.cs index 482dc96..39ffb44 100644 --- a/YD_Event.Application/AppUser/Dtos/AthleteDtos.cs +++ b/YD_Event.Application/Common/Dtos/OcrInput.cs @@ -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; /// /// OCR识别输入 diff --git a/YD_Event.Application/Common/Dtos/SendVerificationCodeInput.cs b/YD_Event.Application/Common/Dtos/SendVerificationCodeInput.cs new file mode 100644 index 0000000..50146c4 --- /dev/null +++ b/YD_Event.Application/Common/Dtos/SendVerificationCodeInput.cs @@ -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; } +} diff --git a/YD_Event.Application/Common/OcrService.cs b/YD_Event.Application/Common/OcrService.cs new file mode 100644 index 0000000..23fb883 --- /dev/null +++ b/YD_Event.Application/Common/OcrService.cs @@ -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 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 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); + } +} diff --git a/YD_Event.Application/Common/SmsService.cs b/YD_Event.Application/Common/SmsService.cs new file mode 100644 index 0000000..c48c1eb --- /dev/null +++ b/YD_Event.Application/Common/SmsService.cs @@ -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)); + } +} diff --git a/YD_Event.Application/Merchant/MerchantCertificationService.cs b/YD_Event.Application/Merchant/MerchantCertificationService.cs index c1e086f..1bb1641 100644 --- a/YD_Event.Application/Merchant/MerchantCertificationService.cs +++ b/YD_Event.Application/Merchant/MerchantCertificationService.cs @@ -35,22 +35,6 @@ public class MerchantCertificationService : BaseService, _smsService = smsService; } - /// - /// 发送验证码 - /// - [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); - } - /// /// 提交单位认证 /// @@ -58,7 +42,7 @@ public class MerchantCertificationService : BaseService, [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, await _repository.UpdateAsync(certification); } - _memoryCache.Remove($"verification_code_{input.ContactPhone}"); + _memoryCache.Remove($"sms:code:{input.ContactPhone}"); } /// diff --git a/YD_Event.Application/YD_Event.Application.xml b/YD_Event.Application/YD_Event.Application.xml index 227ddbf..dc6e7f0 100644 --- a/YD_Event.Application/YD_Event.Application.xml +++ b/YD_Event.Application/YD_Event.Application.xml @@ -107,20 +107,6 @@ - - - 识别身份证信息 - - - - - - - 识别护照信息 - - 护照图片URL输入 - 护照识别结果 - 普通用户分页查询输入 @@ -386,16 +372,6 @@ 审核备注 - - - OCR识别输入 - - - - - 图片URL - - 用户授权信息 @@ -2774,6 +2750,16 @@ 生成自定义 Token + + + OCR识别输入 + + + + + 图片URL + + 优惠券服务 @@ -6468,11 +6454,6 @@ 单位认证管理 - - - 发送验证码 - - 提交单位认证