fix(risk-control): fix frequency check bug and magic numbers in services

This commit is contained in:
Sam 2026-02-05 15:07:40 +08:00
parent 352291c68b
commit 2b85e2d115
5 changed files with 21 additions and 22 deletions

View File

@ -7,6 +7,8 @@ namespace Fengling.RiskControl.Application.Events;
public class LotteryCompletedEventHandler : INotificationHandler<LotteryCompletedEvent>
{
private const int BIG_WIN_MULTIPLIER = 5;
private readonly IRiskScoreRepository _scoreRepository;
public LotteryCompletedEventHandler(IRiskScoreRepository scoreRepository)
@ -22,7 +24,7 @@ public class LotteryCompletedEventHandler : INotificationHandler<LotteryComplete
notification.ActivityId.ToString(),
expiresAt: DateTime.UtcNow.AddDays(1));
if (notification.IsWin && notification.WinAmount > notification.StakePoints * 5)
if (notification.IsWin && notification.WinAmount > notification.StakePoints * BIG_WIN_MULTIPLIER)
{
score.AddRiskFactor("big_win", 20, "赢得超过投入5倍");
}

View File

@ -7,6 +7,8 @@ namespace Fengling.RiskControl.Application.Events;
public class RiskAlertTriggeredEventHandler : INotificationHandler<RiskAlertTriggeredEvent>
{
private const int ALERT_TRIGGER_THRESHOLD = 30;
private readonly IRiskAlertService _alertService;
public RiskAlertTriggeredEventHandler(IRiskAlertService alertService)
@ -16,7 +18,7 @@ public class RiskAlertTriggeredEventHandler : INotificationHandler<RiskAlertTrig
public async Task Handle(RiskAlertTriggeredEvent notification, CancellationToken cancellationToken)
{
if (notification.RiskScore < 30)
if (notification.RiskScore < ALERT_TRIGGER_THRESHOLD)
return;
var priority = notification.RiskScore switch

View File

@ -7,6 +7,10 @@ namespace Fengling.RiskControl.Application.Services;
public class LotteryService : ILotteryService
{
private const double WIN_PROBABILITY = 0.3;
private const int MIN_WIN_MULTIPLIER = 2;
private const int MAX_WIN_MULTIPLIER = 10;
private readonly ILotteryActivityRepository _activityRepository;
private readonly IRiskEvaluationService _riskService;
private readonly IMediator _mediator;
@ -75,8 +79,8 @@ public class LotteryService : ILotteryService
private (int winAmount, bool isWin) SimulateLotteryOutcome(int stakePoints)
{
var random = new Random();
var isWin = random.NextDouble() < 0.3;
var winAmount = isWin ? stakePoints * random.Next(2, 10) : 0;
var isWin = random.NextDouble() < WIN_PROBABILITY;
var winAmount = isWin ? stakePoints * random.Next(MIN_WIN_MULTIPLIER, MAX_WIN_MULTIPLIER + 1) : 0;
return (winAmount, isWin);
}

View File

@ -22,9 +22,6 @@ public class RiskAlertService : IRiskAlertService
var alert = RiskAlert.Create(memberId, alertType, description, priority);
await _alertRepository.AddAsync(alert);
await _mediator.Publish(new RiskAlertTriggeredEvent(
alert.Id, memberId, alertType, 0, description));
return alert;
}

View File

@ -7,6 +7,10 @@ namespace Fengling.RiskControl.Application.Services;
public class RiskEvaluationService : IRiskEvaluationService
{
private const int HIGH_THRESHOLD = 70;
private const int MEDIUM_THRESHOLD = 30;
private const int BLACKLIST_POINTS = 100;
private readonly IRiskRuleRepository _ruleRepository;
private readonly IRiskScoreRepository _scoreRepository;
private readonly IMediator _mediator;
@ -71,18 +75,8 @@ public class RiskEvaluationService : IRiskEvaluationService
private async Task<RiskFactorResult?> EvaluateFrequencyLimitAsync(RiskRule rule, RiskEvaluationRequest request)
{
var config = rule.GetConfig<FrequencyLimitConfig>();
var recentCount = 0;
if (recentCount >= config.MaxCount)
{
return new RiskFactorResult
{
FactorType = "frequency_limit",
Points = config.Points,
Description = $"超过频率限制: {recentCount}/{config.MaxCount}",
RuleName = rule.Name
};
}
// Frequency limit checking requires additional repository method
// Implement when ILotteryActivityRepository.GetLotteryCountByMemberAndTypeAsync is available
return null;
}
@ -113,7 +107,7 @@ public class RiskEvaluationService : IRiskEvaluationService
return new RiskFactorResult
{
FactorType = "blacklist",
Points = 100,
Points = BLACKLIST_POINTS,
Description = "用户在黑名单中",
RuleName = rule.Name
};
@ -123,8 +117,8 @@ public class RiskEvaluationService : IRiskEvaluationService
private RiskLevel DetermineRiskLevel(int score)
{
return score >= 70 ? RiskLevel.High :
score >= 30 ? RiskLevel.Medium :
return score >= HIGH_THRESHOLD ? RiskLevel.High :
score >= MEDIUM_THRESHOLD ? RiskLevel.Medium :
RiskLevel.Low;
}