Azure Notification Hubs for push notifications in laravel and nextjs

To add native notifications to your frontend Next.js app (using Azure Notification Hubs for push notifications), along with CapacitorJS for building mobile apps, you’ll need to handle both web and mobile notification flows. Here’s an outline of the steps:

1. Set Up Azure Notification Hubs

You’ve already set up Azure Notification Hubs as your push notification service, but ensure:

  • Notification Hub is configured for the platforms you plan to support (e.g., iOS, Android, and Web).
  • Register your Notification Hub with appropriate APNs (Apple Push Notification service) and Firebase Cloud Messaging (FCM) credentials.

2. Configure Capacitor for Push Notifications (Mobile Apps)

CapacitorJS has built-in support for handling push notifications on iOS and Android.

  • Install the Capacitor push notification
npm install @capacitor/push-notifications
npx cap sync
  • Modify the iOS/Android app-specific files:
    • iOS: Configure APNs certificates in Xcode and ensure push notifications are enabled.
    • Android: Use Firebase Cloud Messaging (FCM) by adding the google-services.json (Firebase config file) to your Android app and updating your AndroidManifest.xml.
  • In your Next.js app, register the push notifications in your Capacitor app:
import { PushNotifications } from '@capacitor/push-notifications';

PushNotifications.requestPermissions().then((result) => {
  if (result.receive === 'granted') {
    PushNotifications.register();
  }
});

PushNotifications.addListener('pushNotificationReceived', (notification) => {
  console.log('Notification received: ', notification);
});

This setup will allow your CapacitorJS-based mobile app to handle native notifications for both iOS and Android.

3. Add Web Push Notifications (PWA)

For web push notifications, you can use the Web Push API. Here’s how to implement it for your Next.js app:

  • Service Worker: First, register a Service Worker for web push notifications in your Next.js app. Create a file public/sw.js (Service Worker script) and register it in your pages/_app.js:js
useEffect(() => {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js').then(registration => {
      console.log('Service Worker registered:', registration);
    }).catch(error => {
      console.log('Service Worker registration failed:', error);
    });
  }
}, []);
  • Handle Notifications in Service Worker: In sw.js, add a listener to display the notification:
self.addEventListener('push', function(event) {
  const data = event.data.json();
  self.registration.showNotification(data.title, {
    body: data.body,
    icon: data.icon,
  });
});
  • Push API Registration: Register the user for push notifications:
if ('serviceWorker' in navigator && 'PushManager' in window) {
  navigator.serviceWorker.ready.then(function(reg) {
    return reg.pushManager.subscribe({
      userVisibleOnly: true,
      applicationServerKey: '<Your VAPID Public Key>',
    });
  }).then(function(subscription) {
    // Send the subscription object to the server
  });
}
  • Connect to Azure Notification Hubs: After obtaining the push subscription (which includes the endpoint, keys, etc.) – the subscription object will look something like this:
{
  "endpoint": "https://fcm.googleapis.com/fcm/send/abc123...",
  "keys": {
    "p256dh": "BN...",
    "auth": "q1..."
  }
}
  • Send the subscription response to your backend server:
fetch('/api/store-subscription', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(subscription),
});

4. Backend Integration (Laravel with Azure Notification Hubs)

Your Laravel backend will serve as the central point to handle push notifications for both mobile and web platforms.

  • Store the Subscription: Store the user’s push subscription in a database, with fields like endpoint, p256dh, and auth.
// Example of saving subscription data in Laravel, eg from the /api/store-subscription endpoint

$subscription = request()->all();
DB::table('push_subscriptions')->insert([
    'endpoint' => $subscription['endpoint'],
    'p256dh' => $subscription['keys']['p256dh'],
    'auth' => $subscription['keys']['auth'],
]);
  • Use Guzzle to interact with Azure Notification Hubs:
composer require require guzzlehttp/guzzle

Set up Azure Notification Hub API

  • You will interact with the Azure Notification Hub REST API to send notifications.
  • You can obtain the necessary connection string and hub name from your Azure portal.
  • Here is an example of how to use Guzzle to send a notification to Azure Notification Hubs:
use GuzzleHttp\Client;

function sendNotification($message, $tag = null) {
    $hubName = '<your-hub-name>';
    $connectionString = "Endpoint=sb://<your-hub>.servicebus.windows.net/;SharedAccessKeyName=<your-key-name>;SharedAccessKey=<your-key>";
    $uri = "https://<your-hub>.servicebus.windows.net/<your-namespace>/messages/";
    $endpoint = "https://$hubName.servicebus.windows.net/$hubName/messages/?api-version=2015-01";
    
    // Parse connection string to get SAS token
    $sasToken = generateSasToken($connectionString, $uri);

    $client = new Client();
    
    // Notification payload (adapt it according to the platform)
    $payload = json_encode([
        'notification' => [
            'title' => 'New Alert',
            'body' => $message,
            'icon' => 'your-icon-url'
        ]
    ]);
    
    $headers = [
        'Authorization' => $sasToken,
        'Content-Type' => 'application/json',
        'ServiceBusNotification-Format' => 'gcm', // Change to 'apns' or 'wns' for iOS or Windows
        'ServiceBusNotification-Tags' => $tag // Optional tag for targeting specific audiences
    ];

    $response = $client->post($endpoint, [
        'headers' => $headers,
        'body' => $payload
    ]);

    return $response->getStatusCode();
}

// Helper function to generate SAS token
function generateSasToken($connectionString, $uri) {
    // Parse the connection string into parts (Endpoint, SharedAccessKeyName, and SharedAccessKey)
    $parts = [];
    parse_str(str_replace(";", "&", $connectionString), $parts);

    $endpoint = $parts['Endpoint'];
    $sasKeyName = $parts['SharedAccessKeyName'];
    $sasKeyValue = $parts['SharedAccessKey'];

    // Define the target URI (must be URL-encoded)
    $targetUri = strtolower(rawurlencode($uri));
    
    // Set the expiry time for the token (1 hour in this case)
    $expiry = time() + 3600;

    // Create the string to sign
    $toSign = $targetUri . "\n" . $expiry;

    // Generate the HMAC SHA-256 hash using the shared access key
    $signature = base64_encode(hash_hmac('sha256', $toSign, $sasKeyValue, true));

    // Construct the SAS token
    $sasToken = "SharedAccessSignature sr={$targetUri}&sig=" . rawurlencode($signature) . "&se={$expiry}&skn={$sasKeyName}";

    return $sasToken;
}

You can modify the logic to send notifications to APNs (iOS) and web push notifications as well.

5. Notification Payload Format

For web push notifications, the payload must be properly structured. Azure Notification Hubs expects a payload in JSON format that includes details like title, body, icon, and actions for the notification.

{
  "title": "New message!",
  "body": "You have received a new message.",
  "icon": "/img/icon.png",
  "data": {
    "url": "https://example.com/messages"
  }
}

6. Testing Notifications

  • Test your notifications for mobile apps (using CapacitorJS and Azure Notification Hubs) on real devices.
  • For web push notifications, use the browser’s developer tools to inspect the Service Worker and simulate push notifications.

Leave a Reply