Files
Virtnet.bond/extensions/Others/Security/Services/FraudDetectionService.php
2025-11-30 11:57:22 +01:00

83 lines
2.5 KiB
PHP

<?php
namespace Paymenter\Extensions\Others\Security\Services;
use App\Models\User;
use Paymenter\Extensions\Others\Security\Models\SuspendedAccount;
use Paymenter\Extensions\Others\Security\Models\LoginAttempt;
use Illuminate\Support\Facades\Auth;
class FraudDetectionService
{
public static function checkAndSuspendForFraud(User $user): bool
{
$extension = app(\Paymenter\Extensions\Others\Security\Security::class);
$config = $extension->getConfig();
$autoSuspend = false;
foreach ($config as $setting) {
if ($setting['name'] === 'auto_suspend_fraud') {
$autoSuspend = $setting['default'] ?? false;
break;
}
}
if (!$autoSuspend) {
return false;
}
$fraudScore = static::calculateFraudScore($user);
if ($fraudScore >= 70) {
SuspendedAccount::suspendUser(
$user->id,
"Auto-suspended due to suspected fraudulent activity (Score: {$fraudScore})",
Auth::id() ?? 1,
false,
now()->addDays(7),
"Automated fraud detection triggered suspension"
);
return true;
}
return false;
}
protected static function calculateFraudScore(User $user): int
{
$score = 0;
$recentFailedLogins = LoginAttempt::where('email', $user->email)
->where('successful', false)
->where('attempted_at', '>', now()->subDay())
->count();
if ($recentFailedLogins > 10) $score += 30;
elseif ($recentFailedLogins > 5) $score += 15;
$recentIPs = LoginAttempt::where('email', $user->email)
->where('attempted_at', '>', now()->subHours(2))
->distinct('ip_address')
->count();
if ($recentIPs > 3) $score += 25;
elseif ($recentIPs > 2) $score += 10;
$rapidLogins = LoginAttempt::where('email', $user->email)
->where('attempted_at', '>', now()->subMinutes(10))
->count();
if ($rapidLogins > 10) $score += 35;
elseif ($rapidLogins > 5) $score += 20;
return min($score, 100);
}
public static function shouldFlagForReview(User $user): bool
{
$fraudScore = static::calculateFraudScore($user);
return $fraudScore >= 40 && $fraudScore < 70;
}
}