PushNotificationService.php 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. namespace App\Services;
  3. use App\Models\DeviceToken;
  4. use App\Models\PushNotificationLog;
  5. use App\Models\User;
  6. use App\Notifications\Push\BasePushNotification;
  7. use Illuminate\Support\Collection;
  8. use Kreait\Firebase\Contract\Messaging;
  9. use Kreait\Firebase\Messaging\AndroidConfig;
  10. use Kreait\Firebase\Messaging\CloudMessage;
  11. use Kreait\Firebase\Messaging\Notification;
  12. use Throwable;
  13. class PushNotificationService
  14. {
  15. public function __construct(private Messaging $messaging) {}
  16. /**
  17. * Envia uma push notification para todos os tokens ativos de um usuário.
  18. * Registra o envio no log e desativa tokens inválidos automaticamente.
  19. */
  20. public function sendToUser(User $user, BasePushNotification $notification): void
  21. {
  22. $tokens = DeviceToken::where('user_id', $user->id)
  23. ->where('app_type', $notification->target()->value)
  24. ->where('active', true)
  25. ->pluck('token')
  26. ->toArray();
  27. if (empty($tokens)) {
  28. return;
  29. }
  30. $message = CloudMessage::new()
  31. ->withNotification(Notification::create($notification->title(), $notification->body()))
  32. ->withAndroidConfig(AndroidConfig::fromArray([
  33. 'notification' => ['channel_id' => 'default'],
  34. 'priority' => 'high',
  35. ]));
  36. $report = $this->messaging->sendMulticast($message, $tokens);
  37. $this->deactivateInvalidTokens($report->invalidTokens());
  38. if ($report->successes()->count() > 0) {
  39. $this->log($user, $notification);
  40. }
  41. }
  42. /**
  43. * Envia para uma coleção de usuários, respeitando cooldowns.
  44. * Usuários sem tokens ativos são ignorados silenciosamente.
  45. */
  46. public function sendToUsers(Collection $users, BasePushNotification $notification): void
  47. {
  48. foreach ($users as $user) {
  49. $this->sendToUser($user, $notification);
  50. }
  51. }
  52. private function log(User $user, BasePushNotification $notification): void
  53. {
  54. PushNotificationLog::create([
  55. 'label' => $notification->label(),
  56. 'user_id' => $user->id,
  57. 'target' => $notification->target()->value,
  58. 'category' => $notification->category()->value,
  59. 'sent_at' => now(),
  60. ]);
  61. }
  62. private function deactivateInvalidTokens(array $tokens): void
  63. {
  64. if (empty($tokens)) {
  65. return;
  66. }
  67. DeviceToken::whereIn('token', $tokens)->update(['active' => false]);
  68. }
  69. }