WebPush

TsgcHTMLWebPush: Web Push voor een browser die niet draait of niet op je pagina staat, in Delphi, C++ Builder en .NET. Alleen beschikbaar in de Enterprise- en All-Access-edities.

TsgcHTMLWebPush

Web Push bereikt een gebruiker wiens browser gesloten is of een andere pagina toont. De pagina abonneert zich, je applicatie slaat het abonnement op via drie gebeurtenissen, en één aanroep van Send levert de melding af. Alleen beschikbaar in de Enterprise- en All-Access-edities.

Componentklasse

TsgcHTMLWebPush (unit sgcHTML_WebPush)

Rendert

Geen markup: versleutelde pushberichten die naar de browser worden gestuurd

Talen

Delphi, C++ Builder, .NET

Genereer sleutels, sla abonnementen op, verstuur

Genereer eenmalig een VAPID-sleutelpaar en bewaar het. Wijs het paar en een Subject toe, handel de opslaggebeurtenissen af, stel WebPush in op de engine en WebPushEnabled op de sjabloon ervan, en roep dan Send aan.

// 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>

Belangrijkste eigenschappen en methoden

De members die je het vaakst gebruikt.

Edities

Web Push is alleen beschikbaar in de Enterprise- en All-Access-edities. De unit compileert wanneer SGC_WEBPUSH is gedefinieerd, wat sgcVer.inc instelt voor die twee edities, en heeft ook sgcHTML zelf nodig, dat los wordt verkocht. De meldingeninbox en de tabel met voorkeuren maken deel uit van sgcHTML en hebben het niet nodig: alleen het pushkanaal wel.

VAPID-sleutels

GenerateVAPIDKeys is een klassemethode die een nieuw paar teruggeeft: de publieke helft is de base64url application server key waarmee de browser zich abonneert, de private helft een EC-sleutel in PEM. Wijs ze toe aan VAPIDPublicKey en VAPIDPrivateKey. Subject is het VAPID-contact, een mailto:- of https:-URI. De standaard Delphi-build laadt OpenSSL 3.x voor de cryptografie en kiest die API zelf; de .NET-port gebruikt managed cryptografie en heeft geen OpenSSL nodig.

Opslaggebeurtenissen

Het component houdt zelf geen abonnement bij. OnSaveSubscription(aUserID, aEndpoint, aP256dh, aAuth) slaat er een op, OnLoadSubscriptions(aUserID, aList) vult aList met één Add(endpoint, p256dh, auth) per opgeslagen abonnement van de gebruiker, en OnDeleteSubscription(aUserID, aEndpoint) verwijdert er een. Elk item is een TsgcHTMLWebPushSubscription.

Versturen

Send(aUserID, aTitle, aBody, aURL, aIcon, aTag, aTTL, aUrgency) versleutelt één melding per opgeslagen abonnement van de gebruiker (RFC 8291) en POST die met een VAPID-handtekening (RFC 8292) naar de pushservice. Het geeft terug aan hoeveel abonnementen het heeft afgeleverd, of 0 wanneer Enabled False is. De verzender, TsgcHTMLWebPushClient, hergebruikt TsgcHTTP_API_WebPush_Client.

Time-to-live en urgentie

TTL is standaard 2419200 seconden (28 dagen) en Urgency is leeg, waardoor er geen urgency-header wordt verstuurd. Geef aTTL of aUrgency mee aan Send om een van beide voor één melding te overschrijven.

Verlopen en mislukte verzendingen

Wanneer een pushservice met 404 of 410 antwoordt, wordt OnSubscriptionExpired(aUserID, aEndpoint, aStatusCode) aangeroepen zodat je het abonnement kunt verwijderen. Elke andere fout roept OnSendError(aUserID, aEndpoint, E) op en de overige abonnementen worden nog steeds geprobeerd.

Subscribe-endpoints

Zodra het component aan de engine is toegewezen, wordt een POST naar SubscribeEndpoint (/push/subscribe) of UnsubscribeEndpoint (/push/unsubscribe) voor je beantwoord: 204 wanneer afgehandeld, 400 voor een ongeldig abonnement, 403 wanneer er geen gebruiker wordt bepaald, 413 boven 64 KB. Roep HandleSubscribe(aJSON, aUserID) en HandleUnsubscribe zelf aan om de POST-verzoeken op je eigen manier te routeren.

Wie zich abonneert

De gebruiker wordt nooit gelezen uit wat de browser post. Met een TsgcHTMLAuth op de engine is het de gebruiker van de sessiecookie en is het CSRF-token vereist. Zonder Auth antwoordt OnResolveUser(aCookieHeader, aHeaders, aBody, aUserID, aAllowed) met je eigen gebruikers-id of weigert. Met geen van beide krijgt het verzoek 403.

In de pagina

Als Template.WebPushEnabled aan staat, kopieert de engine de publieke sleutel en de endpoints naar de sjabloon, serveert de service worker op ServiceWorkerPath en bevat de pagina het subscribe-script. Zet <button data-sgc-webpush> in de pagina zodat de toestemmingsvraag door een klik wordt gestart; data-sgc-webpush="unsubscribe" schakelt het uit. Browsers hebben https nodig, of localhost tijdens de ontwikkeling.

Pagina of push

TsgcHTMLComponent_Notification kiest tussen de twee. Wijs Presence en WebPush toe, beantwoord OnGetChannel met ncPush en roep AddNotification(aUserID, aId, aTitle, aMessage, ...) aan: een verbonden gebruiker krijgt de melding in de pagina, een gebruiker die niet verbonden is krijgt één Send, zodat niemand twee keer wordt ingelicht. Zonder OnGetChannel-eventhandler wordt er nooit iets gepusht.

Blijf ontdekken

Online helpVolledige API-referentie en gebruikshandleiding voor dit onderdeel.
Web Push-handleidingHoe de onderdelen in elkaar passen: abonnementen, VAPID, de endpoints van de engine en het meldingscomponent.
Alle sgcHTML-componentenBlader door de volledige functiematrix van 80+ componenten.
Download gratis proefversieDe proefversie van 30 dagen bevat de 60.HTML-demoprojecten, waaronder 17.FieldService, dat Web Push gebruikt.
PrijzenSingle-, Team- en Site-licenties met volledige broncode.
De beste deal: All-AccessElk eSeGeCe-product, inclusief Premium-ondersteuning, vanaf €1,059 per jaar.
Bekijk de All-Access-prijzen

Klaar om te beginnen?

Download de gratis proefversie en begin met het bouwen van web-UI's in Delphi, C++ Builder en .NET.