This commit is contained in:
Mekan1206
2026-05-19 21:22:36 +05:00
parent b1a6c12a00
commit e66ce8fdcd
21 changed files with 677 additions and 150 deletions

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Services;
use App\Models\Coupon;
use Illuminate\Database\UniqueConstraintViolationException;
use Illuminate\Support\Str;
class CouponService
{
public function findOrCreateForPhone(string $phone): Coupon
{
$existing = Coupon::query()->where('phone', $phone)->first();
if ($existing) {
return $existing;
}
return $this->createWithUniqueCode($phone);
}
private function createWithUniqueCode(string $phone): Coupon
{
for ($attempt = 0; $attempt < 10; $attempt++) {
try {
return Coupon::query()->create([
'phone' => $phone,
'code' => $this->generateCouponCode(),
]);
} catch (UniqueConstraintViolationException) {
continue;
}
}
throw new \RuntimeException('Unable to generate a unique coupon code.');
}
private function generateCouponCode(): string
{
$x = random_int(1, 9);
$yyyy = Str::upper(Str::random(4));
return "{$x}_{$yyyy}";
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace App\Services;
use App\Enums\OtpVerificationResult;
use App\Models\PhoneVerification;
use Illuminate\Support\Facades\Hash;
class OtpService
{
public const OTP_EXPIRY_MINUTES = 10;
public function issue(string $phone): bool
{
$otp = $this->generateOtp();
PhoneVerification::query()->updateOrCreate(
['phone' => $phone],
[
'otp' => Hash::make($otp),
'expires_at' => now()->addMinutes(self::OTP_EXPIRY_MINUTES),
'verified' => false,
],
);
return sendSMS($phone, 'Tassyklaýyş belgi: '.$otp);
}
public function verify(string $phone, string $otp): OtpVerificationResult
{
$verification = PhoneVerification::query()->where('phone', $phone)->first();
if (! $verification) {
return OtpVerificationResult::Invalid;
}
if ($verification->expires_at->isPast()) {
return OtpVerificationResult::Expired;
}
if (! Hash::check($otp, $verification->otp)) {
return OtpVerificationResult::Invalid;
}
$verification->update(['verified' => true]);
return OtpVerificationResult::Verified;
}
private function generateOtp(): string
{
return (string) random_int(1000, 9999);
}
}