This commit is contained in:
Devit
2026-03-29 19:45:29 +05:00
parent 2cd5ebb4fd
commit 7a20be6e1b
3 changed files with 314 additions and 91 deletions

View File

@@ -10,8 +10,6 @@ use App\Models\Blog;
use App\Models\Category;
use App\Models\Chat;
use App\Models\City;
use App\Models\Client;
use App\Models\Clientsreg;
use App\Models\ContactUs;
use App\Models\Country;
use App\Models\Currency;
@@ -172,7 +170,7 @@ class ApiController extends Controller
$countryCode = ltrim($request->country_code, '+');
// 1⃣ First: try with mobile + country code
$mobileWithCode = $countryCode . $mobile;
$mobileWithCode = $countryCode . $mobile;
// First try strict match
$user = User::where('type', 'phone')
@@ -180,28 +178,28 @@ class ApiController extends Controller
->withTrashed()
->first();
if (!$user) {
return ResponseService::errorResponse(
__('User not found. Please signup first.')
);
}
if (!$user) {
return ResponseService::errorResponse(
__('User not found. Please signup first.')
);
}
if ($user->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.')
);
}
if ($user->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.')
);
}
// password exists check
if (empty($user->password)) {
return ResponseService::errorResponse(
__('Password is not set. Please set your password using the forgot password option.')
);
}
// password exists check
if (empty($user->password)) {
return ResponseService::errorResponse(
__('Password is not set. Please set your password using the forgot password option.')
);
}
if (! Hash::check($request->password, $user->password)) {
return ResponseService::errorResponse(__('Invalid password.'));
}
if (! Hash::check($request->password, $user->password)) {
return ResponseService::errorResponse(__('Invalid password.'));
}
}
$socialLogin = null;
if (! empty($firebase_id)) {
@@ -708,7 +706,7 @@ class ApiController extends Controller
}
// Get all_category_ids from request (should contain category and all parent categories)
$allCategoryIds = $request->input('all_category_ids', []);
$allCategoryIds = $request->input('all_category_ids', []);
// If it comes as comma-separated string, convert to array
if (is_string($allCategoryIds)) {
@@ -982,9 +980,9 @@ class ApiController extends Controller
->where(function ($query) {
// Either no parent or parent status != 0
$query->whereDoesntHave('parent') // no parent category
->orWhereHas('parent', function ($q2) {
$q2->where('status', '!=', 0);
});
->orWhereHas('parent', function ($q2) {
$q2->where('status', '!=', 0);
});
});
})
->when($request->id, function ($sql) use ($request) {
@@ -1727,49 +1725,49 @@ class ApiController extends Controller
// dd($packageCategoryIds);
// Get the requested category
$requestedCategory = Category::find($request->category_id);
$requestedCategory = Category::find($request->category_id);
$requestedCategory = Category::find($request->category_id);
if ($requestedCategory) {
// Check if user has access to the category or any of its subcategories
if (! $hasGlobalPackage) {
$hasAccess = false;
if (! $hasGlobalPackage) {
$hasAccess = false;
// 1⃣ Direct category access
if (in_array($requestedCategory->id, $packageCategoryIds)) {
// 1⃣ Direct category access
if (in_array($requestedCategory->id, $packageCategoryIds)) {
$hasAccess = true;
}
// 2⃣ Check ancestors (parent → root)
if (! $hasAccess) {
$ancestorIds = $requestedCategory->ancestors()
->where('status', 1)
->pluck('id')
->toArray();
if (! empty(array_intersect($ancestorIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// 2️⃣ Check ancestors (parentroot)
if (! $hasAccess) {
$ancestorIds = $requestedCategory->ancestors()
->where('status', 1)
->pluck('id')
->toArray();
// 3️⃣ Check descendants (children → deep)
if (! $hasAccess) {
$descendantIds = $requestedCategory->descendants()
->where('status', 1)
->pluck('id')
->toArray();
if (! empty(array_intersect($ancestorIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// 3⃣ Check descendants (children → deep)
if (! $hasAccess) {
$descendantIds = $requestedCategory->descendants()
->where('status', 1)
->pluck('id')
->toArray();
if (! empty(array_intersect($descendantIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// ❌ No access
if (! $hasAccess) {
ResponseService::errorResponse(
__('You need to purchase a package for this category to access it.')
);
if (! empty(array_intersect($descendantIds, $packageCategoryIds))) {
$hasAccess = true;
}
}
// ❌ No access
if (! $hasAccess) {
ResponseService::errorResponse(
__('You need to purchase a package for this category to access it.')
);
}
}
// If hasGlobalPackage is true, user has access to all categories
} else {
ResponseService::errorResponse(__('Category not found.'));
@@ -3953,10 +3951,126 @@ class ApiController extends Controller
return ResponseService::errorResponse();
}
}
public function getOtp(Request $request)
{
try {
$validator = Validator::make($request->query(), [
'country_code' => 'required|string|max:5',
'number' => 'required|string|max:15',
]);
if ($validator->fails()) {
return ResponseService::validationError($validator->errors()->first());
}
// Normalize inputs
$countryCode = ltrim(trim($request->query('country_code')), '+');
$number = preg_replace('/\D/', '', $request->query('number'));
$toNumber = '+' . $countryCode . $number;
// ✅ Oddiy validation (Twilio orniga)
if (!preg_match('/^\+\d{10,15}$/', $toNumber)) {
return ResponseService::errorResponse(__('Invalid phone number.'));
}
$otp = rand(100000, 999999);
$expireAt = now()->addMinutes(10);
NumberOtp::updateOrCreate(
[
'number' => $number,
],
[
'otp' => $otp,
'expire_at' => $expireAt,
]
);
// ✅ Eskiz orqali yuborish
dispatch(new SendSmsJob($toNumber, $otp));
return ResponseService::successResponse(__('OTP sent successfully.'));
} catch (\Throwable $th) {
ResponseService::logErrorResponse($th, 'OTP Controller -> getOtp');
return ResponseService::errorResponse();
}
}
public function verifyOtp(Request $request)
{
try {
$validator = Validator::make($request->all(), [
'number' => 'required|string',
'country_code' => 'required|string',
'otp' => 'required|numeric|digits:6',
'password' => 'nullable|string|min:6',
]);
if ($validator->fails()) {
return ResponseService::validationError($validator->errors()->first());
}
$number = $request->query('number');
$countryCode = $request->query('country_code');
// Format full phone number
// $requestNumber = $countryCode.$number;
// $trimmedNumber = ltrim($requestNumber, '+');
// $toNumber = '+'.$trimmedNumber;
$otpRecord = NumberOtp::where('number', $number)->first();
if (! $otpRecord) {
return ResponseService::errorResponse(__('OTP not found.'));
}
if (now()->isAfter($otpRecord->expire_at)) {
return ResponseService::validationError(__('OTP has expired.'));
}
if ($otpRecord->attempts >= 3) {
$otpRecord->delete();
return ResponseService::validationError(__('OTP expired after 3 failed attempts.'));
}
if ($otpRecord->otp != $request->otp) {
$otpRecord->increment('attempts');
return ResponseService::validationError(__('Invalid OTP.'));
}
$otpRecord->delete();
$user = User::where('mobile', $request->number)->where('type', 'phone')->first();
if (! $user) {
$user = User::create([
'mobile' => $request->number,
'type' => 'phone',
'country_code' => $countryCode,
'password' => ! empty($request->password) ? Hash::make($request->password) : '',
]);
$user->assignRole('User');
}else{
if (! empty($countryCode)) {
$user->country_code = ltrim($countryCode, '+');
}
$user->save();
}
Auth::login($user);
$auth = User::find(Auth::id());
$token = $auth->createToken($auth->name ?? '')->plainTextToken;
return ResponseService::successResponse(__('User logged-in successfully'), $auth, ['token' => $token]);
} catch (Throwable $th) {
ResponseService::logErrorResponse($th, 'OTP Controller -> verifyOtp');
return ResponseService::errorResponse();
}
}
public function userExists(Request $request)
{
$validator = Validator::make($request->all(), [
@@ -3974,24 +4088,24 @@ class ApiController extends Controller
$countryCode = ltrim($request->country_code, '+');
$mobileWithCode = $countryCode . $mobile;
$userExists = User::where('type', 'phone')
->where('mobile', $mobile)
->withTrashed()
->first();
->where('mobile', $mobile)
->withTrashed()
->first();
if (! $userExists) {
return ResponseService::errorResponse(
__('User does not exist'),
['user_exists' => false]
);
}
if (! $userExists) {
return ResponseService::errorResponse(
__('User does not exist'),
['user_exists' => false]
);
}
// ❌ user found but deactivated
if ($userExists->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.'),
['user_exists' => false]
);
}
// ❌ user found but deactivated
if ($userExists->deleted_at) {
return ResponseService::errorResponse(
__('User is deactivated. Please contact the administrator.'),
['user_exists' => false]
);
}
if ($userExists) {
return ResponseService::successResponse(
__('User already exists'),

View File

@@ -1,6 +1,5 @@
<?php
use App\Http\Controllers\api\AuthController;
use App\Http\Controllers\ApiController;
use Illuminate\Support\Facades\Route;
@@ -72,24 +71,11 @@ Route::group(['middleware' => ['auth:sanctum']], static function () {
Route::post('logout', [ApiController::class, 'logout']);
});
Route::post('get-otp', [AuthController::class, 'getOtp']);
Route::post('verify-otp', [AuthController::class, 'verifyOtp']);
Route::post('login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::get('profile', [AuthController::class, 'profile']);
Route::get('logout', [AuthController::class, 'logout']);
});
/* Non Authenticated Routes */
Route::get('user-exists', [ApiController::class, 'userExists']);
Route::get('get-currencies', [ApiController::class, 'getCurrencies']);
Route::get('get-otp', [ApiController::class, 'getOtp']);
Route::get('verify-otp', [ApiController::class, 'verifyOtp']);
Route::get('get-package', [ApiController::class, 'getPackage']);
Route::get('get-languages', [ApiController::class, 'getLanguages']);
Route::post('user-signup', [ApiController::class, 'userSignup']);

123
routes/api11.php Normal file
View File

@@ -0,0 +1,123 @@
<?php
use App\Http\Controllers\api\AuthController;
use App\Http\Controllers\ApiController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
/* Authenticated Routes */
Route::group(['middleware' => ['auth:sanctum']], static function () {
Route::post('reset-password', [ApiController::class, 'resetPassword']);
Route::get('get-package', [ApiController::class, 'getPackage']);
Route::post('update-profile', [ApiController::class, 'updateProfile']);
Route::delete('delete-user', [ApiController::class, 'deleteUser']);
Route::get('get-user-info', [ApiController::class, 'getUser']);
Route::get('my-items', [ApiController::class, 'getItem']);
Route::post('add-item', [ApiController::class, 'addItem']);
Route::post('update-item', [ApiController::class, 'updateItem']);
Route::post('delete-item', [ApiController::class, 'deleteItem']);
Route::post('update-item-status', [ApiController::class, 'updateItemStatus']);
Route::get('item-buyer-list', [ApiController::class, 'getItemBuyerList']);
Route::post('renew-item', [ApiController::class, 'renewItem']);
Route::post('assign-free-package', [ApiController::class, 'assignFreePackage']);
Route::post('make-item-featured', [ApiController::class, 'makeFeaturedItem']);
Route::post('manage-favourite', [ApiController::class, 'manageFavourite']);
Route::post('add-reports', [ApiController::class, 'addReports']);
Route::get('get-notification-list', [ApiController::class, 'getNotificationList']);
Route::get('get-limits', [ApiController::class, 'getLimits']);
Route::get('get-favourite-item', [ApiController::class, 'getFavouriteItem']);
Route::get('get-payment-settings', [ApiController::class, 'getPaymentSettings']);
Route::post('payment-intent', [ApiController::class, 'getPaymentIntent']);
Route::get('payment-transactions', [ApiController::class, 'getPaymentTransactions']);
/* Chat Module */
Route::post('item-offer', [ApiController::class, 'createItemOffer']);
Route::get('chat-list', [ApiController::class, 'getChatList']);
Route::post('send-message', [ApiController::class, 'sendMessage']);
Route::get('chat-messages', [ApiController::class, 'getChatMessages']);
Route::post('in-app-purchase', [ApiController::class, 'inAppPurchase']);
Route::post('block-user', [ApiController::class, 'blockUser']);
Route::post('unblock-user', [ApiController::class, 'unblockUser']);
Route::get('blocked-users', [ApiController::class, 'getBlockedUsers']);
Route::post('add-item-review', [ApiController::class, 'addItemReview']);
Route::get('my-review', [ApiController::class, 'getMyReview']);
Route::post('add-review-report', [ApiController::class, 'addReviewReport']);
Route::get('verification-fields', [ApiController::class, 'getVerificationFields']);
Route::post('send-verification-request', [ApiController::class, 'sendVerificationRequest']);
Route::get('verification-request', [ApiController::class, 'getVerificationRequest']);
Route::post('bank-transfer-update', [ApiController::class, 'bankTransferUpdate']);
Route::post('job-apply', [ApiController::class, 'applyJob']);
Route::get('get-job-applications', [ApiController::class, 'recruiterApplications']);
Route::get('my-job-applications', [ApiController::class, 'myJobApplications']);
Route::post('update-job-applications-status', [ApiController::class, 'updateJobStatus']);
Route::post('logout', [ApiController::class, 'logout']);
});
Route::post('get-otp', [AuthController::class, 'getOtp']);
Route::post('verify-otp', [AuthController::class, 'verifyOtp']);
Route::post('login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::get('profile', [AuthController::class, 'profile']);
Route::get('logout', [AuthController::class, 'logout']);
});
/* Non Authenticated Routes */
Route::get('user-exists', [ApiController::class, 'userExists']);
Route::get('get-currencies', [ApiController::class, 'getCurrencies']);
Route::get('get-package', [ApiController::class, 'getPackage']);
Route::get('get-languages', [ApiController::class, 'getLanguages']);
Route::post('user-signup', [ApiController::class, 'userSignup']);
Route::post('set-item-total-click', [ApiController::class, 'setItemTotalClick']);
Route::get('get-system-settings', [ApiController::class, 'getSystemSettings']);
Route::get('app-payment-status', [ApiController::class, 'appPaymentStatus']);
Route::get('get-customfields', [ApiController::class, 'getCustomFields']);
Route::get('get-item', [ApiController::class, 'getItem']);
Route::get('get-slider', [ApiController::class, 'getSlider']);
Route::get('get-report-reasons', [ApiController::class, 'getReportReasons']);
Route::get('get-categories', [ApiController::class, 'getSubCategories']);
Route::get('get-parent-categories', [ApiController::class, 'getParentCategoryTree']);
Route::get('get-featured-section', [ApiController::class, 'getFeaturedSection']);
Route::get('blogs', [ApiController::class, 'getBlog']);
Route::get('blog-tags', [ApiController::class, 'getAllBlogTags']);
Route::get('faq', [ApiController::class, 'getFaqs']);
Route::get('tips', [ApiController::class, 'getTips']);
Route::get('countries', [ApiController::class, 'getCountries']);
Route::get('states', [ApiController::class, 'getStates']);
Route::get('cities', [ApiController::class, 'getCities']);
Route::get('areas', [ApiController::class, 'getAreas']);
Route::post('contact-us', [ApiController::class, 'storeContactUs']);
Route::get('seo-settings', [ApiController::class, 'seoSettings']);
Route::get('get-seller', [ApiController::class, 'getSeller']);
Route::get('get-categories-demo', [ApiController::class, 'getCategories']);
Route::get('get-location', [ApiController::class, 'getLocationFromCoordinates']);
Route::get('get-item-slug', [ApiController::class, 'getItemSlugs']);
Route::get('get-categories-slug', [ApiController::class, 'getCategoriesSlug']);
Route::get('get-blogs-slug', [ApiController::class, 'getBlogsSlug']);
Route::get('get-featured-section-slug', [ApiController::class, 'getFeatureSectionSlug']);
Route::get('get-seller-slug', [ApiController::class, 'getSellerSlug']);