cookie('device_registered')) { return redirect()->route('verification.congratulations'); } if (session()->has('coupon_code')) { return redirect()->route('verification.congratulations'); } return view('verification.index'); } public function sendOtp(Request $request) { if ($request->cookie('device_registered')) { return back()->withErrors(['phone' => 'Siz eýýäm agza bolduňyz.']); } $request->validate([ 'phone' => ['required', 'regex:/^\+993 [67]\d \d{2} \d{2} \d{2}$/'] ], [ 'phone.regex' => 'Telefon belgiňiz şu formatda bolmaly: +993 KX XX XX XX (bu ýerde K 6 ýa-da 7).' ]); $phone = unmask_phone($request->phone); $existingCoupon = Coupon::query()->where('phone', $phone)->first(); if ($existingCoupon) { return back()->withErrors(['phone' => 'Bu telefon belgisi eýýäm ulanyldy.'])->withInput(); } // Generate a 4-digit OTP $otp = (string) rand(1000, 9999); // Store in DB PhoneVerification::updateOrCreate( ['phone' => $phone], [ 'otp' => $otp, 'expires_at' => now()->addMinutes(10), 'verified' => false ] ); sendSMS($phone, 'Tassyklaýyş belgi: ' . $otp); // Store phone in session for the next step session()->put('verify_phone', $phone); return redirect()->route('verification.verify.form'); } public function verifyForm() { if (request()->cookie('device_registered')) { return redirect()->route('verification.congratulations'); } if (session()->has('coupon_code')) { return redirect()->route('verification.congratulations'); } if (! session()->has('verify_phone')) { return redirect()->route('verification.index'); } return view('verification.verify', [ 'phone' => session()->get('verify_phone') ]); } public function resendOtp() { $phone = session()->get('verify_phone'); if (!$phone) { return redirect()->route('verification.index'); } // Generate a 4-digit OTP $otp = (string) rand(1000, 9999); // Store in DB PhoneVerification::updateOrCreate( ['phone' => $phone], [ 'otp' => $otp, 'expires_at' => now()->addMinutes(10), 'verified' => false ] ); sendSMS($phone, $otp); return back()->with('status', 'Täze kod iberildi!'); } public function verifyOtp(Request $request) { $request->validate([ 'phone' => 'required', 'otp' => 'required|digits:4' ]); $verification = PhoneVerification::query()->where('phone', $request->phone)->first(); if (!$verification || $verification->otp !== $request->otp) { return back()->withErrors(['otp' => 'Nädogry kod.']); } if ($verification->expires_at < now()) { return back()->withErrors(['otp' => 'Kodyň möhleti gutardy.']); } // Mark as verified $verification->update(['verified' => true]); // Generate or get Coupon $coupon = Coupon::firstOrCreate( ['phone' => $request->phone], ['code' => $this->generateCouponCode()] ); // Put coupon code in session for the congratulations page session()->put('coupon_code', $coupon->code); // We set a long-lived cookie to mark this device as registered (e.g. 5 years) return redirect()->route('verification.congratulations') ->cookie('device_registered', 'true', 60 * 24 * 365 * 5); } public function congratulations() { // If they have the cookie but lost the session, we don't know their code unless we query // But for simplicity based on the flow, we'll try to find it by phone if available if (!session()->has('coupon_code') && !request()->cookie('device_registered')) { return redirect()->route('verification.index'); } $code = session()->get('coupon_code'); if (!$code && session()->has('verify_phone')) { $coupon = Coupon::query()->where('phone', session()->get('verify_phone'))->first(); if ($coupon) { $code = $coupon->code; session()->put('coupon_code', $code); } } // If for some reason code is completely lost (e.g. cookie exists but session cleared and no phone), // we can't show a specific code. In this specific scenario, we'll default to redirecting back. if (!$code) { return redirect()->route('verification.index')->withoutCookie('device_registered'); } return view('verification.congratulations', [ 'code' => $code ]); } private function generateCouponCode() { // Format X_YYYY (X is integer, Y is capital char) $x = rand(1, 9); $yyyy = substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 4); return "{$x}_{$yyyy}"; } }