File: /var/www/console.fixgini.com/app/Http/Controllers/Authentication/Google.php
<?php
namespace App\Http\Controllers\Authentication;
use App\Http\Controllers\Controller;
use App\Mail\WelcomeMail;
use App\Models\Country;
use App\Models\SellerNin;
use App\Models\Shop;
use App\Models\User;
use App\Models\Wallet;
use App\Services\ActivityLogger;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Validation\Rule;
use Laravel\Sanctum\PersonalAccessToken;
class Google extends Controller
{
public function callBack(Request $request)
{
try {
// Validate incoming request
$validatedData = $request->validate([
'google_id' => 'required|string|max:255',
'name' => 'nullable|string|max:255',
'lastname' => 'nullable|string|max:255',
'email' => 'required|email',
'nationality_id' => 'nullable|exists:countries,id',
'role' => 'nullable|string|in:buyer,seller',
'ip_address' => 'required|string',
'device_name' => 'nullable|string|max:255',
'photo' => 'nullable|string',
'middlename' => 'nullable|string|max:255',
'phone' => 'nullable',
'dob' => 'nullable|string|max:100',
'gender' => 'nullable',
'nin' => 'nullable|string|unique:seller_nins,nin',
]);
} catch (\Exception $e) {
Log::info($e->getMessage());
return response()->json(['status' => 'error', 'message' => $e->getMessage()], 500);
}
$location = $this->getLocation($validatedData['ip_address']);
$user = User::where('email', $validatedData['email'])->whereNotNull('google_id')->first();
if ($user) {
return $this->login($validatedData);
} else {
return $this->register($validatedData);
}
}
public function login($credentials)
{
try {
$user = User::where('email', $credentials['email'])->first();
if ($user->status == 'inactive') {
return response()->json(['status' => 'failed', 'message' => 'Account is inactive, Please contact support to continue'], 404);
}
$ip = $credentials['ip_address'];
$activityIp = optional($user->activity)->ip;
// Check if the activity IP matches the incoming IP; if not, fetch location
$location = ($activityIp && $activityIp === $ip) ? $activityIp : $this->getLocation($ip);
// Update user location details
$user->latitude = $location['latitude'] ?? $user->latitude;
$user->longitude = $location['longitude'] ?? $user->longitude;
$user->save();
// Generate authentication token
$token = $user->createToken('api_token')->plainTextToken;
// Log the user activity
$device = $credentials['device_name'];
$activityLogger = app(ActivityLogger::class);
$activityLogger->log('User login from mobile phone (API)', $user->id, $user->role, $device);
// Check if the user has an associated shop
$isShop = Shop::where('user_id', $user->id)->exists();
$isNin = SellerNin::where('user_id', $user->id)->exists();
return response()->json([
'status' => 'success',
'message' => 'Login successfully',
'token' => $token,
'user' => $user,
'is_shop' => $isShop,
'is_nin' => $isNin,
], 200);
} catch (\Throwable $th) {
// Handle any unexpected errors
$message = $th->getMessage();
Log::info($message);
return response()->json([
'status' => 'failed',
'message' => 'Oops, Service Unavailable. Please try again later ',
'reason' => $message
], 400);
}
}
public function register($validatedData)
{
$user = User::where('email', $validatedData['email'])->exists();
if ($user) {
return response()->json(['status' => 'failed', 'message' => 'Please continue with email and password. Thank you'], 404);
}
// Create a new user if not found
$user = User::create([
'google_id' => $validatedData['google_id'] ?? '',
'name' => $validatedData['name'],
'lastname' => $validatedData['lastname'] ?? '',
'email' => $validatedData['email'],
'phone' => $validatedData['phone'] ?? '',
'status' => 'active',
'city' => $location['city'] ?? '',
'state' => $location['state'] ?? '',
'latitude' => $location['latitude'] ?? '',
'longitude' => $location['longitude'] ?? '',
'profile_photo_url' => $validatedData['photo'] ?? '',
'nationality_id' => $validatedData['nationality_id'] ?? '1',
'role' => $validatedData['role'] ?? 'buyer',
'email_verified_at' => now(),
'is_fingerprint' => false,
'is_pin' => false,
]);
// Create Wallet for the user
$currency = Country::where('id', $validatedData['nationality_id'])->first();
Wallet::create([
'user_id' => $user->id,
'balance' => 0.0,
'currency' => $currency->symbol
]);
// Handle Seller-specific data if role is seller
if ($validatedData['role'] == 'seller') {
SellerNin::create([
'user_id' => $user->id,
'name' => $validatedData['name'] ?? '',
'lastname' => $validatedData['lastname'] ?? '',
'middlename' => $validatedData['middlename'] ?? '',
'dob' => $validatedData['dob'] ?? '',
'gender' => $validatedData['gender'] ?? '',
'nin' => $validatedData['nin'] ?? '',
]);
}
// Send Welcome Email
Mail::to($validatedData['email'])->send(new WelcomeMail($user));
$token = $user->createToken('api_token')->plainTextToken;
return response()->json([
'status' => 'success',
'message' => 'Registration was successful.',
'is_shop' => Shop::where('user_id', $user->id)->exists(),
'is_nin' => SellerNin::where('user_id', $user->id)->exists(),
'user' => $user,
'token' => $token
], 200);
}
private function getLocation($ip)
{
try {
$clientIp = $ip;
// Attempt the first API call to api.ip2location.io
$apiKey = env('IP2LOCATION_API_KEY');
$response = Http::get("https://api.ip2location.io/?key={$apiKey}&ip={$clientIp}&format=json");
if ($response->successful()) {
$data = $response->json();
$latitude = $data['latitude'] ?? '';
$longitude = $data['longitude'] ?? '';
// If lat/lng exists, perform reverse geocoding
if ($latitude && $longitude) {
return $this->reverseGeocode($latitude, $longitude);
}
} else {
// Check for specific error in the first API response
$error = $response->json('error') ?? [];
if (isset($error['error_code']) && $error['error_code'] === 10000) {
Log::warning('IP2Location API error: ' . $error['error_message']);
}
}
// Fallback to ipinfo.io API
$response = Http::get("https://ipinfo.io/{$clientIp}?token=55690b2a8bf492");
if ($response->successful()) {
$data = $response->json();
// Extract location data from ipinfo response
$location = explode(',', $data['loc'] ?? '');
$latitude = $location[0] ?? '';
$longitude = $location[1] ?? '';
// Include city and state in the response
return [
'city' => $data['city'] ?? '',
'state' => $data['region'] ?? '',
'country' => $data['country'] ?? '',
'latitude' => $latitude ?? '',
'longitude' => $longitude ?? '',
];
}
} catch (\Exception $e) {
Log::error('Location fetching error: ' . $e->getMessage());
}
// Return a default response if all attempts fail
return [
'city' => '',
'state' => '',
'country' => '',
'latitude' => '',
'longitude' => '',
];
}
private function reverseGeocode($latitude, $longitude)
{
try {
$response = Http::get('https://maps.googleapis.com/maps/api/geocode/json', [
'latlng' => "{$latitude},{$longitude}",
'key' => env('GOOGLE_API_KEY'),
]);
if ($response->successful()) {
$data = $response->json();
if (isset($data['results']) && count($data['results']) > 0) {
$components = $data['results'][0]['address_components'];
$locationInfo = [
'city' => null,
'state' => null,
'latitude' => $latitude,
'longitude' => $longitude,
];
foreach ($components as $component) {
if (in_array('locality', $component['types'])) {
$locationInfo['city'] = $component['long_name'];
}
if (in_array('administrative_area_level_1', $component['types'])) {
$locationInfo['state'] = $component['long_name'];
}
}
return $locationInfo;
} else {
return [
'error' => true,
'message' => 'No results found.',
];
}
} else {
return [
'error' => true,
'message' => 'Failed to retrieve location data.',
];
}
} catch (\Exception $e) {
return [
'error' => true,
'message' => $e->getMessage(),
];
}
}
}