WebPush
TsgcHTMLWebPush: 起動していないブラウザー、またはページを開いていないブラウザーに向けた Web Push を、Delphi、C++ Builder、.NET で提供します。Enterprise および All-Access エディションでのみ利用できます。
TsgcHTMLWebPush: 起動していないブラウザー、またはページを開いていないブラウザーに向けた Web Push を、Delphi、C++ Builder、.NET で提供します。Enterprise および All-Access エディションでのみ利用できます。
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 の一部で、これを必要としません。必要なのはプッシュチャネルだけです。
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 の既定値は 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 ライセンス。 | 開く |