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 キーです。これらを VAPIDPublicKey と VAPIDPrivateKey に割り当てます。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 します。配信できたサブスクリプションの数を返し、Enabled が False の場合は 0 を返します。送信側の TsgcHTMLWebPushClient は TsgcHTTP_API_WebPush_Client を再利用します。

有効期間(TTL)と緊急度

TTL の既定値は 2419200 秒(28 日)で、Urgency は空です。空の場合は緊急度ヘッダーを送信しません。aTTL または aUrgency を Send に渡すと、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 が両者を選択します。Presence と WebPush を割り当て、OnGetChannel で ncPush を返し、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 の構築を始めましょう。