私はGoogleで作業していますChromeプッシュ通知と、Googleにペイロードを送信しようとしていますchromeワーカーですが、このペイロードを受信します。
データベースに通知を作成して保存するAPIがあり、https://Android.googleapis.com/gcm/send
を介して値を送信し、worker.jsで受信する必要があります
これは私のworker.jsです
self.addEventListener('Push', function(event) {
var title = 'Yay a message.';
var body = 'We have received a Push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-Push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
そして、これは私がGCMを呼んでいる方法です
curl --header "Authorization: key=AIzaSyDQjYDxeS9MM0LcJm3oR6B7MU7Ad2x2Vqc" --header "Content-Type: application/json" https://Android.googleapis.com/gcm/send -d "{ \"data\":{\"foo\":\"bar\"}, \"registration_ids\":[\"APA91bGqJpCmyCnSHLjY6STaBQEumz3eFY9r-2CHTtbsUMzBttq0crU3nEXzzU9TxNpsYeFmjA27urSaszKtA0WWC3yez1hhneLjbwJqlRdc_Yj1EiqLHluVwHB6V4FNdXdKb_gc_-7rbkYkypI3MtHpEaJbWsj6M5Pgs4nKqQ2R-WNho82mnRU\"]}"
event.data
を取得しようとしましたが、これは未定義です。
誰にもアイデアや提案はありますか?
そのデータを取得するには、「event.data.text()」をJSONオブジェクトに解析する必要があります。あなたがこれを動作させようとしたので、何かが更新されたと思いますが、今は動作します。不運!
ただし、解決策を自分で検索するときにこの投稿にたどり着いたので、他の人はおそらく実用的な答えを望んでいます。ここにあります:
// Push message event handler
self.addEventListener('Push', function(event) {
// If true, the event holds data
if(event.data){
// Need to parse to JSON format
// - Consider event.data.text() the "stringify()"
// version of the data
var payload = JSON.parse(event.data.text());
// For those of you who love logging
console.log(payload);
var title = payload.data.title;
var body = payload.data.body;
var icon = './assets/icons/icon.ico'
var tag = 'notification-tag';
// Wait until payload is fetched
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag,
data: {} // Keeping this here in case I need it later
})
);
} else {
console.log("Event does not have data...");
}
}); // End Push listener
// Notification Click event
self.addEventListener('notificationclick', function(event) {
console.log("Notification Clicked");
}); // End click listener
個人的には、データがファンキーな場合に備えて「一般的な」通知を作成し、try/catchも使用します。同じことをお勧めします。
残念ながら 意図した動作 のようです:
ChromeのPush APIの現在の実装のマイナス面は、Pushメッセージでペイロードを送信できないことです。いいえ、何もありません。これは、将来の実装では、ペイロードは、プッシュメッセージングエンドポイントに送信される前にサーバーで暗号化する必要がありますこの方法では、プッシュプロバイダーがどのようなものであっても、エンドポイントはプッシュペイロードのコンテンツを簡単に表示できません。 HTTPS証明書の検証が不十分で、サーバーとプッシュプロバイダー間の中間者攻撃が発生しますが、この暗号化はまだサポートされていないため、その間に必要な情報を取得するためにフェッチリクエストを実行する必要があります通知を入力します。
上記のように、回避策は、プッシュを受信した後にバックエンドに連絡して、サードパーティのサーバーに保存されたデータを取得することです。
@gauchofunkyの答えは正しいです。 Chromium dev slackチャンネルと@gauchofunkyの人々からのいくつかのガイダンスで、私は何かをつなぎ合わせることができました。現在の制限を回避する方法は次のとおりです。うまくいけば、私の答えはすぐに時代遅れになります!
最初に、バックエンドで通知を永続化する方法を理解します。 Node/ExpressとMongoDBをMongooseで使用していますが、スキーマは次のようになります。
var NotificationSchema = new Schema({
_user: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
subscriptionId: String,
title: String,
body: String,
sent: { type: Boolean, default: false }
});
アイコンを変更する場合は、必ずアイコンを追加してください。私は毎回同じアイコンを使用しているので、私のものはサービスワーカーにハードコードされています。
正しいREST Webサービスを考えると、GETは簡単な選択のように思えましたが、通知を取得するための呼び出しは副作用を引き起こすため、GETが出ました。結局、POST
から/api/notifications
の本文は{subscriptionId: <SUBSCRIPTION_ID>}
。メソッド内では、基本的にデキューを実行します。
var subscriptionId = req.body.subscriptionId;
Notification
.findOne({_user: req.user, subscriptionId: subscriptionId, sent: false})
.exec(function(err, notification) {
if(err) { return handleError(res, err); }
notification.sent = true;
notification.save(function(err) {
if(err) { return handleError(res, err); }
return res.status(201).json(notification);
});
});
Service Workerでは、fetch
を作成する前にサブスクリプションを取得する必要があります。
self.addEventListener('Push', function(event) {
event.waitUntil(
self.registration.pushManager.getSubscription().then(function(subscription) {
fetch('/api/notifications/', {
method: 'post',
headers: {
'Authorization': 'Bearer ' + self.token,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
})
.then(function(response) { return response.json(); })
.then(function(data) {
self.registration.showNotification(data.title, {
body: data.body,
icon: 'favicon-196x196.png'
});
})
.catch(function(err) {
console.log('err');
console.log(err);
});
})
);
});
また、サブスクリプションオブジェクトがChrome 43からChrome 45. In Chrome 45 the subscriptionId
プロパティは削除されました。注意が必要なのは、このコードがChrome 43。
バックエンドに認証済みの呼び出しを行いたいので、AngularアプリケーションからサービスワーカーにJWTを取得する方法を理解する必要がありました。最終的にはpostMessage
を使用しました。サービスワーカーを登録した後の処理:
navigator.serviceWorker.register('/service-worker.js', {scope:'./'}).then(function(reg) {
var messenger = reg.installing || navigator.serviceWorker.controller;
messenger.postMessage({token: $localStorage.token});
}).catch(function(err) {
console.log('err');
console.log(err);
});
サービスワーカーでメッセージをリッスンします。
self.onmessage.addEventListener('message', function(event) {
self.token = event.data.token;
});
奇妙なことに、リスナーはChrome 43で動作しますが、Chrome 45では動作しません。Chrome 45は次のようなハンドラで動作します。
self.addEventListener('message', function(event) {
self.token = event.data.token;
});
現在、プッシュ通知は何か役に立つものを得るためにかなりの作業を必要とします-私は本当にペイロードを楽しみにしています!
実際、ペイロードはChrome 50(リリース日-2016年4月19日)に実装する必要があります。InChrome 50(およびデスクトップ上のFirefoxの現在のバージョン)クライアントが追加のリクエストを行わないように、Pushとともに任意のデータを送信できます。すべてのペイロードデータは暗号化する必要があります。
開発者からの暗号化の詳細は次のとおりです。 https://developers.google.com/web/updates/2016/03/web-Push-encryption?hl=en
私はこの問題に出くわしました。 firefoxおよびchrome(バージョン50+)の新しいバージョンは、ペイロード転送をサポートしています。
dev docs here これがどのように機能するかの実装の詳細。注意すべき重要なことは、Google GCMまたはクライアント/ホーム(おそらくどちらか)が暗号化されていない場合、実際にペイロードを完全に無視することです。
This Webサイトには、プッシュを実行する方法とサービスワーカーを介して取得する方法の両方のクライアント/サーバー実装があります。例が使用するプッシュライブラリは、単に 通常のREST呼び出し)のラッパー
service worker実装例:
self.addEventListener('Push', function(event) {
var payload = event.data ? event.data.text() : 'no payload';
event.waitUntil(
self.registration.showNotification('ServiceWorker Cookbook', {
body: payload,
})
);
});
Server実装例:
var webPush = require('web-Push');
webPush.setGCMAPIKey(process.env.GCM_API_KEY);
module.exports = function(app, route) {
app.post(route + 'register', function(req, res) {
res.sendStatus(201);
});
app.post(route + 'sendNotification', function(req, res) {
setTimeout(function() {
webPush.sendNotification(req.body.endpoint, {
TTL: req.body.ttl,
payload: req.body.payload,
userPublicKey: req.body.key,
userAuth: req.body.authSecret,
}).then(function() {
res.sendStatus(201);
});
}, req.body.delay * 1000);
});
};
クライアント側javascript必須フィールドを印刷する実装例。
navigator.serviceWorker.register('serviceWorker.js')
.then(function(registration) {
return registration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription;
}
return registration.pushManager.subscribe({
userVisibleOnly: true
});
});
}).then(function(subscription) {
var rawKey = subscription.getKey ? subscription.getKey('p256dh') : '';
key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : '';
var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : '';
authSecret = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : '';
endpoint = subscription.endpoint;
console.log("Endpoint: " + endpoint);
console.log("Key: " + key);
console.log("AuthSecret: " + authSecret);
});
これを実現するには、次の手順に従います。
ブラウザ内:
subscription
オブジェクトを取得して保存する必要があるため、サーバーからアクセスできます。 詳細について
navigator.serviceWorker.ready.then(serviceWorkerRegistration => {
serviceWorkerRegistration.pushManager.subscribe({userVisibleOnly: true})
.then(subscription => {
//save subscription.toJSON() object to your server
})});
サーバー内:
install web-push npm package
そして、次のようなWebプッシュを送信します。
const webpush = require('web-Push');
setImmediate(async () => {
const params = {
payload: {title: 'Hey', body: 'Hello World'}
};
//this is the subscription object you should get in the browser. This is a demo of how it should look like
const subscription = {"endpoint":"https://Android.googleapis.com/gcm/send/deC24xZL8z4:APA91bE9ZWs2KvLdo71NGYvBHGX6ZO4FFIQCppMsZhiTXtM1S2SlAqoOPNxzLlPye4ieL2ulzzSvPue-dGFBszDcFbSkfb_VhleiJgXRA8UwgLn5Z20_77WroZ1LofWQ22g6bpIGmg2JwYAqjeca_gzrZi3XUpcWHfw","expirationTime":null,"keys":{"p256dh":"BG55fZ3zZq7Cd20vVouPXeVic9-3pa7RhcR5g3kRb13MyJyghTY86IO_IToVKdBmk_2kA9znmbqvd0-o8U1FfA3M","auth":"1gNTE1wddcuF3FUPryGTZOA"}};
if (subscription.keys) {
params.userPublicKey = subscription.keys.p256dh;
params.userAuth = subscription.keys.auth;
}
// this key you should take from firebase console for example
// settings -> cloud messaging -> Server key
webpush.setGCMAPIKey('AAAASwYmslc:APfA91bGy3tdKvuq90eOvz4AoUm6uPtbqZktZ9dAnElrlH4gglUiuvereTJJWxz8_dANEQciX9legijnJrxvlapI84bno4icD2D0cdVX3_XBOuW3aWrpoqsoxLDTdth86CjkDD4JhqRzxV7RrDXQZd_sZAOpC6f32nbA');
try {
const r = await webpush.sendNotification(subscription, JSON.stringify(params));
console.log(r);
}
catch (e) {
console.error(e);
}
});