护照识别

This commit is contained in:
马梓彭 2026-03-25 16:53:22 +08:00
parent 26c25f1e06
commit 06d52d56db
6 changed files with 293 additions and 22 deletions

View File

@ -318,12 +318,48 @@ public class AppUserService : BaseService<AppUserEntity>, ITransient
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("member/ocr")]
[HttpPost("member/recognize/idcard")]
[DisplayName("OCR识别身份证")]
public async Task<OcrResult> RecognizeIdCard([FromBody] AthleteOcrInput input)
{
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

@ -114,6 +114,13 @@
<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>
普通用户分页查询输入

View File

@ -2,9 +2,9 @@
namespace YD_Event.Core.Infrastructure.Aliyun.Ocr;
/// <summary>
/// OCR识别结果
/// 身份证识别结果
/// </summary>
public class OcrResult
public class IdCardRecognitionResult
{
/// <summary>
/// 是否成功
@ -32,7 +32,7 @@ public class OcrResult
public string? IdCardNumber { get; set; }
/// <summary>
/// 出生日期 (可选)
/// 出生日期
/// </summary>
public string? BirthDate { get; set; }
}
}

View File

@ -28,11 +28,11 @@ public class OcrService : ITransient
/// </summary>
/// <param name="imageUrl">图片URL</param>
/// <returns></returns>
public async Task<OcrResult> RecognizeIdCardAsync(string imageUrl)
public async Task<IdCardRecognitionResult> RecognizeIdCardAsync(string imageUrl)
{
if (string.IsNullOrWhiteSpace(imageUrl))
{
return new OcrResult { Success = false, Message = "图片URL不能为空" };
return new IdCardRecognitionResult { Success = false, Message = "图片URL不能为空" };
}
try
@ -67,23 +67,101 @@ public class OcrService : ITransient
if (!string.IsNullOrEmpty(idNumber))
{
return new OcrResult
return new IdCardRecognitionResult
{
Success = true,
Name = name,
Gender = sex,
IdCardNumber = idNumber,
BirthDate = birthDate,
Message = "识别成功"
Message = "身份证识别成功"
};
}
}
return new OcrResult { Success = false, Message = "未识别到有效身份证信息" };
return new IdCardRecognitionResult { Success = false, Message = "未识别到有效身份证信息" };
}
catch (Exception ex)
{
return new OcrResult { Success = false, Message = $"OCR识别异常: {ex.Message}" };
return new IdCardRecognitionResult { Success = false, Message = $"身份证OCR识别异常: {ex.Message}" };
}
}
/// <summary>
/// 识别护照信息
/// </summary>
/// <param name="imageUrl">护照图片URL</param>
/// <returns></returns>
public async Task<PassportRecognitionResult> RecognizePassportAsync(string imageUrl)
{
if (string.IsNullOrWhiteSpace(imageUrl))
{
return new PassportRecognitionResult { Success = false, Message = "图片URL不能为空" };
}
try
{
var config = new AlibabaCloud.OpenApiClient.Models.Config
{
AccessKeyId = _options.AccessKeyId,
AccessKeySecret = _options.AccessKeySecret,
Endpoint = _options.Endpoint
};
var client = new Client(config);
var request = new RecognizePassportRequest
{
Url = imageUrl
};
var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
var response = await client.RecognizePassportWithOptionsAsync(request, runtime);
if (response.Body != null && !string.IsNullOrEmpty(response.Body.Data))
{
// Data是一个JSON字符串,包含识别结果
var json = JObject.Parse(response.Body.Data);
// 解析护照信息字段
var name = (string?)json.SelectToken("..data.name") ?? (string?)json.SelectToken("..name");
var passportNumber = (string?)json.SelectToken("..data.passportNumber") ?? (string?)json.SelectToken("..passportNumber");
var nationality = (string?)json.SelectToken("..data.nationality") ?? (string?)json.SelectToken("..nationality");
var gender = (string?)json.SelectToken("..data.sex") ?? (string?)json.SelectToken("..gender") ?? (string?)json.SelectToken("..sex");
var birthDate = (string?)json.SelectToken("..data.birthDate") ?? (string?)json.SelectToken("..birthDate");
var issuingAuthority = (string?)json.SelectToken("..data.issuingAuthority") ?? (string?)json.SelectToken("..issuingAuthority");
var issueDate = (string?)json.SelectToken("..data.issueDate") ?? (string?)json.SelectToken("..issueDate");
var expiryDate = (string?)json.SelectToken("..data.expiryDate") ?? (string?)json.SelectToken("..expiryDate");
// 新增字段
var validToDate = (string?)json.SelectToken("..data.validToDate") ?? (string?)json.SelectToken("..validToDate");
var birthDateYmd = (string?)json.SelectToken("..data.birthDateYmd") ?? (string?)json.SelectToken("..birthDateYmd");
var issueDateYmd = (string?)json.SelectToken("..data.issueDateYmd") ?? (string?)json.SelectToken("..issueDateYmd");
if (!string.IsNullOrEmpty(passportNumber))
{
return new PassportRecognitionResult
{
Success = true,
Name = name,
Gender = gender,
PassportNumber = passportNumber,
Nationality = nationality,
BirthDate = birthDate,
IssuingAuthority = issuingAuthority,
IssueDate = issueDate,
ExpiryDate = expiryDate,
ValidToDate = validToDate,
BirthDateYmd = birthDateYmd,
IssueDateYmd = issueDateYmd,
Message = "护照识别成功"
};
}
}
return new PassportRecognitionResult { Success = false, Message = "未识别到有效护照信息" };
}
catch (Exception ex)
{
return new PassportRecognitionResult { Success = false, Message = $"护照OCR识别异常: {ex.Message}" };
}
}
}

