WebPush

TsgcHTMLWebPush: Web Push dla przeglądarki, która nie jest uruchomiona lub nie jest na Twojej stronie, w Delphi, C++ Builder i .NET. Dostępny tylko w edycjach Enterprise i All-Access.

TsgcHTMLWebPush

Web Push dociera do użytkownika, którego przeglądarka jest zamknięta lub pokazuje inną stronę. Strona tworzy subskrypcję, Twoja aplikacja przechowuje ją przez trzy zdarzenia, a jedno wywołanie Send dostarcza powiadomienie. Dostępny tylko w edycjach Enterprise i All-Access.

Klasa komponentu

TsgcHTMLWebPush (jednostka sgcHTML_WebPush)

Renderuje

Bez znaczników: szyfrowane wiadomości push wysyłane do przeglądarki

Języki

Delphi, C++ Builder, .NET

Wygeneruj klucze, zapisz subskrypcje, wyślij

Wygeneruj raz parę kluczy VAPID i zachowaj ją. Przypisz parę oraz Subject, obsłuż zdarzenia magazynu, ustaw WebPush w silniku i WebPushEnabled w jego szablonie, a następnie wywołaj Send.

// Enterprise and All-Access only: compiled when SGC_WEBPUSH is defined
uses
  Data.DB, sgcHTML_WebPush, sgcHTMX_Engine_Server;

var
  vPublic, vPrivate: string;
begin
  // once, then keep both values in your own settings
  TsgcHTMLWebPush.GenerateVAPIDKeys(vPublic, vPrivate);

  FPush := TsgcHTMLWebPush.Create(Self);
  FPush.VAPIDPublicKey := vPublic;
  FPush.VAPIDPrivateKey := vPrivate;
  FPush.Subject := 'mailto:support@example.com';
  FPush.OnSaveSubscription := PushSave;
  FPush.OnLoadSubscriptions := PushLoad;
  FPush.OnDeleteSubscription := PushDelete;
  FPush.OnSubscriptionExpired := PushExpired;
  FPush.Enabled := True;

  // oHTMX is a TsgcHTMX_Engine_Server
  oHTMX.WebPush := FPush;
  oHTMX.Template.WebPushEnabled := True;

  // later, from anywhere in the application
  FPush.Send('u1', 'Order shipped',
    'Order 1042 left the warehouse', '/orders/1042');
end;

// the application owns the storage
procedure TForm1.PushSave(Sender: TObject;
  const aUserID, aEndpoint, aP256dh, aAuth: string);
begin
  SaveSubscription(aUserID, aEndpoint, aP256dh, aAuth);
end;

procedure TForm1.PushLoad(Sender: TObject; const aUserID: string;
  const aList: TsgcHTMLWebPushSubscriptions);
var
  oQuery: TDataSet;
begin
  oQuery := OpenSubscriptions(aUserID);
  try
    // one Add per stored subscription of this user
    while not oQuery.Eof do
    begin
      aList.Add(oQuery.FieldByName('endpoint').AsString,
        oQuery.FieldByName('p256dh').AsString,
        oQuery.FieldByName('auth').AsString);
      oQuery.Next;
    end;
  finally
    oQuery.Free;
  end;
end;

procedure TForm1.PushDelete(Sender: TObject; const aUserID, aEndpoint: string);
begin
  DeleteSubscription(aUserID, aEndpoint);
end;

procedure TForm1.PushExpired(Sender: TObject;
  const aUserID, aEndpoint: string; aStatusCode: Integer);
begin
  // 404 or 410: the push service dropped it for good
  DeleteSubscription(aUserID, aEndpoint);
end;

// in the page, a click starts the permission prompt:
// <button data-sgc-webpush>Enable notifications</button>
// includes: sgcHTML_WebPush.hpp, sgcHTMX_Engine_Server.hpp
// Enterprise and All-Access only: compiled when SGC_WEBPUSH is defined

String vPublic, vPrivate;
// once, then keep both values in your own settings
TsgcHTMLWebPush::GenerateVAPIDKeys(vPublic, vPrivate);

FPush = new TsgcHTMLWebPush(this);
FPush->VAPIDPublicKey = vPublic;
FPush->VAPIDPrivateKey = vPrivate;
FPush->Subject = "mailto:support@example.com";
FPush->OnSaveSubscription = PushSave;
FPush->OnLoadSubscriptions = PushLoad;
FPush->OnDeleteSubscription = PushDelete;
FPush->OnSubscriptionExpired = PushExpired;
FPush->Enabled = true;

