WebPush

TsgcHTMLWebPush: Web Push para um navegador que não está em execução ou que não está na sua página, em Delphi, C++ Builder e .NET. Disponível somente nas edições Enterprise e All-Access.

TsgcHTMLWebPush

O Web Push alcança um usuário cujo navegador está fechado ou exibindo outra página. A página se inscreve, a sua aplicação guarda a inscrição por meio de três eventos, e uma chamada a Send entrega a notificação. Disponível somente nas edições Enterprise e All-Access.

Classe do componente

TsgcHTMLWebPush (unit sgcHTML_WebPush)

Renderiza

Sem markup: mensagens push criptografadas enviadas ao navegador

Linguagens

Delphi, C++ Builder, .NET

Gere as chaves, guarde as inscrições, envie

Gere um par de chaves VAPID uma vez e guarde-o. Atribua o par e um Subject, trate os eventos de armazenamento, defina WebPush no engine e WebPushEnabled no template dele, e então chame 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>

Principais propriedades & métodos

Os membros que você usa com mais frequência.

Edições

O Web Push está disponível somente nas edições Enterprise e All-Access. A unit compila quando SGC_WEBPUSH está definido, o que o sgcVer.inc faz para essas duas edições, e ela também precisa do próprio sgcHTML, que é vendido de forma independente. A caixa de entrada de notificações e a tabela de preferências fazem parte do sgcHTML e não precisam do Web Push: só o canal de push precisa.

Chaves VAPID

GenerateVAPIDKeys é um método de classe que devolve um novo par: a metade pública é a application server key em base64url com a qual o navegador se inscreve, e a metade privada é uma chave EC em PEM. Atribua-as a VAPIDPublicKey e VAPIDPrivateKey. Subject é o contato VAPID, uma URI mailto: ou https:. A build padrão do Delphi carrega o OpenSSL 3.x para a criptografia e seleciona essa API por conta própria; a versão .NET usa criptografia gerenciada e não precisa do OpenSSL.

Eventos de armazenamento

O componente não guarda nenhuma inscrição por conta própria. OnSaveSubscription(aUserID, aEndpoint, aP256dh, aAuth) guarda uma, OnLoadSubscriptions(aUserID, aList) preenche aList com um Add(endpoint, p256dh, auth) por inscrição guardada do usuário, e OnDeleteSubscription(aUserID, aEndpoint) remove uma. Cada entrada é um TsgcHTMLWebPushSubscription.

Envio

Send(aUserID, aTitle, aBody, aURL, aIcon, aTag, aTTL, aUrgency) criptografa uma notificação por inscrição guardada do usuário (RFC 8291) e a envia por POST ao serviço de push com uma assinatura VAPID (RFC 8292). Devolve para quantas inscrições entregou, ou 0 quando Enabled é False. O remetente, TsgcHTMLWebPushClient, reutiliza TsgcHTTP_API_WebPush_Client.

Tempo de vida e urgência

TTL tem 2419200 segundos (28 dias) como padrão e Urgency é vazio, o que não envia nenhum cabeçalho de urgência. Passe aTTL ou aUrgency a Send para substituir qualquer um dos dois em uma única notificação.

Envios expirados e com falha

Quando um serviço de push responde 404 ou 410, OnSubscriptionExpired(aUserID, aEndpoint, aStatusCode) dispara para que você descarte a inscrição. Qualquer outra falha aciona OnSendError(aUserID, aEndpoint, E) e as inscrições restantes ainda são tentadas.

Endpoints de inscrição

Depois que o componente é atribuído ao engine, um POST em SubscribeEndpoint (/push/subscribe) ou UnsubscribeEndpoint (/push/unsubscribe) é respondido para você: 204 quando tratado, 400 para uma inscrição inválida, 403 quando nenhum usuário é resolvido, 413 acima de 64 KB. Chame HandleSubscribe(aJSON, aUserID) e HandleUnsubscribe você mesmo para rotear os POSTs do seu jeito.

Quem está se inscrevendo

O usuário nunca é lido do que o navegador envia. Com um TsgcHTMLAuth no engine, é o usuário do cookie de sessão, e o token CSRF é exigido. Sem ele, OnResolveUser(aCookieHeader, aHeaders, aBody, aUserID, aAllowed) responde com o seu próprio id de usuário ou recusa. Sem nenhum dos dois, a requisição recebe 403.

Na página

Com Template.WebPushEnabled ligado, o engine copia a chave pública e os endpoints para o template, serve o service worker em ServiceWorkerPath e a página traz o script de inscrição. Coloque <button data-sgc-webpush> na página para que o pedido de permissão parta de um clique; data-sgc-webpush="unsubscribe" cancela a inscrição. Os navegadores exigem https, ou localhost durante o desenvolvimento.

Página ou push

TsgcHTMLComponent_Notification escolhe entre os dois. Atribua Presence e WebPush, responda OnGetChannel com ncPush e chame AddNotification(aUserID, aId, aTitle, aMessage, ...): um usuário conectado recebe a notificação na página, um usuário que não está conectado recebe um Send, e assim ninguém é avisado duas vezes. Sem um handler de OnGetChannel, nada é enviado por push.

Continue explorando

Ajuda onlineReferência completa da API e guia de uso para este componente.
Guia do Web PushComo as peças se encaixam: inscrições, VAPID, os endpoints do engine e o componente de notificação.
Todos os Componentes sgcHTMLExplore a matriz completa de recursos com mais de 80 componentes.
Baixar Versão de Avaliação GratuitaA avaliação de 30 dias inclui os projetos de demonstração 60.HTML, entre eles o 17.FieldService, que usa Web Push.
PreçosLicenças Single, Team e Site com código-fonte completo.
Melhor custo-benefício: All-AccessTodos os produtos da eSeGeCe, com Suporte Premium incluído, a partir de €1,059/ano.
Ver preços do All-Access

Pronto para Começar?

Baixe a versão de avaliação gratuita e comece a construir UIs web em Delphi, C++ Builder e .NET.