View File

@ -0,0 +1,73 @@
#nullable enable
namespace YD_Event.Core.Infrastructure.Aliyun.Ocr;
/// <summary>
/// 护照识别结果
/// </summary>
public class PassportRecognitionResult
{
/// <summary>
/// 是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 错误信息
/// </summary>
public string? Message { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 性别
/// </summary>
public string? Gender { get; set; }
/// <summary>
/// 护照号码
/// </summary>
public string? PassportNumber { get; set; }
/// <summary>
/// 国籍
/// </summary>
public string? Nationality { get; set; }
/// <summary>
/// 签发地点
/// </summary>
public string? IssuingAuthority { get; set; }
/// <summary>
/// 签发日期
/// </summary>
public string? IssueDate { get; set; }
/// <summary>
/// 有效期至
/// </summary>
public string? ExpiryDate { get; set; }
/// <summary>
/// 出生日期
/// </summary>
public string? BirthDate { get; set; }
/// <summary>
/// 有效期至(格式化显示)
/// </summary>
public string? ValidToDate { get; set; }
/// <summary>
/// 出生日期(纯数字格式)
/// </summary>
public string? BirthDateYmd { get; set; }
/// <summary>
/// 签发日期(格式化显示)
/// </summary>
public string? IssueDateYmd { get; set; }
}

View File

@ -4332,39 +4332,39 @@
赞助单位
</summary>
</member>
<member name="T:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult">
<member name="T:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult">
<summary>
OCR识别结果
身份证识别结果
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult.Success">
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult.Success">
<summary>
是否成功
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult.Message">
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult.Message">
<summary>
错误信息
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult.Name">
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult.Name">
<summary>
姓名
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult.Gender">
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult.Gender">
<summary>
性别
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult.IdCardNumber">
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult.IdCardNumber">
<summary>
身份证号
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrResult.BirthDate">
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.IdCardRecognitionResult.BirthDate">
<summary>
出生日期 (可选)
出生日期
</summary>
</member>
<member name="T:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrService">
@ -4379,6 +4379,83 @@
<param name="imageUrl">图片URL</param>
<returns></returns>
</member>
<member name="M:YD_Event.Core.Infrastructure.Aliyun.Ocr.OcrService.RecognizePassportAsync(System.String)">
<summary>
识别护照信息
</summary>
<param name="imageUrl">护照图片URL</param>
<returns></returns>
</member>
<member name="T:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult">
<summary>
护照识别结果
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.Success">
<summary>
是否成功
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.Message">
<summary>
错误信息
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.Name">
<summary>
姓名
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.Gender">
<summary>
性别
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.PassportNumber">
<summary>
护照号码
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.Nationality">
<summary>
国籍
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.IssuingAuthority">
<summary>
签发地点
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.IssueDate">
<summary>
签发日期
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.ExpiryDate">
<summary>
有效期至
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.BirthDate">
<summary>
出生日期
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.ValidToDate">
<summary>
有效期至(格式化显示)
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.BirthDateYmd">
<summary>
出生日期(纯数字格式)
</summary>
</member>
<member name="P:YD_Event.Core.Infrastructure.Aliyun.Ocr.PassportRecognitionResult.IssueDateYmd">
<summary>
签发日期(格式化显示)
</summary>
</member>
<member name="M:YD_Event.Core.Infrastructure.Aliyun.Oss.OssService.GetFullUrl(System.String)">
<summary>
获取完整的URL