// oHTMX is a TsgcHTMX_Engine_Server
oHTMX->WebPush = FPush;
oHTMX->Template->WebPushEnabled = true;

// later, from anywhere in the application
FPush->Send("u1", "Order shipped",
  "Order 1042 left the warehouse", "/orders/1042");

// the application owns the storage
void __fastcall TForm1::PushSave(TObject *Sender,
  const UnicodeString aUserID, const UnicodeString aEndpoint,
  const UnicodeString aP256dh, const UnicodeString aAuth)
{
  SaveSubscription(aUserID, aEndpoint, aP256dh, aAuth);
}

void __fastcall TForm1::PushLoad(TObject *Sender, const UnicodeString aUserID,
  TsgcHTMLWebPushSubscriptions *const aList)
{
  // one Add per stored subscription of this user
  for (const TStoredSubscription &row : LoadSubscriptions(aUserID))
    aList->Add(row.Endpoint, row.P256dh, row.Auth);
}

// in the page, a click starts the permission prompt:
// <button data-sgc-webpush>Enable notifications</button>
using esegece.sgcWebSockets;

// once, then keep both values in your own settings
TsgcHTMLWebPush.GenerateVAPIDKeys(out var pub, out var priv);

var push = new TsgcHTMLWebPush();
push.VAPIDPublicKey = pub;
push.VAPIDPrivateKey = priv;
push.Subject = "mailto:support@example.com";

// the application owns the storage
push.OnSaveSubscription += (sender, aUserID, aEndpoint, aP256dh, aAuth) =>
    SaveSubscription(aUserID, aEndpoint, aP256dh, aAuth);
push.OnLoadSubscriptions += (sender, aUserID, aList) =>
{
    // one Add per stored subscription of this user
    foreach (var row in LoadSubscriptions(aUserID))
        aList.Add(row.Endpoint, row.P256dh, row.Auth);
};
push.OnDeleteSubscription += (sender, aUserID, aEndpoint) =>
    DeleteSubscription(aUserID, aEndpoint);
push.OnSubscriptionExpired += (sender, aUserID, aEndpoint, aStatusCode) =>
    DeleteSubscription(aUserID, aEndpoint);   // 404 or 410: gone for good
push.Enabled = true;

// htmx is a TsgcHTMX_Engine_Server
htmx.WebPush = push;
htmx.Template.WebPushEnabled = true;

// later, from anywhere in the application
int delivered = push.Send("u1", "Order shipped",
    "Order 1042 left the warehouse", "/orders/1042");

// in the page, a click starts the permission prompt:
// <button data-sgc-webpush>Enable notifications</button>

Kluczowe właściwości i metody

Składniki, po które sięgasz najczęściej.

Edycje

Web Push jest dostępny tylko w edycjach Enterprise i All-Access. Jednostka kompiluje się, gdy zdefiniowane jest SGC_WEBPUSH, co sgcVer.inc ustawia dla tych dwóch edycji, a potrzebuje też samego sgcHTML, sprzedawanego niezależnie. Skrzynka powiadomień i tabela preferencji są częścią sgcHTML i nie wymagają go: potrzebuje go tylko kanał push.

Klucze VAPID

GenerateVAPIDKeys to metoda klasy, która zwraca nową parę: połowa publiczna to klucz serwera aplikacji w base64url, z którym przeglądarka tworzy subskrypcję, a połowa prywatna to klucz EC w PEM. Przypisz je do VAPIDPublicKey i VAPIDPrivateKey. Subject to kontakt VAPID, czyli URI mailto: lub https:. Standardowa wersja Delphi ładuje OpenSSL 3.x do kryptografii i sama wybiera to API; port .NET używa kryptografii zarządzanej i nie potrzebuje OpenSSL.

Zdarzenia magazynu

Komponent nie przechowuje żadnej własnej subskrypcji. OnSaveSubscription(aUserID, aEndpoint, aP256dh, aAuth) zapisuje jedną, OnLoadSubscriptions(aUserID, aList) wypełnia aList jednym Add(endpoint, p256dh, auth) dla każdej zapisanej subskrypcji użytkownika, a OnDeleteSubscription(aUserID, aEndpoint) usuwa jedną. Każdy wpis to TsgcHTMLWebPushSubscription.

