PWA Payload and JSON

First time here, I have a problem with PWA push notifications.
It’s a chatting page made with PHP.
My push notifications are sent OK (on the phone and on the web). I have a push notification.

But there is a problem with the format of the received notification.

I received a notification text formatted like that :

{“title”:”Nouveau message de Maman”,”body”:”Test”,”icon”:”/icons/icone-app-72.png”,”url”:”/messagerie.php”}

I want to receive :

Nouveau message de maman

Test

Icons of the app and link on the click on the notification

It’s seems to be a parsing problem ? but no ideads where is problem and how to resolve it.

Payload seems to be the problem because when i try juste to send the function and do no pass informations with payload it’s OK.

Can anyone help me ?

Thanks a lot 🙂

$stmt = $pdo->prepare("SELECT endpoint, p256dh, auth FROM subscriptions WHERE user_id = ?");
        $stmt->execute([$destinataire_id]);
        $subscriptionData = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($subscriptionData) {
            $subscription = Subscription::create([
                'endpoint' => $subscriptionData['endpoint'],
                'keys' => [
                    'p256dh' => $subscriptionData['p256dh'],
                    'auth' => $subscriptionData['auth'],
                ],
            ]);
        
            $webPush = new WebPush([
                'VAPID' => [
                    'subject' => 'mailto:[email protected]',
                    'publicKey' => VAPID_PUBLIC_KEY,
                    'privateKey' => VAPID_PRIVATE_KEY,
                ],
            ]);
        
            // Payload spécifique pour la messagerie
            $payload = json_encode([
                'body' => 'Vous avez un nouveau message de ' . htmlspecialchars($_SESSION['nom']),
                'icon' => '/icons/icone-app-72.png',
                'url' => '/messagerie.php?utilisateur_id=' . $_SESSION['user_id'],
            ]);
        
            $webPush->queueNotification($subscription, $payload);
        
            foreach ($webPush->flush() as $report) {
                if (!$report->isSuccess()) {
                    error_log("Erreur d'envoi (messagerie) : " . $report->getReason());
                }
            }
        }

And here is my sw.js (services workers)

self.addEventListener('push', (event) => {
  console.log('Notification reçue.');

  let data = {
    body: 'Tu as une nouvelle notification.',
    icon: '/icons/icone-app-72.png',
    url: '/notifications.php', // URL par défaut pour redirection
  };

  try {
    // Extraire les données envoyées par le serveur (si présentes)
    if (event.data) {
      const payload = event.data.json();
      data = {
        body: payload.body || data.body,
        icon: payload.icon || data.icon,
        url: payload.url || data.url,
      };
    }
  } catch (error) {
    console.error('Erreur lors du traitement du payload:', error);
  }

  const options = {
    body: data.body,
    icon: data.icon,
    data: { url: data.url },
  };

  event.waitUntil(self.registration.showNotification('Notification', options));
});

self.addEventListener('notificationclick', (event) => {
  event.notification.close();

  if (event.notification.data && event.notification.data.url) {
    event.waitUntil(clients.openWindow(event.notification.data.url));
  }
});