尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Symfony Notifier Firebase 桥接组件实战指南:从 DSN 配置到 FCM 消息发送

Symfony Notifier Firebase 桥接组件实战指南:从 DSN 配置到 FCM 消息发送 后端Web框架【免费下载链接】symfonyThe Symfony PHP framework项目地址https://gitcode.com/GitHub_Trending/sy/symfony点击查看免费下载本指南以 Symfony 仓库中 Firebase Notifier 桥接组件文档 为主体系统讲解如何通过symfony/firebase-notifier将 Symfony Notifier 与 Firebase Cloud MessagingFCM集成从获取服务账号私钥、构建firebase://DSN到使用FirebaseOptions构造带平台特性的推送消息并深入剖析FirebaseTransport底层如何基于 FCM v1 API 完成 JWT 鉴权与消息投递。读完本文你将能在一套标准的 Symfony Notifier 通知体系中接入 Firebase 推送并灵活控制 token、topic、condition 三种消息目标与 Android / WebPush / APNS 平台配置。桥接组件概览Firebase 在 Symfony Notifier 中的角色该桥接组件位于 src/Symfony/Component/Notifier/Bridge/Firebase包名为symfony/firebase-notifier其职责是为 Symfony Notifier 提供 FirebaseFirebase Cloud Messaging集成能力。它的定位是通道Channel你仍然通过 Notifier 统一的ChatMessage发消息由FirebaseTransport负责把它翻译成 FCM v1 API 的请求并发送到 Firebase。从 composer.json 可以看到其运行前提php 8.4.1ext-openssl用于对 JWT 断言签名见下文鉴权原理symfony/http-client ^7.4|^8.0发送 HTTP 请求symfony/notifier ^8.2桥接组件整体结构包含FirebaseTransport传输实现、FirebaseTransportFactoryDSN 工厂、FirebaseOptions消息选项、TargetType目标类型枚举以及一组已被标记废弃的Notification\AndroidNotification、Notification\IOSNotification、Notification\WebNotification辅助类。第一步获取 Firebase 服务账号凭据在配置 DSN 之前需要先从 Firebase 控制台拿到服务账号私钥文件。原文档给出了完整的操作路径登录 Firebase 控制台点击进入你的项目点击 Project Overview 旁边的齿轮图标选择 Project settings切换到 Service accounts 标签页点击底部的 Generate new private key 按钮浏览器将下载一个 JSON 格式的私钥文件。下载下来的 JSON 私钥文件应包含以下键typeproject_idprivate_key_idprivate_keyclient_emailclient_idauth_uritoken_uriauth_provider_x509_cert_urlclient_x509_cert_urluniverse_domain其中project_id、private_key_id、private_key、client_email四个字段是构建 DSN 所必需的其余字段供 Firebase 生态内其他场景使用。这一点与 FirebaseTransportFactory.php 的create()方法严格对应工厂通过$dsn-getRequiredOption(project_id)、getRequiredOption(private_key_id)、getRequiredOption(private_key)强制校验这三个 query 参数缺失即抛出MissingRequiredOptionException。第二步理解并构建 firebase:// DSN原文档给出的 DSN 模板如下FIREBASE_DSNfirebase://CLIENT_EMAILdefault?project_idPROJECT_IDprivate_key_idPRIVATE_KEY_IDprivate_keyPRIVATE_KEY四个参数全部必填且都位于上述 Firebase JSON 私钥文件中。DSN 的结构值得逐段拆解对照工厂源码DSN 片段含义在工厂中的解析位置firebase://协议 schemeFirebaseTransportFactory::getSupportedSchemes()返回[firebase]FirebaseTransportFactory.phpscheme 不匹配时抛出UnsupportedSchemeExceptionCLIENT_EMAIL用户部分即client_email通过$this-getUser($dsn)读取作为传输的$clientEmail参数FirebaseTransportFactory.phpdefault主机名占位default $dsn-getHost() ? null : $dsn-getHost()即默认使用内置端点fcm.googleapis.comFirebaseTransportFactory.phpproject_id项目 ID必需的 query 选项private_key_id私钥 ID必需的 query 选项private_key私钥内容必需的 query 选项必须安全地进行 URL 编码关键注意事项private_key是一段包含换行符和 PEM 标记-----BEGIN PRIVATE KEY-----的长文本直接拼进 URL 会被解析器截断或转义错误。原文档特别强调必须对它做 URL 编码urlencode并建议直接使用下面提供的转换脚本而不是手写 DSN。从 FirebaseTransportTest.php 的测试常量也可以看到真实私钥是带\n的多行 PEM 文本这正是必须编码的原因。版本说明在 8.2 之前桥接组件曾支持firebase://USERNAME:PASSWORDdefault这种旧式 DSN凭据为服务账号令牌。根据 CHANGELOG.md8.2 起已弃用该格式改为firebase://PROJECT_ID?client_email...private_key_id...private_key...所对应的新格式工厂在缺少新参数时会触发trigger_deprecation并退回旧路径FirebaseTransportFactory.php。新项目请直接使用四参数 DSN。第三步用官方脚本把 JSON 私钥转换为 DSN原文档提供了一个开箱即用的 PHP 转换脚本可直接复制保存为firebase_dsn.php使用?php if (!isset($argv[1])) { echo Usage: php . $argv[0] . path_to_your_key.json.PHP_EOL; exit(1); } $file file_get_contents($argv[1]); if (false $file) { echo Could not open file at path: .$argv[1].PHP_EOL.PHP_EOL; exit(1); } $key json_decode($file, true); if (false $key) { echo Unable to load JSON content of the file at path: .$argv[1].PHP_EOL; exit(1); } foreach ([client_email, project_id, private_key_id, private_key] as $param) { if (!isset($key[$param])) { echo Missing param .$param. inside the JSON key..PHP_EOL; exit(1); } } echo sprintf( FIREBASE_DSNfirebase://%sdefault?project_id%sprivate_key_id%sprivate_key%s, $key[client_email], $key[project_id], $key[private_key_id], urlencode($key[private_key]), ).PHP_EOL;脚本的执行方式php script_name.php path/to/your/firebase/key.json脚本逻辑与前述 DSN 结构一一对应读取 JSON 私钥文件 → 校验四个必需字段是否存在 → 将client_email放入 DSN 用户段、project_id/private_key_id/private_key放入 query 段其中private_key经urlencode()安全编码后输出。运行后把输出的FIREBASE_DSN...整行写入你的环境变量.env或FIREBASE_DSN环境变量即可被 Notifier 工厂自动解析。第四步通过 FirebaseOptions 定制消息原文档强调Firebase 消息的平台特定选项要通过FirebaseOptions类来指定。它对应 FCM v1 REST API 中projects.messages的message资源结构FirebaseOptions.php 的实现注解指向该资源定义。基础用法指定通知内容与自定义数据use Symfony\Component\Notifier\Message\ChatMessage; use Symfony\Component\Notifier\Bridge\Firebase\FirebaseOptions; $chatMessage new ChatMessage(Hello, you should contribute to Symfony.); // 为 Firebase 指定选项 $firebaseOptions (new FirebaseOptions(/topics/news)) -title(New message!) -body(This will overwrite the subject from ChatMessage object.) -image(https://path-to-your-image.png) -data([ key1 value1, key2 value2, ]) // ... ; // 将自定义选项挂到聊天消息上并发送 $chatMessage-options($firebaseOptions); $chatter-send($chatMessage);几点源码级解读FirebaseOptions构造签名是__construct(string $target, array $options [], array $data [], TargetType $targetType TargetType::Topic)首参$target即消息目标如/topics/news默认目标类型为 TopicFirebaseOptions.php。title()/body()/image()通过addNotificationOption()写入options[notification]键FirebaseOptions.php而data()写入options[data]键和值都必须是字符串。toArray()会把目标按targetType-value作为键合并进选项数组例如默认生成[topic /topics/news, ...]FirebaseOptions.php。在FirebaseTransport::doSend()中若消息未显式设置notification.body传输层会用ChatMessage的 subject 填充FirebaseTransport.php这正是原文档示例中body()注释覆盖 ChatMessage subject的含义。原文档示例中最后一句$chatMessage-options($androidOptions)中的$androidOptions应为前文定义的$firebaseOptions示例笔误实际应挂载FirebaseOptions实例。三种目标类型token / topic / conditionFirebase 提供 3 种不同的消息发送目标桥接组件用枚举 TargetType 表达TargetType::Topic→topicTargetType::Token→token单个设备注册令牌TargetType::Condition→condition基于主题的表达式的布尔组合指定不同目标的方式use Symfony\Component\Notifier\Bridge\Firebase\FirebaseOptions; use Symfony\Component\Notifier\Bridge\Firebase\TargetType; // 以主题为目标 $topicOptions new FirebaseOptions(/topics/news, targetType: TargetType::Topic); // 以设备令牌为目标 $tokenOptions new FirebaseOptions(dU5e3nFJf9bE:APA91bH3Kd/exampleToken, targetType: TargetType::Token); // 以条件为目标 $conditionOptions new FirebaseOptions(\news\ in topics, targetType: TargetType::Condition);从传输层实现看doSend()会校验最终消息中必须且只能包含token、topic、condition三者之一否则抛出InvalidArgumentExceptionFirebaseTransport.php。此外getRecipientId()会返回形如[topic]/topics/news的接收者标识便于 Notifier 的调试与统计FirebaseOptions.php。平台特定选项Android / WebPush / APNSFirebase 允许为不同平台指定各自的配置FirebaseOptions提供了对应链式方法FirebaseOptions.phpuse Symfony\Component\Notifier\Bridge\Firebase\FirebaseOptions; use Symfony\Component\Notifier\Bridge\Firebase\TargetType; $detailedOptions (new FirebaseOptions(dU5e3nFJf9bE:APA91bH3Kd/exampleToken, targetType: TargetType::Token)) // 基础选项 -title(New message!) -data([ key1 value1, key2 value2, ]) // Android 专属选项 -android([ notification [ color #4538D5, ], ]) // WebPush 专属选项 -webpush([ notification [ icon https://path-to-an-icon.png, ], ]) // APNS 专属选项 -apns([ payload [ aps [ sound default, ], ], ]) // ... ;方法清单与对应的 FCM 配置字段方法写入的message字段对应 FCM 资源notification(array)notificationNotificationandroid(array)androidAndroidConfigwebpush(array)webpushWebpushConfigapns(array)apnsApnsConfigfcmOptions(array)fcm_optionsFcmOptionsdata(array)data自定义键值数据android、webpush、apns等方法直接把数组原样写入对应顶层键其中 APNS 有更精细的辅助方法addApnsOption、addApnsAlertOption用于嵌套构造payload.aps及alert结构FirebaseOptions.php。每种平台支持的具体字段繁多完整的可用选项请以 Firebase 官方 FCM REST 文档 为准桥接组件只负责透传。底层原理FirebaseTransport 如何发送消息支持的消息类型FirebaseTransport::supports()明确限定只接受ChatMessage且其 options 必须为null或FirebaseOptions实例FirebaseTransport.php。测试用例也印证了这一点ChatMessage(Hello!)受支持而SmsMessage和DummyMessage被拒绝FirebaseTransportTest.php。端点与鉴权JWTRS256传输的默认主机为fcm.googleapis.comFirebaseTransport.php发送请求指向FCM v1 APIPOST https://fcm.googleapis.com/v1/projects/{projectId}/messages:send Authorization: Bearer JWT鉴权由getJwt()实现FirebaseTransport.php其构造过程与 Firebase 服务账号标准的 OAuth2 JWT 断言一致JOSE 头algRS256、typJWT、kidprivateKeyId——Google 依据kid选择签名密钥载荷issclientEmail、subclientEmail、audhttps://fcm.googleapis.com/、iat当前时间、exp当前时间3600签名用openssl_pkey_get_private()加载private_key以OPENSSL_ALGO_SHA256对header.payload做 RS256 签名缓存JWT 有效期 1 小时传输层缓存 3540 秒jwtExpiresAt临近过期才重新签发避免每个消息都重复签名。注意三个编码细节JWT 三个段均使用 base64url//替换为-/_并去掉填充见base64UrlEncode()FirebaseTransport.phpprivate_key加载失败如 DSN 中未正确解码会抛出无法从 DSN 加载私钥的InvalidArgumentException。这正是原文档强调PRIVATE_KEY必须安全 URL 编码的原因——一旦编码不当换行符丢失PEM 密钥将无法被 OpenSSL 解析。消息结构与错误处理doSend()最终发送的 JSON 结构为{message: {...options}}FirebaseTransport.php。响应处理分两条路径若响应为application/json且含error.message字段或 HTTP 状态码非 200则抛出携带 Firebase 错误信息的TransportExceptionFirebaseTransport.php。测试用例sendWithErrorThrowsExceptionProvider覆盖了 200 与 400 两种错误响应场景FirebaseTransportTest.php成功时从响应name字段取出消息 ID写入SentMessage::setMessageId()后返回FirebaseTransport.php。另外8.2 起可通过 DSN 的ssl选项让请求走明文 HTTP见 CHANGELOG.md对应工厂中setSsl($this-getSsl($dsn))的调用仅用于本地调试等特殊场景。版本演进与升级注意点综合 CHANGELOG.md 与本仓库当前代码桥接组件的关键演进如下5.1.0新增本桥接组件5.3不再标记为experimental并新增data字段支持8.2切换为通过Firebase Cloud Messaging v1 API发送消息弃用AndroidNotification、IOSNotification、WebNotification三个类统一改用FirebaseOptions弃用旧式firebase://USERNAME:PASSWORDdefaultDSN 与FirebaseTransport::__construct()的$token参数构造函数内会触发弃用提示见 FirebaseTransport.php新增sslDSN 选项。从源码可以看出被弃用的三个 Notification 类本身也是FirebaseOptions的子类例如 AndroidNotification.php 构造时直接调用parent::__construct($target, [notification $options], $data, $targetType)并触发弃用提示。其曾经提供的channelId()、icon()、sound()、tag()、color()、clickAction()、bodyLocKey()等便捷方法AndroidNotification.php在新代码中均可用FirebaseOptions::android([...])数组方式等价表达——这正是 AndroidNotificationTest.php 中全部选项测试所展示的最终toArray()结构。因此新项目请直接使用FirebaseOptions。验证与调试仓库内的测试资产如需验证自己的集成理解仓库提供了现成的测试资产可直接参照FirebaseTransportTest.php展示了如何用四个凭据参数构造传输、断言__toString()输出firebase://fcm.googleapis.com、验证消息类型支持矩阵以及错误响应处理FirebaseTransportFactoryTest.php覆盖新/旧 DSN 格式的解析、scheme 支持判定与不完整 DSN 的报错Notification 目录下的三个测试分别验证 Android / iOS / Web 通知选项组装成toArray()的完整结构。总结接入symfony/firebase-notifier的完整链路是在 Firebase 控制台生成服务账号私钥 → 用转换脚本产出FIREBASE_DSN环境变量 → 在 Notifier 中构造携带FirebaseOptions的ChatMessage并发送。底层由FirebaseTransport负责基于client_email、project_id、private_key_id、private_key生成 RS256 JWT再以Bearer令牌调用 FCM v1 的messages:send端点完成投递。掌握 DSN 四参数与private_key的 URL 编码这一关键细节即可稳定地在 Symfony 项目中落地 Firebase 推送能力。赞分享后端Web框架【免费下载链接】symfonyThe Symfony PHP framework项目地址https://gitcode.com/GitHub_Trending/sy/symfony点击查看免费下载相关推荐Symfony Notifier Pushy 桥接组件从 DSN 配置到推送消息发送的完整实战指南Symfony Notifier Pushy 桥接组件从 DSN 配置到推送消息发送的完整实战指南 导读 本文基于 Symfony 官方仓库中 src/Sym后端Web框架Symfony Pushover Notifier 桥接组件实战DSN 配置与推送消息发送全解析Symfony Pushover Notifier 桥接组件实战DSN 配置与推送消息发送全解析 导读 Pushover 是一款面向个人与团队的消息推送服务后端Web框架OmniRoute Webhooks 事件推送指南HMAC-SHA256 签名、重试与交付健康管理OmniRoute Webhooks 事件推送指南HMAC SHA256 签名、重试与交付健康管理 本文基于仓库 docs/frameworks/WEBHOO后端Web框架创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表