Wysyłanie

Send(aUserID, aTitle, aBody, aURL, aIcon, aTag, aTTL, aUrgency) szyfruje jedno powiadomienie dla każdej zapisanej subskrypcji użytkownika (RFC 8291) i wysyła je metodą POST do usługi push z podpisem VAPID (RFC 8292). Zwraca liczbę subskrypcji, do których dostarczono powiadomienie, lub 0, gdy Enabled ma wartość False. Nadawca, TsgcHTMLWebPushClient, ponownie wykorzystuje TsgcHTTP_API_WebPush_Client.

Czas życia i pilność

TTL domyślnie wynosi 2419200 sekund (28 dni), a Urgency jest puste, co nie wysyła nagłówka pilności. Przekaż aTTL lub aUrgency do Send, aby zastąpić każde z nich dla jednego powiadomienia.

Wygasłe i nieudane wysyłki

Gdy usługa push odpowie 404 lub 410, wywoływane jest OnSubscriptionExpired(aUserID, aEndpoint, aStatusCode), dzięki czemu możesz usunąć subskrypcję. Każdy inny błąd wywołuje OnSendError(aUserID, aEndpoint, E), a pozostałe subskrypcje są nadal próbowane.

Punkty końcowe subskrypcji

Gdy komponent zostanie przypisany do silnika, POST do SubscribeEndpoint (/push/subscribe) lub UnsubscribeEndpoint (/push/unsubscribe) jest obsługiwany za Ciebie: 204, gdy obsłużono, 400 dla nieprawidłowej subskrypcji, 403, gdy żaden użytkownik nie zostanie ustalony, 413 powyżej 64 KB. Wywołaj HandleSubscribe(aJSON, aUserID) i HandleUnsubscribe samodzielnie, aby obsłużyć żądania POST na własny sposób.

Kto się subskrybuje

Użytkownik nigdy nie jest odczytywany z tego, co wysyła przeglądarka. Gdy w silniku jest TsgcHTMLAuth, jest to użytkownik z ciasteczka sesji i wymagany jest token CSRF. Bez niego OnResolveUser(aCookieHeader, aHeaders, aBody, aUserID, aAllowed) odpowiada Twoim własnym identyfikatorem użytkownika albo odmawia. Bez żadnego z nich żądanie dostaje 403.

Na stronie

Gdy Template.WebPushEnabled jest włączone, silnik kopiuje klucz publiczny i punkty końcowe do szablonu, serwuje service worker pod ServiceWorkerPath, a strona zawiera skrypt subskrypcji. Umieść <button data-sgc-webpush> na stronie, aby prośba o zgodę uruchamiała się z kliknięcia; data-sgc-webpush="unsubscribe" wyłącza subskrypcję. Przeglądarki wymagają https, a podczas pracy nad aplikacją wystarczy localhost.

Strona czy push

TsgcHTMLComponent_Notification wybiera między nimi. Przypisz Presence i WebPush, odpowiedz w OnGetChannel wartością ncPush i wywołaj AddNotification(aUserID, aId, aTitle, aMessage, ...): połączony użytkownik dostaje powiadomienie na stronie, użytkownik niepołączony dostaje jedno Send, więc nikt nie jest powiadamiany dwa razy. Bez procedury obsługi OnGetChannel nic nigdy nie jest wysyłane push.

Poznawaj dalej

Pomoc onlinePełna dokumentacja API i przewodnik użytkowania tego komponentu.
Przewodnik po Web PushJak łączą się poszczególne elementy: subskrypcje, VAPID, punkty końcowe silnika i komponent powiadomień.
Wszystkie komponenty sgcHTMLPrzejrzyj pełną matrycę funkcji 80+ komponentów.
Pobierz bezpłatną wersję próbną30-dniowa wersja próbna zawiera projekty demonstracyjne 60.HTML, w tym 17.FieldService, który używa Web Push.
CennikLicencje Single, Team i Site z pełnym kodem źródłowym.
Najkorzystniejsza oferta: All-AccessWszystkie produkty eSeGeCe, ze wsparciem Premium w cenie, już od €1,059 rocznie.
Zobacz cennik All-Access

Gotowy, aby zacząć?

Pobierz bezpłatną wersję próbną i zacznij budować interfejsy webowe w Delphi, C++ Builder i .NET.