ไลบรารี Web Push สำหรับ PHP
สามารถใช้ WebPush เพื่อส่งข้อความพุชไปยังจุดสิ้นสุดตามที่อธิบายไว้ในโปรโตคอล Web Push
จากนั้นเบราว์เซอร์จะได้รับข้อความพุชนี้ ซึ่งสามารถสร้างการแจ้งเตือนโดยใช้พนักงานบริการและ API การแจ้งเตือนได้
PHP 8.1+ และส่วนขยายต่อไปนี้:
ไม่มีการสนับสนุนและการบำรุงรักษาสำหรับ PHP เวอร์ชันเก่า อย่างไรก็ตาม คุณสามารถใช้เวอร์ชันที่เข้ากันได้ดังต่อไปนี้:
v1.x
v2.x
v3.x-v5.x
v6.x
v7.x
v8.x
README นี้เข้ากันได้กับเวอร์ชันล่าสุดเท่านั้น ไลบรารีแต่ละเวอร์ชันมีแท็ก git ซึ่งสามารถอ่าน README ที่เกี่ยวข้องได้
ใช้ผู้แต่งเพื่อดาวน์โหลดและติดตั้งไลบรารีและการขึ้นต่อกัน
composer require minishlink/web-push
ตัวอย่างที่สมบูรณ์ของส่วนหน้า html+JS และแบ็กเอนด์ php โดยใช้ web-push-php
สามารถพบได้ที่นี่: 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)
);
เบราว์เซอร์จำเป็นต้องยืนยันตัวตนของคุณ มาตรฐานที่เรียกว่า VAPID สามารถตรวจสอบสิทธิ์คุณสำหรับเบราว์เซอร์ทั้งหมด คุณจะต้องสร้างและระบุรหัสสาธารณะและรหัสส่วนตัวสำหรับเซิร์ฟเวอร์ของคุณ คีย์เหล่านี้จะต้องเก็บไว้อย่างปลอดภัยและไม่ควรเปลี่ยนแปลง
คุณสามารถระบุรายละเอียดการรับรองความถูกต้องของคุณเมื่อสร้างอินสแตนซ์ WebPush คุณสามารถส่งคีย์ได้โดยตรง (แนะนำ) หรือคุณสามารถโหลดไฟล์ PEM หรือเนื้อหาได้:
<?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 (...);
ในการสร้างคีย์สาธารณะและคีย์ลับที่ไม่มีการบีบอัด ซึ่งเข้ารหัสใน Base64 ให้ป้อนข้อมูลต่อไปนี้ใน Linux bash ของคุณ:
$ 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
หากคุณไม่สามารถเข้าถึง Linux bash ได้ คุณสามารถพิมพ์ผลลัพธ์ของฟังก์ชัน createVapidKeys
ได้:
var_dump ( VAPID :: createVapidKeys ()); // store the keys afterwards
ที่ฝั่งไคลเอ็นต์ อย่าลืมสมัครสมาชิกด้วยคีย์สาธารณะ VAPID เป็น applicationServerKey
: ( ที่มา urlBase64ToUint8Array
ที่นี่)
serviceWorkerRegistration . pushManager . subscribe ( {
userVisibleOnly : true ,
applicationServerKey : urlBase64ToUint8Array ( vapidPublicKey )
} )
ส่วนหัว VAPID ใช้ JSON Web Token (JWT) เพื่อยืนยันตัวตนของคุณ เพย์โหลดโทเค็นนั้นรวมถึงโปรโตคอลและชื่อโฮสต์ของอุปกรณ์ปลายทางที่รวมอยู่ในการสมัครใช้งานและการประทับเวลาการหมดอายุ (โดยปกติจะอยู่ระหว่าง 12-24 ชั่วโมง) และลงนามโดยใช้คีย์สาธารณะและคีย์ส่วนตัวของคุณ เนื่องจากการแจ้งเตือนสองครั้งที่ส่งไปยังบริการพุชเดียวกันจะใช้โทเค็นเดียวกัน ดังนั้นคุณจึงสามารถนำมาใช้ใหม่สำหรับเซสชันฟลัชเดียวกันเพื่อเพิ่มประสิทธิภาพโดยใช้:
$ webPush -> setReuseVAPIDHeaders ( true );
การแจ้งเตือนแต่ละรายการสามารถมี Time To Live ความเร่งด่วน และหัวข้อที่เฉพาะเจาะจงได้ มาตรฐาน WebPush ระบุว่าความ urgency
เป็นทางเลือก แต่ผู้ใช้บางรายรายงานว่า Safari ส่งข้อผิดพลาดเมื่อไม่ได้ระบุ สิ่งนี้อาจจะได้รับการแก้ไขในอนาคต คุณสามารถเปลี่ยนตัวเลือกเริ่มต้นด้วย setDefaultOptions()
หรือในตัวสร้าง:
<?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 เป็นวินาที) คือระยะเวลาที่ข้อความพุชยังคงอยู่โดยบริการพุช (เช่น Mozilla) ในกรณีที่ยังไม่สามารถเข้าถึงเบราว์เซอร์ของผู้ใช้ได้ (เช่น ไม่ได้เชื่อมต่อ) คุณอาจต้องการใช้เวลานานมากสำหรับการแจ้งเตือนที่สำคัญ TTL เริ่มต้นคือ 4 สัปดาห์ อย่างไรก็ตาม หากคุณส่งการแจ้งเตือนที่ไม่จำเป็นหลายรายการ ให้ตั้งค่า TTL เป็น 0: การแจ้งเตือนแบบพุชจะถูกส่งต่อเมื่อผู้ใช้เชื่อมต่ออยู่ในปัจจุบันเท่านั้น สำหรับกรณีอื่นๆ คุณควรใช้เวลาอย่างน้อยหนึ่งวันหากผู้ใช้ของคุณมีหลายเขตเวลา และหากไม่มีเวลาหลายชั่วโมงก็เพียงพอแล้ว
ความเร่งด่วนอาจเป็นได้ทั้ง "ต่ำมาก" "ต่ำ" "ปกติ" หรือ "สูง" หากผู้จำหน่ายเบราว์เซอร์ได้ใช้คุณลักษณะนี้ จะช่วยประหยัดอายุการใช้งานแบตเตอรี่บนอุปกรณ์เคลื่อนที่ (โปรโตคอลที่อ้างอิง)
สตริงนี้จะทำให้ผู้ขายแสดงต่อผู้ใช้เฉพาะการแจ้งเตือนล่าสุดของหัวข้อนี้ (โปรโตคอลที่อ้างอิง)
หากคุณส่งการแจ้งเตือนครั้งละหลายหมื่นรายการ คุณอาจได้รับหน่วยความจำล้นเนื่องจากวิธีเรียกปลายทางใน Guzzle เพื่อแก้ไขปัญหานี้ WebPush จะส่งการแจ้งเตือนเป็นชุด ขนาดเริ่มต้นคือ 1,000 ขึ้นอยู่กับการกำหนดค่าเซิร์ฟเวอร์ของคุณ (หน่วยความจำ) คุณอาจต้องการลดจำนวนนี้ ทำสิ่งนี้ในขณะที่สร้างอินสแตนซ์ WebPush หรือเรียกใช้ setDefaultOptions
หรือหากคุณต้องการปรับแต่งสิ่งนี้สำหรับฟลัชที่เฉพาะเจาะจง ให้ให้เป็นพารามิเตอร์ : $webPush->flush($batchSize)
คุณสามารถดูว่าเซิร์ฟเวอร์ของผู้จำหน่ายเบราว์เซอร์ส่งอะไรกลับมาในกรณีที่พบข้อผิดพลาด (พุชการหมดอายุการสมัครสมาชิก พารามิเตอร์ผิด...)
sendOneNotification()
ส่งคืน MessageSentReport
flush()
ส่งคืน Generator
พร้อมวัตถุ MessageSentReport
หากต้องการวนซ้ำผลลัพธ์ เพียงส่งมันไปที่ foreach
คุณยังสามารถใช้ iterator_to_array
เพื่อตรวจสอบเนื้อหาขณะทำการดีบัก <?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 ();
}
}
โปรดทราบ: คุณสามารถวนซ้ำได้เพียง ครั้งเดียว บนวัตถุ Generator
ข้อผิดพลาดของ Firefox แสดงอยู่ในเอกสารการกดอัตโนมัติ
เพย์โหลดถูกเข้ารหัสโดยห้องสมุด ความยาวเพย์โหลดสูงสุดตามทฤษฎีคือ 4,078 ไบต์ (หรืออักขระ ASCII) เพื่อเหตุผลด้านความเข้ากันได้ (เก็บถาวร) เพย์โหลดของคุณควรมีความยาวน้อยกว่า 3052 ไบต์
ไลบรารีจะแพดเพย์โหลดตามค่าเริ่มต้น วิธีนี้มีความปลอดภัยมากกว่า แต่จะลดประสิทธิภาพทั้งเซิร์ฟเวอร์และอุปกรณ์ของผู้ใช้ของคุณ
เมื่อคุณเข้ารหัสสตริงที่มีความยาวที่กำหนด สตริงผลลัพธ์จะมีความยาวเท่ากันเสมอ ไม่ว่าคุณจะเข้ารหัสสตริงเริ่มต้นกี่ครั้งก็ตาม สิ่งนี้สามารถทำให้ผู้โจมตีคาดเดาเนื้อหาของเพย์โหลดได้ เพื่อหลีกเลี่ยงปัญหานี้ ไลบรารีนี้จะเพิ่มช่องว่างภายในเพย์โหลดเริ่มต้น เพื่อให้อินพุตทั้งหมดของกระบวนการเข้ารหัสจะมีความยาวเท่ากัน ด้วยวิธีนี้ ผลลัพธ์ทั้งหมดของกระบวนการเข้ารหัสจะมีความยาวเท่ากัน และผู้โจมตีจะไม่สามารถคาดเดาเนื้อหาของเพย์โหลดของคุณได้
การเข้ารหัสไบต์ที่มากขึ้นจะใช้เวลารันไทม์บนเซิร์ฟเวอร์ของคุณมากขึ้น และยังทำให้อุปกรณ์ของผู้ใช้ช้าลงด้วยการถอดรหัสอีกด้วย นอกจากนี้การส่งและรับแพ็กเก็ตจะใช้เวลานานกว่า นอกจากนี้ยังไม่เป็นมิตรกับผู้ใช้ที่มีแผนข้อมูลจำกัด
คุณสามารถปรับแต่งช่องว่างภายในอัตโนมัติเพื่อให้เหมาะกับความต้องการของคุณได้ดียิ่งขึ้น
ต่อไปนี้คือแนวคิดบางประการเกี่ยวกับการตั้งค่า:
Encryption::MAX_COMPATIBILITY_PAYLOAD_LENGTH
(2820 ไบต์) เพื่อความเข้ากันได้กับ Firefox สำหรับ Android (ดู #108)Encryption::MAX_PAYLOAD_LENGTH
(4078 ไบต์) เพื่อความปลอดภัยสูงสุดfalse
เพื่อประสิทธิภาพสูงสุดX
ไบต์ ให้ตั้งค่าเป็น X
เพื่อความสมดุลที่ดีที่สุดระหว่างความปลอดภัยและประสิทธิภาพ <?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 ใช้ Guzzle มันจะใช้ไคลเอนต์ที่เหมาะสมที่สุดที่พบ และส่วนใหญ่จะเป็น MultiCurl
ซึ่งอนุญาตให้ส่งการแจ้งเตือนหลายรายการพร้อมกัน
คุณสามารถปรับแต่งตัวเลือกคำขอเริ่มต้นและการหมดเวลาได้เมื่อสร้างอินสแตนซ์ WebPush:
<?php
use Minishlink WebPush WebPush ;
$ timeout = 20 ; // seconds
$ clientOptions = [
GuzzleHttp RequestOptions:: ALLOW_REDIRECTS => false ,
]; // see GuzzleHttp RequestOptions
$ webPush = new WebPush ([], [], $ timeout , $ clientOptions );
มีดังต่อไปนี้:
อย่าลังเลที่จะเพิ่มของคุณเอง!
เพย์โหลดได้รับการเข้ารหัสตามมาตรฐาน Message Encryption for Web Push โดยใช้คีย์สาธารณะของผู้ใช้และความลับในการตรวจสอบสิทธิ์ที่คุณจะได้รับโดยปฏิบัติตามข้อกำหนด Web Push API
ภายใน WebPush ใช้เฟรมเวิร์ก WebToken และ OpenSSL เพื่อจัดการการสร้างและการเข้ารหัสคีย์การเข้ารหัส
นี่คือแนวคิดบางส่วน:
defaultOptions
หรือเป็นพารามิเตอร์เพื่อ flush()
)flushPooled()
แทน flush()
แบบแรกใช้คำขอที่เกิดขึ้นพร้อมกัน เพื่อเร่งกระบวนการและมักจะเพิ่มความเร็วของคำขอเป็นสองเท่าการติดตั้งของคุณไม่มีใบรับรองบางอย่าง
php.ini
ของคุณ : หลังจาก [curl]
ให้พิมพ์ curl.cainfo = /path/to/cacert.pem
คุณยังสามารถบังคับใช้ไคลเอนต์โดยไม่ต้องมีการยืนยันจากเพื่อนได้
ตรวจสอบให้แน่ใจว่าต้องใช้ตัวโหลดอัตโนมัติของผู้แต่ง
require __DIR__ . ' /path/to/vendor/autoload.php ' ;
ตรวจสอบให้แน่ใจว่ามีช่องฐานข้อมูลที่ใหญ่เพียงพอสำหรับความยาวของข้อมูลที่คุณจัดเก็บ (#233) สำหรับอุปกรณ์ปลายทาง ผู้ใช้รายงานว่า URL มีความยาวไม่เกิน 500 อักขระ แต่สามารถเปลี่ยนแปลงได้ ดังนั้นคุณจึงสามารถตั้งค่าขีดจำกัดอักขระไว้ที่ 2,048 ตัวในเบราว์เซอร์ส่วนใหญ่ได้
ดูฉบับที่ #58
บริการนี้ไม่มีอยู่อีกต่อไป ถูกแทนที่ด้วย Firebase Cloud Messaging (FCM) ของ Google เมื่อวันที่ 29 พฤษภาคม 2019
ไลบรารีนี้ไม่รองรับ Firebase Cloud Messaging (FCM) การสมัครใช้งาน Chrome แบบเก่า (ก่อนปี 2018 และ VAPID) ใช้โปรโตคอล HTTP เดิมโดย Firebase Cloud Messaging (FCM) ซึ่งเลิกใช้งานแล้วตั้งแต่ปี 2023 และจะหยุดทำงานในเดือนมิถุนายน 2024 การรองรับการสมัครใช้บริการที่ล้าสมัยนี้จะถูกลบออก
โปรดอย่าสับสนเนื่องจากโปรโตคอล HTTP เดิมและ Web Push ที่มี VAPID ใช้ URL ปลายทางที่เหมือนกัน:
https://fcm.googleapis.com/fcm/send
Web Push พร้อม VAPID จะยังคงอยู่ที่ URL นี้ ไม่จำเป็นต้องดำเนินการใดๆ เพิ่มเติมในขณะนี้
ผู้จำหน่ายเบราว์เซอร์ไม่อนุญาตให้ส่งข้อมูลโดยใช้ Push API โดยไม่สร้างการแจ้งเตือน ใช้ API ทางเลือกบางอย่าง เช่น WebSocket/WebTransport หรือการซิงโครไนซ์พื้นหลัง
WebPush ใช้สำหรับเว็บแอป คุณต้องการบางอย่างเช่น RMSPushNotificationsBundle (Symfony)
ไลบรารีนี้ได้รับแรงบันดาลใจจากไลบรารี Node.js web-push-libs/web-push
server.js
: ควรแทนที่ด้วยโค้ดเซิร์ฟเวอร์ PHP ของคุณด้วยไลบรารีนี้)เอ็มไอที