I. Giới thiệu
- Như tiêu đề, bài viết này mình sẽ giới thiệu cách gửi notification sử dụng Firebase và Laravel, có thể
subscribe topic
được nhiềudevice token qua
đó nâng cao hiệu năng gửi notification, (một vấn đề mình đã gặp trong dự án vừa qua), sử dụng queue… - Sẽ có nhiều bài viết đã hướng dẫn cách
subscribe topic
theo từng device token,subscribe topic
khi vào một action nào đó nhưng ở bài viết này mình sẽ hướng dẫn theo từng case tương ứng khi muốn push vào một thời gian nhất định với lượng device token nhất định theo rule bất kỳ.
II. Hướng dẫn cách làm
1. Cách lấy server key
- Có rất nhiều bài viết hướng dẫn tạo app trên firebase và bạn có thể làm theo và lấy key trong tab Cloud Messaging (Project Setting) có dạng
Server key: AAA..xyz
2. Setup trong Laravel
- Tạo một interface NotificationService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php namespace AppServicesNotification; interface NotificationService { public function sendBatchNotification($deviceTokens, $data); public function sendNotification($data); public function subscribeTopic($deviceTokens, $topicName); public function unsubscribeTopic($deviceTokens, $topicName); } |
- Tạo Một FcmService như sau
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | <?php namespace AppServicesNotification; use GuzzleHttpClient; use GuzzleHttpExceptionGuzzleException; use IlluminateHttpResponse; use IlluminateSupportFacadesLog; use Exception; class FcmService implements NotificationService { /** * @param $deviceTokens * @param $data * @throws GuzzleException */ public function sendBatchNotification($deviceTokens, $data = []) { self::subscribeTopic($deviceTokens, $data['topicName']); self::sendNotification($data, $data['topicName']); self::unsubscribeTopic($deviceTokens, $data['topicName']); } /** * @param $data * @param $topicName * @throws GuzzleException */ public function sendNotification($data, $topicName = null) { $url = 'https://fcm.googleapis.com/fcm/send'; $data = [ 'to' => '/topics/' . $topicName, 'notification' => [ 'body' => $data['body'] ?? 'Something', 'title' => $data['title'] ?? 'Something', 'image' => $data['image'] ?? null, ], 'data' => [ 'url' => $data['url'] ?? null, 'redirect_to' => $data['redirect_to'] ?? null, ], 'apns' => [ 'payload' => [ 'aps' => [ 'mutable-content' => 1, ], ], 'fcm_options' => [ 'image' => $data['image'] ?? null, ], ], ]; $this->execute($url, $data); } /** * @param $deviceToken * @param $topicName * @throws GuzzleException */ public function subscribeTopic($deviceTokens, $topicName = null) { $url = 'https://iid.googleapis.com/iid/v1:batchAdd'; $data = [ 'to' => '/topics/' . $topicName, 'registration_tokens' => $deviceTokens, ]; $this->execute($url, $data); } /** * @param $deviceToken * @param $topicName * @throws GuzzleException */ public function unsubscribeTopic($deviceTokens, $topicName = null) { $url = 'https://iid.googleapis.com/iid/v1:batchRemove'; $data = [ 'to' => '/topics/' . $topicName, 'registration_tokens' => $deviceTokens, ]; $this->execute($url, $data); } /** * @param $url * @param array $dataPost * @param string $method * @return bool * @throws GuzzleException */ private function execute($url, $dataPost = [], $method = 'POST') { $result = false; try { $client = new Client(); $result = $client->request($method, $url, [ 'headers' => [ 'Content-Type' => 'application/json', 'Authorization' => 'key=' . $keyInHere, ], 'json' => $dataPost, 'timeout' => 300, ]); $result = $result->getStatusCode() == Response::HTTP_OK; } catch (Exception $e) { Log::debug($e) } return $result; } } |
- Ý nghĩa từng hàm
–subscribeTopic
: Hàm này thực hiện để subscribe topic trên firebase và thực hiện được với nhiều device token.
–unsubscribeTopic
: Hàm này thực hiện để unsubscribe topic (cancel topic) trên firebase và thực hiện được với nhiều device token.
–sendNotification
: Dựa trên topic name và device token đã đươc đăng ký, hàm này thực hiên gửi notification dựa vào topic đã được gửi qua hàm subscribeTopic
, ý nghĩa của các attrubte
+to: để biết push notification đến topic nafo
+notification: tieu đề và nội dung của notification
+apns (for IOS): các option định sẵn như image chẳng hạn.
+data: thêm các custom attribute.
–sendBatchNotification
: Hàm này sẽ thực hiện tuần tự subscribeTopic -> sendNotification -> unsubscribeTopic.
- Tạo file PushNotificationJob như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <?php namespace AppJobs; use AppServicesNotificationNotificationService; use IlluminateBusQueueable; use IlluminateContractsQueueShouldQueue; use IlluminateFoundationBusDispatchable; use IlluminateQueueInteractsWithQueue; use IlluminateQueueSerializesModels; class PushNotificationJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; protected $serviceMethod; protected $methodParams; /** * Notification constructor. * @param $serviceMethod * @param $methodParams * @param string $methodHttp */ public function __construct($serviceMethod, $methodParams = [[]]) { $this->serviceMethod = $serviceMethod; $this->methodParams = $methodParams; } /** * @param NotificationService $notificationService */ public function handle(NotificationService $notificationService) { call_user_func_array( [ $notificationService, $this->serviceMethod, ], $this->methodParams ); } } |
- Giờ thì xem cách nó hoạt động thôi !!!
Giả sử có một bài toán như sau:Gửi notification đến những device có ngày sinh nhật vào ngày 25-10
(Vơi device token được lưu trong bảng User)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $deviceTokens = User::whereDay('birthday', now()->format('d')) ->whereMonth('birthday', now()->format('m')) ->pluck('device_token') ->toArray(); PushNotificationJob::dispatch('sendBatchNotification', [ $deviceTokens, [ 'topicName' => 'birthday', 'title' => 'Chúc mứng sinh nhật', 'body' => 'Chúc bạn sinh nhật vui vẻ', 'image' => 'https://picsum.photos/536/354', ], ]); |
III. Kết thúc
- Trên đây là cách gửi push notification được setup trên server sử dụng laravel. Hi vọng có thể giúp ích được cho các bạn trong qua trình phát triển sản phẩm m/