PHP技术问题:为何无法向订阅地址推送通知?
Web Push通知推送失败排查与修复
你的核心问题在于没有对通知内容进行加密,却声明了aes128gcm内容编码,这直接导致推送服务器(WNS)无法处理请求。Web Push规范(包括WNS实现)要求所有包含内容的通知必须使用aes128gcm加密,你提到的加密要求完全适用于当前场景。以下是具体排查和修复步骤:
1. 核心问题分析
你设置了Content-Encoding: aes128gcm请求头,但直接发送了明文JSON数据。推送服务器期望接收的是加密后的二进制流,而非明文,因此会静默拒绝处理你的请求,这就是你看不到输出但收不到通知的原因。
2. 快速修复:使用成熟库处理加密与推送
手动实现Web Push加密逻辑非常繁琐,推荐使用minishlink/web-push库,它已经封装了加密、签名、服务商适配等所有细节。
步骤1:安装依赖
composer require minishlink/web-push
步骤2:重构代码
<?php require 'vendor/autoload.php'; use Minishlink\WebPush\WebPush; use Minishlink\WebPush\Subscription; // 构造订阅信息 $subscription = Subscription::create([ 'endpoint' => 'https://wns2-by3p.notify.windows.com/w/?token=BQYAAAAEycZlxsQTTp9zcqC%2fb8SosCVZv8A%2fzlCmVXBhpFZsBydTExEV7punPkvI6Iyq34EvL4DCGnq1q5iltFpbXpNfFIMFmZX5zceXuMKnxD7vfMCICw9T5j6yRyTtueWg%2fCpatXRfRTpVA3KnW2ZEW1HjcOvqY92pKLyj8Q0qNetRkyl1WUVhi46IjRRzFXqtB8zyM4jr%2fp0KUbGhhUIKodZ8QreC%2fGiw8CpVAjIFjn2F5a98zDgTyj6NHajd5OWGSQ2lzo452DmQpHgattx9bSfhfC7SrVuvBvoS7YUQ3y3lR4pfAejU9DIPc5H0iDCim9LDQ3BqfqCUJpW5l25NQNrs', 'publicKey' => 'BA7Fcw-tgO1UZrNZPUZjntJtkBYigJNLxcGFFRyHa0my0SszwnUwu0sZaE4W-EZas7yPi9iFNIe4LG5z6PtNfXc', // 对应原代码的p256dh 'authToken' => 'mRmbv1KsA_Yc_sKR43KnQw', // 对应原代码的auth ]); // 初始化WebPush客户端(需补充VAPID私钥) $webPush = new WebPush([ 'VAPID' => [ 'subject' => 'mailto:simple-push-demo@guestface.co.uk', // 你的联系邮箱 'publicKey' => 'BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaNndIo', 'privateKey' => '你的VAPID私钥', // 关键:原代码仅提供公钥,必须补上对应的私钥才能生成有效签名 ], ]); // 准备通知内容 $message = json_encode([ "title" => "Notification Title", "body" => "This is the body of the notification." ]); // 发送推送并检查结果 $report = $webPush->sendOneNotification($subscription, $message); if ($report->isSuccess()) { echo "推送成功"; } else { echo "推送失败: " . $report->getReason(); }
3. 其他潜在问题排查
- VAPID私钥缺失:你原代码的Authorization头仅包含公钥,VAPID签名必须使用公私钥对生成,确保你持有与提供的公钥对应的私钥。
- 订阅有效性:检查订阅是否已过期或被用户取消,WNS会返回410状态码表示订阅失效。
- 调试增强:在原代码中添加HTTP状态码输出,帮助定位问题:
常见错误码:400(请求格式错误)、401(VAPID签名无效)、410(订阅失效)。$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); echo "HTTP状态码: " . $httpCode . "\n"; - 设备状态:确保接收通知的设备在线,浏览器已开启通知权限,且未清除订阅数据。
内容的提问来源于stack exchange,提问作者Peemima
相关产品推荐
相关产品推荐

