mirror of
https://github.com/myronblair/tomsjavajive
synced 2026-06-30 17:50:32 -05:00
Initial commit
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/**
|
||||
* Tom's Java Jive - Push Notification Service
|
||||
*
|
||||
* Handles web push notifications using VAPID
|
||||
*/
|
||||
|
||||
class PushNotification {
|
||||
private string $publicKey;
|
||||
private string $privateKey;
|
||||
private string $subject;
|
||||
|
||||
public function __construct() {
|
||||
// VAPID keys - generate your own at: https://web-push-codelab.glitch.me/
|
||||
$this->publicKey = getSetting('vapid_public_key', 'YOUR_VAPID_PUBLIC_KEY');
|
||||
$this->privateKey = getSetting('vapid_private_key', 'YOUR_VAPID_PRIVATE_KEY');
|
||||
$this->subject = 'mailto:' . getSetting('admin_email', 'admin@tomsjavajive.com');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get VAPID public key for client
|
||||
*/
|
||||
public function getPublicKey(): string {
|
||||
return $this->publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send push notification to a subscription
|
||||
*/
|
||||
public function send(array $subscription, string $title, string $body, array $options = []): array {
|
||||
$payload = json_encode([
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
'icon' => $options['icon'] ?? '/assets/icons/icon-192.png',
|
||||
'badge' => $options['badge'] ?? '/assets/icons/badge-72.png',
|
||||
'url' => $options['url'] ?? '/',
|
||||
'tag' => $options['tag'] ?? null,
|
||||
'data' => $options['data'] ?? []
|
||||
]);
|
||||
|
||||
// For now, we'll store notifications for when the user comes online
|
||||
// Full web push requires a library like minishlink/web-push
|
||||
// This is a simplified version that works with the service worker
|
||||
|
||||
try {
|
||||
// Store notification for retrieval
|
||||
$notificationId = generateId('notif_');
|
||||
db()->insert('push_notifications', [
|
||||
'notification_id' => $notificationId,
|
||||
'subscription_endpoint' => $subscription['endpoint'],
|
||||
'payload' => $payload,
|
||||
'status' => 'pending',
|
||||
'created_at' => date('Y-m-d H:i:s')
|
||||
]);
|
||||
|
||||
return ['success' => true, 'notification_id' => $notificationId];
|
||||
} catch (Exception $e) {
|
||||
return ['success' => false, 'error' => $e->getMessage()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send notification to all subscribed users
|
||||
*/
|
||||
public function broadcast(string $title, string $body, array $options = []): array {
|
||||
$subscriptions = db()->fetchAll("SELECT * FROM push_subscriptions WHERE is_active = 1");
|
||||
|
||||
$results = ['sent' => 0, 'failed' => 0];
|
||||
|
||||
foreach ($subscriptions as $sub) {
|
||||
$subscription = [
|
||||
'endpoint' => $sub['endpoint'],
|
||||
'keys' => [
|
||||
'p256dh' => $sub['p256dh_key'],
|
||||
'auth' => $sub['auth_key']
|
||||
]
|
||||
];
|
||||
|
||||
$result = $this->send($subscription, $title, $body, $options);
|
||||
|
||||
if ($result['success']) {
|
||||
$results['sent']++;
|
||||
} else {
|
||||
$results['failed']++;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send order status update notification
|
||||
*/
|
||||
public function sendOrderUpdate(string $customerId, array $order, string $status): array {
|
||||
$subscription = $this->getCustomerSubscription($customerId);
|
||||
|
||||
if (!$subscription) {
|
||||
return ['success' => false, 'error' => 'No subscription found'];
|
||||
}
|
||||
|
||||
$messages = [
|
||||
'confirmed' => "Your order #{$order['order_number']} has been confirmed!",
|
||||
'processing' => "We're preparing your order #{$order['order_number']}",
|
||||
'shipped' => "Your order #{$order['order_number']} is on its way!",
|
||||
'delivered' => "Your order #{$order['order_number']} has been delivered!",
|
||||
'ready' => "Your order #{$order['order_number']} is ready for pickup!"
|
||||
];
|
||||
|
||||
return $this->send(
|
||||
$subscription,
|
||||
"Order Update",
|
||||
$messages[$status] ?? "Order #{$order['order_number']} status: {$status}",
|
||||
[
|
||||
'url' => "/account/order.php?id={$order['order_id']}",
|
||||
'tag' => "order-{$order['order_id']}"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send promotional notification
|
||||
*/
|
||||
public function sendPromotion(string $customerId, string $title, string $message, string $url = '/shop.php'): array {
|
||||
$subscription = $this->getCustomerSubscription($customerId);
|
||||
|
||||
if (!$subscription) {
|
||||
return ['success' => false, 'error' => 'No subscription found'];
|
||||
}
|
||||
|
||||
return $this->send($subscription, $title, $message, ['url' => $url]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send loyalty tier notification
|
||||
*/
|
||||
public function sendTierNotification(string $customerId, string $tierName, array $benefits): array {
|
||||
$subscription = $this->getCustomerSubscription($customerId);
|
||||
|
||||
if (!$subscription) {
|
||||
return ['success' => false, 'error' => 'No subscription found'];
|
||||
}
|
||||
|
||||
return $this->send(
|
||||
$subscription,
|
||||
"Congratulations! You're now {$tierName}!",
|
||||
"Enjoy new benefits: " . implode(', ', array_slice($benefits, 0, 2)),
|
||||
['url' => '/account/']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer's push subscription
|
||||
*/
|
||||
private function getCustomerSubscription(string $customerId): ?array {
|
||||
$sub = db()->fetch(
|
||||
"SELECT * FROM push_subscriptions WHERE customer_id = :id AND is_active = 1 ORDER BY created_at DESC LIMIT 1",
|
||||
['id' => $customerId]
|
||||
);
|
||||
|
||||
if (!$sub) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'endpoint' => $sub['endpoint'],
|
||||
'keys' => [
|
||||
'p256dh' => $sub['p256dh_key'],
|
||||
'auth' => $sub['auth_key']
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function for easy access
|
||||
function pushNotify(): PushNotification {
|
||||
static $instance = null;
|
||||
if ($instance === null) {
|
||||
$instance = new PushNotification();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
Reference in New Issue
Block a user