withServiceAccount($credentialsFilePath); $messaging = $factory->createMessaging(); $responses = []; foreach ($tokens as $fcmToken) { $message = CloudMessage::withTarget('token', $fcmToken) ->withNotification(Notification::create($title, $body)) ->withAndroidConfig(AndroidConfig::fromArray([ 'priority' => 'high', 'notification' => [ 'channel_id' => 'paud_notif_channel', 'sound' => 'default' ] ])); try { $result = $messaging->send($message); $responses[] = $result; \Log::info("FCM Response for token {$fcmToken}: Sukses via Kreait. Result: " . json_encode($result)); } catch (\Kreait\Firebase\Exception\MessagingException $e) { $errorMessage = $e->getMessage(); $errors = $e->errors(); \Log::error("Kreait FCM Error for token {$fcmToken}: " . $errorMessage); // Cek dari errors() bukan getMessage() $errorCode = $errors['error']['details'][0]['errorCode'] ?? ''; if ($errorCode === 'UNREGISTERED' || str_contains($errorMessage, 'UNREGISTERED') || $errorCode === 'INVALID_ARGUMENT' || str_contains($errorMessage, 'invalid-argument')) { \App\Models\User::where('fcm_token', $fcmToken)->update(['fcm_token' => null]); \Log::warning("FCM Token dihapus karena Unregistered/Invalid: {$fcmToken}"); continue; } // ERROR HANDLING TEGAS SEPERTI SEBELUMNYA dd([ 'STATUS' => 'ERROR_DITOLAK_GOOGLE', 'FCM_ERROR' => $errorMessage, 'FCM_ERROR_DETAILS' => $errors, 'ERROR_CODE_DETECTED' => $errorCode, ]); } } return $responses; } catch (\Exception $e) { \Log::error("FCM System Error: " . $e->getMessage()); dd([ 'STATUS' => 'FATAL_SYSTEM_ERROR', 'ERROR' => $e->getMessage() ]); return false; } } }