Pustaka Web Push untuk PHP
WebPush dapat digunakan untuk mengirim pesan push ke titik akhir seperti yang dijelaskan dalam protokol Web Push.
Pesan push ini kemudian diterima oleh browser, yang kemudian dapat membuat notifikasi menggunakan pekerja layanan dan API Notifikasi.
PHP 8.1+ dan ekstensi berikut:
Tidak ada dukungan dan pemeliharaan untuk versi PHP lama, namun Anda bebas menggunakan versi kompatibel berikut:
v1.x
v2.x
v3.x-v5.x
v6.x
v7.x
v8.x
README ini hanya kompatibel dengan versi terbaru. Setiap versi perpustakaan memiliki tag git tempat README terkait dapat dibaca.
Gunakan komposer untuk mengunduh dan menginstal perpustakaan dan dependensinya.
composer require minishlink/web-push
Contoh lengkap frontend html+JS dan backend php menggunakan web-push-php
dapat dilihat di sini: Minishlink/web-push-php-example
<?php
use Minishlink WebPush WebPush ;
use Minishlink WebPush Subscription ;
// store the client - side `PushSubscription` object ( calling ` . toJSON` on it) as - is and then create a WebPush Subscription from it
$ subscription = Subscription:: create ( json_decode ( $ clientSidePushSubscriptionJSON , true ));
// array of notifications
$ notifications = [
[
' subscription ' => $ subscription ,
' payload ' => ' {"message":"Hello World!"} ' ,
], [
// current PushSubscription format ( browsers might change this in the future)
' subscription ' => Subscription:: create ([
" endpoint " => " https://example.com/other/endpoint/of/another/vendor/abcdef... " ,
" keys " => [
' p256dh ' => ' (stringOf88Chars) ' ,
' auth ' => ' (stringOf24Chars) '
],
]),
' payload ' => ' {"message":"Hello World!"} ' ,
], [
// old Firefox PushSubscription format
' subscription ' => Subscription:: create ([
' endpoint ' => ' https://updates.push.services.mozilla.com/push/abc... ' , // Firefox 43 + ,
' publicKey ' => ' BPcMbnWQL5GOYX/5LKZXT6sLmHiMsJSiEvIFvfcDvX7IZ9qqtq68onpTPEYmyxSQNiH7UD/98AUcQ12kBoxz/0s= ' , // base 64 encoded , should be 88 chars
' authToken ' => ' CxVX6QsVToEGEcjfYPqXQw== ' , // base 64 encoded , should be 24 chars
]),
' payload ' => ' hello ! ' ,
], [
// old Chrome PushSubscription format
' subscription ' => Subscription:: create ([
' endpoint ' => ' https://fcm.googleapis.com/fcm/send/abcdef... ' ,
]),
' payload ' => null ,
], [
// old PushSubscription format
' subscription ' => Subscription:: create ([
' endpoint ' => ' https://example.com/other/endpoint/of/another/vendor/abcdef... ' ,
' publicKey ' => ' (stringOf88Chars) ' ,
' authToken ' => ' (stringOf24Chars) ' ,
' contentEncoding ' => ' aesgcm ' , // one of PushManager . supportedContentEncodings
]),
' payload ' => ' {"message":"test"} ' ,
]
];
$ webPush = new WebPush ();
// send multiple notifications with payload
foreach ( $ notifications as $ notification ) {
$ webPush -> queueNotification (
$ notification [ ' subscription ' ],
$ notification [ ' payload ' ] // optional ( defaults null)
);
}
/**
* Check sent results
* @ var MessageSentReport $ report
* /
foreach ( $ webPush -> flush () as $ report ) {
$ endpoint = $ report -> getRequest ()-> getUri ()-> __toString ();
if ( $ report -> isSuccess ()) {
echo " [v] Message sent successfully for subscription { $ endpoint } . " ;
} else {
echo " [x] Message failed to sent for subscription { $ endpoint } : { $ report -> getReason ()}" ;
}
}
/**
* send one notification and flush directly
* @ var MessageSentReport $ report
* /
$ report = $ webPush -> sendOneNotification (
$ notifications [ 0 ][ ' subscription ' ],
$ notifications [ 0 ][ ' payload ' ], // optional ( defaults null)
);
Browser perlu memverifikasi identitas Anda. Standar yang disebut VAPID dapat mengautentikasi Anda untuk semua browser. Anda harus membuat dan memberikan kunci publik dan pribadi untuk server Anda. Kunci-kunci ini harus disimpan dengan aman dan tidak boleh diubah.
Anda dapat menentukan detail autentikasi Anda saat membuat instance WebPush. Kunci dapat diteruskan secara langsung (disarankan), atau Anda dapat memuat file PEM atau kontennya:
<?php
use Minishlink WebPush WebPush ;
$ endpoint = ' https://fcm.googleapis.com/fcm/send/abcdef... ' ; // Chrome
$ auth = [
' VAPID ' => [
' subject ' => ' mailto:[email protected] ' , // can be a mailto : or your website address
' publicKey ' => ' ~88 chars ' , // (recommended) uncompressed public key P - 256 encoded in Base64 - URL
' privateKey ' => ' ~44 chars ' , // (recommended) in fact the secret multiplier of the private key encoded in Base64 - URL
' pemFile ' => ' path/to/pem ' , // if you have a PEM file and can link to it on your filesystem
' pem ' => ' pemFileContent ' , // if you have a PEM file and want to hardcode its content
],
];
$ webPush = new WebPush ( $ auth );
$ webPush -> queueNotification (...);
Untuk menghasilkan kunci publik dan rahasia yang tidak terkompresi, yang dikodekan dalam Base64, masukkan yang berikut ini di bash Linux Anda:
$ openssl ecparam -genkey -name prime256v1 -out private_key.pem
$ openssl ec -in private_key.pem -pubout -outform DER | tail -c 65 | base64 | tr -d ' = ' | tr ' /+ ' ' _- ' >> public_key.txt
$ openssl ec -in private_key.pem -outform DER | tail -c +8 | head -c 32 | base64 | tr -d ' = ' | tr ' /+ ' ' _- ' >> private_key.txt
Jika Anda tidak dapat mengakses bash Linux, Anda dapat mencetak output dari fungsi createVapidKeys
:
var_dump ( VAPID :: createVapidKeys ()); // store the keys afterwards
Di sisi klien, jangan lupa berlangganan dengan kunci publik VAPID sebagai applicationServerKey
: ( sumber urlBase64ToUint8Array
di sini)
serviceWorkerRegistration . pushManager . subscribe ( {
userVisibleOnly : true ,
applicationServerKey : urlBase64ToUint8Array ( vapidPublicKey )
} )
Header VAPID menggunakan JSON Web Token (JWT) untuk memverifikasi identitas Anda. Payload token tersebut mencakup protokol dan nama host titik akhir yang termasuk dalam langganan dan stempel waktu kedaluwarsa (biasanya antara 12-24 jam), dan ditandatangani menggunakan kunci publik dan pribadi Anda. Mengingat hal tersebut, dua notifikasi yang dikirim ke layanan push yang sama akan menggunakan token yang sama, sehingga Anda dapat menggunakannya kembali untuk sesi flush yang sama guna meningkatkan kinerja menggunakan:
$ webPush -> setReuseVAPIDHeaders ( true );
Setiap notifikasi dapat memiliki Time To Live, urgensi, dan topik tertentu. Standar WebPush menyatakan bahwa urgency
adalah opsional tetapi beberapa pengguna melaporkan bahwa Safari memunculkan kesalahan ketika tidak ditentukan. Hal ini mungkin dapat diperbaiki di masa mendatang. Anda dapat mengubah opsi default dengan setDefaultOptions()
atau di konstruktor:
<?php
use Minishlink WebPush WebPush ;
$ defaultOptions = [
' TTL ' => 300 , // defaults to 4 weeks
' urgency ' => ' normal ' , // protocol defaults to "normal" . ( very - low , low , normal , or high)
' topic ' => ' newEvent ' , // not defined by default . Max . 32 characters from the URL or filename - safe Base64 characters sets
' batchSize ' => 200 , // defaults to 1000
];
// for every notification
$ webPush = new WebPush ([], $ defaultOptions );
$ webPush -> setDefaultOptions ( $ defaultOptions );
// or for one notification
$ webPush -> sendOneNotification ( $ subscription , $ payload , [ ' TTL ' => 5000 ]);
Time To Live (TTL, dalam detik) adalah berapa lama pesan push disimpan oleh layanan push (misalnya Mozilla) jika browser pengguna belum dapat diakses (misalnya tidak terhubung). Anda mungkin ingin menggunakan waktu yang sangat lama untuk pemberitahuan penting. TTL defaultnya adalah 4 minggu. Namun, jika Anda mengirim beberapa notifikasi yang tidak penting, setel TTL ke 0: notifikasi push hanya akan dikirimkan jika pengguna sedang terhubung. Untuk kasus lain, Anda harus menggunakan minimal satu hari jika pengguna Anda memiliki beberapa zona waktu, dan jika tidak, beberapa jam saja sudah cukup.
Urgensi dapat berupa “sangat-rendah”, “rendah”, “normal”, atau “tinggi”. Jika vendor browser telah menerapkan fitur ini, maka akan menghemat masa pakai baterai pada perangkat seluler (lih. protokol).
String ini akan membuat vendor hanya menampilkan pemberitahuan terakhir topik ini kepada pengguna (lih. protokol).
Jika Anda mengirim puluhan ribu notifikasi sekaligus, Anda mungkin mengalami kelebihan memori karena cara titik akhir dipanggil di Guzzle. Untuk memperbaikinya, WebPush mengirimkan pemberitahuan secara berkelompok. Ukuran defaultnya adalah 1000. Tergantung pada konfigurasi server Anda (memori), Anda mungkin ingin mengurangi jumlah ini. Lakukan ini saat membuat instance WebPush atau memanggil setDefaultOptions
. Atau, jika Anda ingin menyesuaikan ini untuk flush tertentu, berikan sebagai parameter : $webPush->flush($batchSize)
.
Anda dapat melihat apa yang dikirim kembali oleh server vendor browser jika terjadi kesalahan (mendorong masa berlaku langganan, parameter salah...).
sendOneNotification()
mengembalikan MessageSentReport
flush()
mengembalikan Generator
dengan objek MessageSentReport
. Untuk mengulang hasilnya, teruskan saja ke foreach
. Anda juga dapat menggunakan iterator_to_array
untuk memeriksa konten saat melakukan debug. <?php
/** @var MinishlinkWebPush MessageSentReport $ report * /
foreach ( $ webPush -> flush () as $ report ) {
$ endpoint = $ report -> getEndpoint ();
if ( $ report -> isSuccess ()) {
echo " [v] Message sent successfully for subscription { $ endpoint } . " ;
} else {
echo " [x] Message failed to sent for subscription { $ endpoint } : { $ report -> getReason ()}" ;
// also available ( to get more info )
/** @var Psr Http Message RequestInterface $ requestToPushService * /
$ requestToPushService = $ report -> getRequest ();
/** @var Psr Http Message ResponseInterface $ responseOfPushService * /
$ responseOfPushService = $ report -> getResponse ();
/** @var string $ failReason */
$ failReason = $ report -> getReason ();
/** @var bool $ isTheEndpointWrongOrExpired */
$ isTheEndpointWrongOrExpired = $ report -> isSubscriptionExpired ();
}
}
HARAP DICATAT: Anda hanya dapat melakukan iterasi satu kali pada objek Generator
.
Kesalahan Firefox tercantum dalam dokumentasi autopush.
Payload dienkripsi oleh perpustakaan. Panjang muatan maksimum secara teori adalah 4078 byte (atau karakter ASCII). Untuk alasan kompatibilitas (diarsipkan), panjang payload Anda harus kurang dari 3052 byte.
Perpustakaan mengisi payload secara default. Ini lebih aman tetapi menurunkan kinerja server dan perangkat pengguna Anda.
Saat Anda mengenkripsi string dengan panjang tertentu, string yang dihasilkan akan selalu memiliki panjang yang sama, tidak peduli berapa kali Anda mengenkripsi string awal. Hal ini dapat membuat penyerang menebak isi muatannya. Untuk menghindari hal ini, perpustakaan ini menambahkan beberapa bantalan nol ke muatan awal, sehingga semua masukan dari proses enkripsi akan memiliki panjang yang sama. Dengan cara ini, semua output dari proses enkripsi juga akan memiliki panjang yang sama dan penyerang tidak akan bisa menebak konten payload Anda.
Mengenkripsi lebih banyak byte membutuhkan lebih banyak waktu proses di server Anda, dan juga memperlambat perangkat pengguna dengan dekripsi. Apalagi pengiriman dan penerimaan paket akan memakan waktu lebih lama. Ini juga tidak terlalu bersahabat dengan pengguna yang memiliki paket data terbatas.
Anda dapat menyesuaikan padding otomatis agar lebih sesuai dengan kebutuhan Anda.
Berikut beberapa ide pengaturan:
Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH
(2820 bytes) untuk tujuan kompatibilitas dengan Firefox untuk Android (Lihat #108)Encryption::MAX_PAYLOAD_LENGTH
(4078 bytes) untuk keamanan maksimumfalse
untuk performa maksimalX
byte, setel ke X
untuk keseimbangan terbaik antara keamanan dan kinerja. <?php
use Minishlink WebPush WebPush ;
$ webPush = new WebPush ();
$ webPush -> setAutomaticPadding ( false ); // disable automatic padding
$ webPush -> setAutomaticPadding ( 512 ); // enable automatic padding to 512 bytes ( you should make sure that your payload is less than 512 bytes , or else an attacker could guess the content )
$ webPush -> setAutomaticPadding ( true ); // enable automatic padding to default maximum compatibility length
WebPush menggunakan Guzzle. Ini akan menggunakan klien paling tepat yang ditemukannya, dan sebagian besar adalah MultiCurl
, yang memungkinkan pengiriman beberapa notifikasi secara paralel.
Anda dapat menyesuaikan opsi permintaan default dan batas waktu saat membuat instance WebPush:
<?php
use Minishlink WebPush WebPush ;
$ timeout = 20 ; // seconds
$ clientOptions = [
GuzzleHttp RequestOptions:: ALLOW_REDIRECTS => false ,
]; // see GuzzleHttp RequestOptions
$ webPush = new WebPush ([], [], $ timeout , $ clientOptions );
Berikut ini tersedia:
Jangan ragu untuk menambahkan milik Anda sendiri!
Payload dienkripsi sesuai dengan standar Enkripsi Pesan untuk Web Push, menggunakan kunci publik pengguna dan rahasia otentikasi yang bisa Anda dapatkan dengan mengikuti spesifikasi Web Push API.
Secara internal, WebPush menggunakan kerangka WebToken dan OpenSSL untuk menangani pembuatan dan enkripsi kunci enkripsi.
Berikut beberapa idenya:
defaultOptions
atau sebagai parameter ke flush()
)flushPooled()
alih-alih flush()
. Yang pertama menggunakan permintaan bersamaan, mempercepat proses dan sering kali menggandakan kecepatan permintaan.Instalasi Anda tidak memiliki beberapa sertifikat.
php.ini
Anda : setelah [curl]
, ketik curl.cainfo = /path/to/cacert.pem
.Anda juga dapat memaksa menggunakan klien tanpa verifikasi rekan.
Pastikan untuk memerlukan autoloader Komposer.
require __DIR__ . ' /path/to/vendor/autoload.php ' ;
Pastikan untuk memiliki field database yang cukup besar untuk panjang data yang Anda simpan (#233). Untuk titik akhir, pengguna telah melaporkan bahwa panjang URL tidak melebihi 500 karakter, namun hal ini dapat berkembang sehingga Anda dapat menyetelnya ke batas 2048 karakter di sebagian besar browser.
Lihat edisi #58.
Layanan ini sudah tidak ada lagi. Layanan ini telah digantikan oleh Firebase Cloud Messaging (FCM) Google pada tanggal 29 Mei 2019.
Library ini tidak mendukung Firebase Cloud Messaging (FCM). Langganan Chrome lama (sebelum 2018 dan VAPID) menggunakan protokol HTTP Lama dari Firebase Cloud Messaging (FCM) yang tidak digunakan lagi sejak tahun 2023 dan akan berhenti berfungsi pada bulan Juni 2024. Dukungan untuk langganan lama ini akan dihapus.
Harap jangan bingung karena protokol HTTP lama dan Web Push dengan VAPID menggunakan URL titik akhir yang sama:
https://fcm.googleapis.com/fcm/send
Web Push dengan VAPID akan tetap tersedia di URL ini. Saat ini tidak diperlukan tindakan lebih lanjut.
Vendor browser tidak mengizinkan pengiriman data menggunakan Push API tanpa membuat notifikasi. Gunakan beberapa API alternatif seperti WebSocket/WebTransport atau Sinkronisasi Latar Belakang.
WebPush adalah untuk aplikasi web. Anda memerlukan sesuatu seperti RMSPushNotificationsBundle (Symfony).
Pustaka ini terinspirasi oleh pustaka web-push-libs/web-push Node.js.
server.js
: sebaiknya diganti dengan kode server PHP Anda dengan perpustakaan ini)MIT