From 2d23dbc7989b950e5af856b626ead4418effb160 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sun, 23 Aug 2026 23:01:17 +0330 Subject: [PATCH] feat(withdrawal): normalize IBAN format in withdrawal requests - Added IbanNormalizer to validate and normalize IBAN numbers in RequestWithdrawalCommandHandler and UserWalletService. - Implemented error handling for invalid IBAN formats, ensuring compliance with expected standards. - Updated relevant methods to handle normalized IBANs for cash withdrawal requests. --- .../RequestWithdrawalCommandHandler.cs | 7 +++- .../Common/IbanNormalizer.cs | 34 +++++++++++++++++++ .../Services/UserWalletService.cs | 14 +++++++- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 src/CMSMicroservice.Application/Common/IbanNormalizer.cs diff --git a/src/CMSMicroservice.Application/CommissionCQ/Commands/RequestWithdrawal/RequestWithdrawalCommandHandler.cs b/src/CMSMicroservice.Application/CommissionCQ/Commands/RequestWithdrawal/RequestWithdrawalCommandHandler.cs index 28894d2..3f04084 100644 --- a/src/CMSMicroservice.Application/CommissionCQ/Commands/RequestWithdrawal/RequestWithdrawalCommandHandler.cs +++ b/src/CMSMicroservice.Application/CommissionCQ/Commands/RequestWithdrawal/RequestWithdrawalCommandHandler.cs @@ -1,3 +1,5 @@ +using CMSMicroservice.Application.Common; + namespace CMSMicroservice.Application.CommissionCQ.Commands.RequestWithdrawal; public class RequestWithdrawalCommandHandler : IRequestHandler @@ -37,7 +39,10 @@ public class RequestWithdrawalCommandHandler : IRequestHandler +/// نرمال‌سازی و اعتبارسنجی شماره شبا ایران (IR + 24 رقم). +/// +public static class IbanNormalizer +{ + private static readonly Regex IranianIbanRegex = new(@"^IR\d{24}$", RegexOptions.Compiled); + + /// + /// فاصله و خط تیره را حذف می‌کند، به حروف بزرگ تبدیل می‌کند و یک پیشوند IR می‌گذارد. + /// در صورت نامعتبر بودن، null برمی‌گرداند. + /// + public static string? TryNormalize(string? iban) + { + if (string.IsNullOrWhiteSpace(iban)) + return null; + + var normalized = iban.Trim().ToUpperInvariant() + .Replace(" ", "", StringComparison.Ordinal) + .Replace("-", "", StringComparison.Ordinal); + + if (normalized.StartsWith("IR", StringComparison.Ordinal)) + normalized = normalized[2..]; + + normalized = "IR" + normalized; + + return IranianIbanRegex.IsMatch(normalized) ? normalized : null; + } + + public static bool IsValid(string? iban) => TryNormalize(iban) is not null; +} diff --git a/src/CMSMicroservice.WebApi/Services/UserWalletService.cs b/src/CMSMicroservice.WebApi/Services/UserWalletService.cs index fa60522..8c92e58 100644 --- a/src/CMSMicroservice.WebApi/Services/UserWalletService.cs +++ b/src/CMSMicroservice.WebApi/Services/UserWalletService.cs @@ -18,6 +18,7 @@ using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory; using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWithdrawals; using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWithdrawalSettings; using CMSMicroservice.Application.Common.Interfaces; +using CMSMicroservice.Application.Common; using CMSMicroservice.Application.Common.Exceptions; using CMSMicroservice.Domain.Common; using CMSMicroservice.Domain.Enums; @@ -175,7 +176,18 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase // Update payout with withdrawal info payout.WithdrawalMethod = (Domain.Enums.WithdrawalMethod)request.WithdrawalMethod; - payout.IbanNumber = request.IbanNumber; + if (payout.WithdrawalMethod == Domain.Enums.WithdrawalMethod.Cash) + { + var normalizedIban = IbanNormalizer.TryNormalize(request.IbanNumber); + if (normalizedIban is null) + throw new RpcException(new Status(StatusCode.InvalidArgument, + "فرمت شماره شبا معتبر نیست. باید IR و ۲۴ رقم باشد.")); + payout.IbanNumber = normalizedIban; + } + else + { + payout.IbanNumber = null; + } payout.Status = Domain.Enums.CommissionPayoutStatus.WithdrawRequested; await _context.SaveChangesAsync(context.CancellationToken);