WebPush

TsgcHTMLWebPush: 起動していないブラウザー、またはページを開いていないブラウザーに向けた Web Push を、Delphi、C++ Builder、.NET で提供します。Enterprise および All-Access エディションでのみ利用できます。

TsgcHTMLWebPush

Web Push は、ブラウザーを閉じている、または別のページを表示しているユーザーにも届きます。ページがサブスクライブし、アプリケーションが 3 つのイベントでサブスクリプションを保存し、Send を 1 回呼び出すと通知が配信されます。Enterprise および All-Access エディションでのみ利用できます。

コンポーネントクラス

TsgcHTMLWebPush(ユニット sgcHTML_WebPush

レンダリング内容

マークアップなし: ブラウザーに送信される暗号化されたプッシュメッセージ

言語

Delphi, C++ Builder, .NET

キーを生成し、サブスクリプションを保存し、送信する

VAPID キーペアを 1 回生成して保管します。そのキーペアと Subject を割り当て、ストレージのイベントを処理し、エンジンに WebPush を、そのテンプレートに WebPushEnabled を設定してから、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>

主なプロパティとメソッド

最もよく使うメンバーです。

エディション

Web Push は Enterprise および All-Access エディションでのみ利用できます。ユニットは SGC_WEBPUSH が定義されている場合にコンパイルされ、sgcVer.inc はこの 2 つのエディションに対してそれを設定します。また、独立して販売されている sgcHTML 自体も必要です。通知の受信トレイと設定テーブルは sgcHTML の一部で、これを必要としません。必要なのはプッシュチャネルだけです。

VAPID キー

GenerateVAPIDKeys は新しいペアを返すクラスメソッドです。公開側は、ブラウザーがサブスクライブに使う base64url 形式のアプリケーションサーバーキーで、秘密側は PEM 形式の EC キーです。これらを VAPIDPublicKeyVAPIDPrivateKey に割り当てます。Subject は VAPID の連絡先で、mailto: または https: の URI です。標準の Delphi ビルドは暗号処理に OpenSSL 3.x を読み込み、その API を自動的に選択します。.NET 版はマネージド暗号を使用するため、OpenSSL は不要です。

ストレージのイベント

コンポーネントは自前でサブスクリプションを保持しません。OnSaveSubscription(aUserID, aEndpoint, aP256dh, aAuth) は 1 件を保存し、OnLoadSubscriptions(aUserID, aList) は、aList にユーザーの保存済みサブスクリプション 1 件ごとに Add(endpoint, p256dh, auth) を 1 回ずつ実行して埋め、OnDeleteSubscription(aUserID, aEndpoint) は 1 件を削除します。各エントリは TsgcHTMLWebPushSubscription です。

送信

Send(aUserID, aTitle, aBody, aURL, aIcon, aTag, aTTL, aUrgency) は、ユーザーの保存済みサブスクリプションごとに通知を 1 件暗号化し(RFC 8291)、VAPID 署名を付けて(RFC 8292)プッシュサービスに POST します。配信できたサブスクリプションの数を返し、EnabledFalse の場合は 0 を返します。送信側の TsgcHTMLWebPushClientTsgcHTTP_API_WebPush_Client を再利用します。

有効期間(TTL)と緊急度

TTL の既定値は 2419200 秒(28 日)で、Urgency は空です。空の場合は緊急度ヘッダーを送信しません。aTTL または aUrgencySend に渡すと、1 件の通知に限っていずれかを上書きできます。

期限切れと失敗した送信

プッシュサービスが 404 または 410 を返すと、OnSubscriptionExpired(aUserID, aEndpoint, aStatusCode) が発生するので、サブスクリプションを削除できます。それ以外の失敗は OnSendError(aUserID, aEndpoint, E) を発生させ、残りのサブスクリプションへの送信は続行されます。

サブスクライブのエンドポイント

コンポーネントをエンジンに割り当てると、SubscribeEndpoint/push/subscribe)または UnsubscribeEndpoint/push/unsubscribe)への POST には自動的に応答します。処理できた場合は 204、サブスクリプションが無効な場合は 400、ユーザーを特定できない場合は 403、64 KB を超える場合は 413 です。POST を独自の方法で振り分けるには、HandleSubscribe(aJSON, aUserID)HandleUnsubscribe を自分で呼び出します。

サブスクライブしているのは誰か

ユーザーがブラウザーからポストされた内容から読み取られることはありません。エンジンに TsgcHTMLAuth がある場合は、セッション Cookie のユーザーが使われ、CSRF トークンが必須です。ない場合は、OnResolveUser(aCookieHeader, aHeaders, aBody, aUserID, aAllowed) が独自のユーザー ID を返すか、拒否します。どちらもない場合、リクエストには 403 が返ります。

ページ内

Template.WebPushEnabled をオンにすると、エンジンは公開キーとエンドポイントをテンプレートにコピーし、ServiceWorkerPath でサービスワーカーを提供し、ページにはサブスクライブ用のスクリプトが含まれます。許可のプロンプトがクリックから実行されるように、ページに <button data-sgc-webpush> を置きます。data-sgc-webpush="unsubscribe" を指定すると解除になります。ブラウザーには https が必要です(開発中は localhost でも動作します)。

ページかプッシュか

TsgcHTMLComponent_Notification が両者を選択します。PresenceWebPush を割り当て、OnGetChannelncPush を返し、AddNotification(aUserID, aId, aTitle, aMessage, ...) を呼び出します。接続中のユーザーにはページ内で通知が届き、接続していないユーザーには Send が 1 回実行されるので、同じ通知が二重に届くことはありません。OnGetChannel ハンドラーがない場合、プッシュは一切送信されません。

さらに詳しく

オンラインヘルプこのコンポーネントの完全な API リファレンスと使用ガイドです。
Web Push ガイド各要素の連携: サブスクリプション、VAPID、エンジンのエンドポイント、通知コンポーネント。
すべての sgcHTML コンポーネント80 以上のコンポーネントの全機能マトリックスを閲覧できます。
無料体験版のダウンロード30 日間の体験版には 60.HTML デモプロジェクトが付属し、Web Push を使用する 17.FieldService も含まれます。
価格完全なソースコード付きの Single、Team、Site ライセンス。
最もお得な選択: All-AccesseSeGeCe の全製品にプレミアムサポートが付いて、年間 €1,059 からご利用いただけます。
All-Access の価格を見る

始める準備はできましたか?

無料体験版をダウンロードして、Delphi、C++ Builder、.NET で Web UI の構築を始めましょう。