WebPush
TsgcHTMLWebPush: Web Push para un navegador que no está en ejecución o que no está en tu página, en Delphi, C++ Builder y .NET. Disponible solo en las ediciones Enterprise y All-Access.
TsgcHTMLWebPush: Web Push para un navegador que no está en ejecución o que no está en tu página, en Delphi, C++ Builder y .NET. Disponible solo en las ediciones Enterprise y All-Access.
Web Push llega a un usuario cuyo navegador está cerrado o mostrando otra página. La página se suscribe, tu aplicación almacena la suscripción mediante tres eventos, y una llamada a Send entrega la notificación. Disponible solo en las ediciones Enterprise y All-Access.
TsgcHTMLWebPush (unidad sgcHTML_WebPush)
Sin marcado: mensajes push cifrados enviados al navegador
Delphi, C++ Builder, .NET
Genera un par de claves VAPID una vez y consérvalo. Asigna el par y un Subject, responde a los eventos de almacenamiento, establece WebPush en el motor y WebPushEnabled en su plantilla, y luego llama a 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>
Los miembros que usarás con más frecuencia.
Web Push está disponible solo en las ediciones Enterprise y All-Access. La unidad se compila cuando SGC_WEBPUSH está definido, algo que sgcVer.inc establece para esas dos ediciones, y además necesita el propio sgcHTML, que se vende de forma independiente. La bandeja de notificaciones y la tabla de preferencias forman parte de sgcHTML y no lo necesitan; solo lo necesita el canal push.
GenerateVAPIDKeys es un método de clase que devuelve un par nuevo: la mitad pública es la clave de servidor de aplicación en base64url con la que se suscribe el navegador, la mitad privada una clave EC en PEM. Asígnalas a VAPIDPublicKey y VAPIDPrivateKey. Subject es el contacto VAPID, un URI mailto: o https:. La compilación estándar de Delphi carga OpenSSL 3.x para la criptografía y selecciona esa API por sí misma; la versión .NET usa criptografía administrada y no necesita OpenSSL.
El componente no guarda ninguna suscripción propia. OnSaveSubscription(aUserID, aEndpoint, aP256dh, aAuth) guarda una, OnLoadSubscriptions(aUserID, aList) rellena aList con un Add(endpoint, p256dh, auth) por cada suscripción almacenada del usuario, y OnDeleteSubscription(aUserID, aEndpoint) elimina una. Cada entrada es un TsgcHTMLWebPushSubscription.
Send(aUserID, aTitle, aBody, aURL, aIcon, aTag, aTTL, aUrgency) cifra una notificación por cada suscripción almacenada del usuario (RFC 8291) y la envía por POST al servicio push con una firma VAPID (RFC 8292). Devuelve a cuántas suscripciones la entregó, o 0 cuando Enabled es False. El emisor, TsgcHTMLWebPushClient, reutiliza TsgcHTTP_API_WebPush_Client.
TTL vale por defecto 2419200 segundos (28 días) y Urgency está vacío, lo que no envía ninguna cabecera de urgencia. Pasa aTTL o aUrgency a Send para cambiar cualquiera de los dos en una notificación.
Cuando un servicio push responde 404 o 410, se dispara OnSubscriptionExpired(aUserID, aEndpoint, aStatusCode) para que puedas descartar la suscripción. Cualquier otro fallo dispara OnSendError(aUserID, aEndpoint, E) y se siguen intentando las suscripciones restantes.
Una vez que el componente está asignado al motor, un POST a SubscribeEndpoint (/push/subscribe) o a UnsubscribeEndpoint (/push/unsubscribe) se responde por ti: 204 cuando se procesa, 400 para una suscripción no válida, 403 cuando no se resuelve ningún usuario, 413 por encima de 64 KB. Llama tú mismo a HandleSubscribe(aJSON, aUserID) y HandleUnsubscribe para enrutar los POST a tu manera.
El usuario nunca se lee de lo que envía el navegador. Con un TsgcHTMLAuth en el motor es el usuario de la cookie de sesión, y el token CSRF es obligatorio. Sin él, OnResolveUser(aCookieHeader, aHeaders, aBody, aUserID, aAllowed) responde con tu propio id de usuario o lo rechaza. Sin ninguno de los dos, la petición recibe 403.
Con Template.WebPushEnabled activado, el motor copia la clave pública y los endpoints en la plantilla, sirve el service worker en ServiceWorkerPath y la página lleva el script de suscripción. Pon <button data-sgc-webpush> en la página para que la solicitud de permiso se ejecute desde un clic; data-sgc-webpush="unsubscribe" lo desactiva. Los navegadores necesitan https, o localhost durante el desarrollo.
TsgcHTMLComponent_Notification elige entre los dos. Asigna Presence y WebPush, responde a OnGetChannel con ncPush y llama a AddNotification(aUserID, aId, aTitle, aMessage, ...): un usuario conectado recibe la notificación en la página, un usuario que no está conectado recibe un Send, de modo que nadie recibe el aviso dos veces. Sin un manejador de OnGetChannel nunca se envía nada por push.
| Ayuda en líneaReferencia completa de la API y guía de uso para este componente. | Abrir | |
| Guía de Web PushCómo encajan las piezas: suscripciones, VAPID, los endpoints del motor y el componente de notificaciones. | Abrir | |
| Todos los componentes de sgcHTMLExplora la matriz completa de más de 80 componentes. | Abrir | |
| Descargar prueba gratuitaLa prueba de 30 días incluye los proyectos de demostración 60.HTML, entre ellos 17.FieldService, que usa Web Push. | Abrir | |
| PreciosLicencias Single, Team y Site con código fuente completo. | Abrir |