-
Notifications
You must be signed in to change notification settings - Fork 6
/
ExpoPushNotifications.php
110 lines (98 loc) · 4.02 KB
/
ExpoPushNotifications.php
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
<?php
namespace Relative\LaravelExpoPushNotifications;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Ramsey\Uuid\Uuid;
use Relative\LaravelExpoPushNotifications\Models\PushToken;
class ExpoPushNotifications
{
private string $baseUrl;
public function __construct()
{
$this->baseUrl = config('expo-push-notifications.service_url');
}
public function send($notifiable, Notification $notification): void
{
$batchId = Uuid::uuid4();
$message = $notification->toExpoPushNotification($notifiable);
$message->to = $notifiable->pushTokens()->active()->get()->pluck('token')->toArray();
$tickets = $this->dispatch($message);
$pushNotifications = collect($message->to)->map(function ($token, $index) use ($message, $tickets, $notifiable, $batchId) {
return $this->createPushNotificationRecord($tickets[$index], $token, $batchId, $message, $notifiable);
});
$receipts = collect($this->fetchReceipts($pushNotifications->pluck('ticket')->toArray()))->values();
$this->updatePushNotificationReceiptStatuses($tickets, $pushNotifications, $receipts);
}
public function dispatch($pushNotification): array
{
$response = Http::withHeaders([
'Accept' => 'application/json',
'Accept-encoding' => 'gzip, deflate',
'Content-Type' => 'application/json'
])->post("{$this->baseUrl}/send", (array)$pushNotification);
$responseJson = $response->json();
return $responseJson['data'] ?? [];
}
public function fetchReceipts(array $tickets): array
{
$response = Http::withHeaders([
'Accept' => 'application/json',
'Accept-encoding' => 'gzip, deflate',
'Content-Type' => 'application/json'
])->post("$this->baseUrl/getReceipts", [
'ids' => $tickets
]);
return $response->json()['data'];
}
/**
* @param $ticket
* @param $token
* @param \Ramsey\Uuid\UuidInterface $batchId
* @param $notification
* @param $notifiable
* @return mixed
*/
public function createPushNotificationRecord($ticket, $token, \Ramsey\Uuid\UuidInterface $batchId, $notification, $notifiable)
{
$pushToken = PushToken::findByReference($token);
$status = $ticket['status'] === 'error' ? 'error' : 'unknown';
if ($status === 'error' && $ticket['details']['error'] === 'DeviceNotRegistered') {
try {
$pushToken->expire();
} catch (\Exception $exception) {
Log::error("Unable to find token $token to expire");
}
}
$pushToken->touch();
return \Relative\LaravelExpoPushNotifications\Models\PushNotification::create([
'batch_id' => $batchId,
'notification' => (array)$notification,
'notifiable_id' => $notifiable->id,
'notifiable_type' => get_class($notifiable),
'token' => $token,
'status' => $status,
'ticket' => $ticket['id'] ?? '',
'error' => $status === 'error' ? $ticket['details']['error'] : null
]);
}
/**
* @param array $tickets
* @param Collection $pushNotifications
* @param Collection $receipts
*/
public function updatePushNotificationReceiptStatuses(array $tickets, Collection $pushNotifications, Collection $receipts): void
{
collect($tickets)->map(function ($ticket, $index) use ($pushNotifications, $receipts) {
$pushNotification = $pushNotifications[$index];
if (isset($ticket['id'])) {
$pushNotification->status = $receipts[$index]['status'] ?? 'unknown';
if ($pushNotification->status === 'error') {
$pushNotification->errors = $receipts[$pushNotification->ticket]['details']['error'];
}
$pushNotification->save();
}
});
}
}