- 后端
- Web框架
【免费下载链接】symfony
The Symfony PHP framework
Sendberry 是 Symfony Notifier 组件为 Sendberry 短信服务平台提供的一体化接入桥(Bridge),本指南将带你完整掌握其 DSN 配置参数、SmsMessage发送流程、底层 HTTP 请求结构、消息校验规则以及 6.1~8.2 各版本的能力演进。读完本文,你既能写出可直接运行的.env配置,也能读懂SendberryTransport源码级实现,并了解如何用测试用例验证桥接行为。
一、桥接组件定位与安装前提
Sendberry 桥接位于 src/Symfony/Component/Notifier/Bridge/Sendberry,属于 Symfony Notifier 生态中众多短信(SMS)桥接之一。从 composer.json 可以看到它的依赖约束:
php: >=8.4.1,要求较新的 PHP 运行时;symfony/http-client: ^7.4|^8.0,发送短信依赖 HttpClient 发起 HTTP 请求;symfony/notifier: ^8.2,桥接建立在 Notifier 组件的 Transport 抽象之上;- 类型为
symfony-notifier-bridge,自动加载命名空间为Symfony\Component\Notifier\Bridge\Sendberry。
因此,要在应用中使用它,至少需要安装 Notifier 与 HttpClient 两个组件,例如:
composer require symfony/notifier symfony/http-client然后通过symfony/notifier的桥接发现机制加载sendberryscheme。实际发送短信时,Notifier 的Transport接口负责消息分发,而桥接只需要实现supports()与doSend()两个关键方法(见 SendberryTransport.php)。
二、DSN 配置:完整参数与来源
Sendberry 桥接的官方 DSN 示例(来自 README.md)如下:
SENDBERRY_DSN=sendberry://USERNAME:PASSWORD@default?auth_key=AUTH_KEY&from=FROM各组成部分含义如下表:
| DSN 片段 | 说明 |
|---|---|
USERNAME | 你在 Sendberry 平台自定义的访问用户名(access name) |
PASSWORD | 与用户名对应的访问密码(access password) |
AUTH_KEY | 平台生成的认证密钥(authentication key) |
FROM | 发件人名称,可以是电话号码或发件人名称(sender name) |
其中USERNAME、PASSWORD分别由 SendberryTransportFactory.php 通过基类AbstractTransportFactory的getUser()与getPassword()解析;若缺失会抛出IncompleteDsnException(见 AbstractTransportFactory.php)。
auth_key与from则通过$dsn->getRequiredOption('auth_key')/$dsn->getRequiredOption('from')读取,属于必填查询参数。测试用例 SendberryTransportFactoryTest.php 明确验证了缺少任一参数都会报错:
// missing option: auth_key 'sendberry://username:password@default?from=from' // missing option: from 'sendberry://username:password@default?auth_key=auth_key'另外,host部分若为字面量default会被置空('default' === $dsn->getHost() ? null : $dsn->getHost()),随后交由setHost()处理,最终回落到SendberryTransport::HOST = 'api.sendberry.com';port同样可显式覆盖。
三、8.2 新增:ssl选项与明文 HTTP 通道
CHANGELOG 记录 8.2 版本引入了一个重要能力:新增sslDSN 选项,用于通过明文 HTTP 发送请求("Add thesslDSN option to send requests over plain HTTP")。
在工厂侧(SendberryTransportFactory.php),构造 Transport 后链式调用了->setSsl($this->getSsl($dsn))。基类getSsl()的实现(AbstractTransportFactory.php)为:
protected function getSsl(Dsn $dsn): ?bool { return null === $dsn->getOption('ssl') ? null : $dsn->getBooleanOption('ssl'); }即:未提供ssl时返回null;提供时按布尔值解析。在 Transport 侧,AbstractTransport::getHttpScheme()(AbstractTransport.php)决定最终协议:
protected function getHttpScheme(): string { return ($this->ssl ?? static::SSL) ? 'https' : 'http'; }因此,只要在 DSN 中追加&ssl=0或&ssl=false,即可让桥接改用明文http://访问api.sendberry.com/SMS/SEND端点。这一特性通常用于对接仅提供明文 HTTP 的网关或本地联调环境;生产环境仍默认走 HTTPS(基类默认SSL常量为真)。
四、消息发送流程与底层 HTTP 调用
SendberryTransport只支持SmsMessage。supports()返回$message instanceof SmsMessage(SendberryTransport.php);若在doSend()中收到非SmsMessage,会抛出UnsupportedMessageTypeException。测试 SendberryTransportTest.php 也验证了ChatMessage与DummyMessage均不被支持。
4.1 发件人取值优先级
doSend()的第一步是确定发件人:
$from = $message->getFrom() ?: $this->from;这与 CHANGELOG 中 6.2 版本的能力一一对应:当SmsMessage定义了from时优先使用消息自身的发件人,否则回退到 DSN 配置的from("UseSmsMessage->fromwhen defined")。这使得同一条 DSN 可以服务多个不同发件人场景。
4.2 发件人格式校验
随后代码用两段正则校验$from(SendberryTransport.php):
- 若匹配
^[+]+[1-9][0-9]{9,14}$,视为合法的国际格式电话号码(+开头、首位非 0、总长 10~15 位); - 否则要求非空,且仅包含
a-zA-Z0-9与空格,即合法的字母数字 Sender ID; - 空字符串或含其他字符都会抛出
IncompleteDsnException(分别提示"This phone number is invalid."与"The Sender ID is invalid.")。
4.3 请求端点与 JSON 载荷
实际请求构造如下(SendberryTransport.php):
$endpoint = \sprintf('%s://%s/SMS/SEND', $this->getHttpScheme(), $this->getEndpoint()); $response = $this->client->request('POST', $endpoint, [ 'json' => [ 'from' => $from, 'to' => [$message->getPhone()], 'content' => $message->getSubject(), 'key' => $this->authKey, 'name' => $this->username, 'password' => $this->password, ], ]);要点:
- 目标为
POST {scheme}://{host}[/:{port}]/SMS/SEND,getEndpoint()会拼接自定义 host/port,缺省时使用api.sendberry.com(AbstractTransport.php); - 载荷为 JSON:
from、to(数组)、content、key、name、password六个字段,其中to来自SmsMessage::getPhone(),content来自getSubject(); - 若 HttpClient 本身抛
TransportExceptionInterface(网络不可达),会被包装为TransportException("Could not reach the remote Sendberry server.")。
4.4 响应校验与消息 ID
请求返回后按如下规则处理(SendberryTransport.php):
- 状态码非 200 时抛出
TransportException("Unable to send the SMS."); - 解析 JSON 响应,若
status存在且不等于'ok',则把message数组逐行拼接进异常信息再抛出; - 成功时构造
SentMessage,并读取ID字段作为消息 ID 写入($sentMessage->setMessageId($responseArr['ID'])),便于后续追踪与对账。
SentMessage的(string)$this形式来自__toString()(SendberryTransport.php),会以sendberry://{endpoint}?from={from}的格式记录发送元信息。
五、消息分发:事件与异常路径
SendberryTransport继承自AbstractTransport,其公开的send()方法(AbstractTransport.php)负责统一的消息分发流程:
- 未配置事件分发器时直接调用
doSend(); - 配置了
EventDispatcherInterface时依次派发MessageEvent(发送前)、SentMessageEvent(成功)或FailedMessageEvent(失败后重抛异常)。
因此,即使桥接本身只实现doSend(),应用仍可无缝接入 Symfony 的事件系统,对发送前、发送成功、发送失败三个阶段做日志、指标或重试处理。
六、版本演进时间线
CHANGELOG 完整记录了该桥接的三个版本节点:
| 版本 | 变更内容 |
|---|---|
| 6.1 | 新增 Sendberry 桥接("Add the bridge"),首次引入SendberryTransport与SendberryTransportFactory |
| 6.2 | 优先使用SmsMessage->from作为发件人("UseSmsMessage->fromwhen defined") |
| 8.2 | 新增sslDSN 选项,支持通过明文 HTTP 发送请求 |
需要说明:仓库当前 composer.json 要求symfony/notifier: ^8.2、symfony/http-client: ^7.4|^8.0,即当前形态面向 8.x 分支;6.x 时代的 API 结构(SmsMessage::getFrom()、auth_key/from必填项等)在 8.2 中仍然延续,并叠加了ssl选项的新能力。
七、测试验证与自定义 host 场景
仓库内的两组测试可帮助理解桥接行为边界:
- SendberryTransportTest.php:验证
sendberry://api.sendberry.com?from=from的字符串表示、仅支持SmsMessage、拒绝ChatMessage与DummyMessage; - SendberryTransportFactoryTest.php:验证 scheme 解析(
sendberry://user:password@host.test?auth_key=auth_key&from=%2B0611223344可创建传输、其他 scheme 报UnsupportedSchemeException)、必填项缺失报错、以及缺少 user 的IncompleteDsnException场景。
其中supportsProvider()里出现sendberry://api_key@default?from=%2B0611223344这类无 user/password 仍通过的用例,说明工厂在supports()阶段只做 scheme 匹配,真正的凭据完整性检查推迟到create()/发送时完成。
若需对接 Sendberry 的测试沙箱或自定义网关,可在 DSN 中显式指定 host 与 port,例如:
SENDBERRY_DSN=sendberry://user:pass@sandbox.example.com:8080?auth_key=KEY&from=+8613800138000&ssl=0其中+8613800138000这类带+的值在 DSN 中需做 URL 编码(%2B),如测试用例所示。
八、快速上手示例
在 Symfony 应用中使用 Sendberry 发送短信的最小路径:
安装依赖:
composer require symfony/notifier symfony/http-client在
.env中配置 DSN:SENDBERRY_DSN=sendberry://USERNAME:PASSWORD@default?auth_key=AUTH_KEY&from=FROM通过
Notifier服务发送SmsMessage:use Symfony\Component\Notifier\Notifier; use Symfony\Component\Notifier\NotifierInterface; use Symfony\Component\Notifier\Recipient\Recipient; /** @var NotifierInterface $notifier */ $notifier->send( new SmsMessage('+8613800138000', 'Hello from Symfony!', '+8613900139000'), new Recipient('+8613800138000'), );若第三个参数(
from)留空,桥接会自动使用 DSN 中的FROM;指定后则以消息级from为准(对应 6.2 行为)。调试时可用
MockHttpClient替换真实客户端(如测试所示),在不触网的情况下断言请求载荷与错误分支。
综上,Sendberry 桥接虽然代码量小,却完整覆盖了 DSN 解析、消息类型约束、发件人校验、HTTP 调用与错误归一化等 Notifier 桥接的标准范式,是理解 Symfony Notifier 传输层实现的上佳样例。
- 后端
- Web框架
【免费下载链接】symfony
The Symfony PHP framework
相关推荐
Symfony Octopush Notifier 桥接器:DSN 配置、消息发送与版本演进全解析
Symfony Octopush Notifier 桥接器:DSN 配置、消息发送与版本演进全解析 导读 本篇文章围绕 Symfony 官方 Notifier
后端Web框架Symfony Notifier 的 KazInfoTeh 短信桥接器:DSN 配置、发送流程与 CHANGELOG 演进解读
Symfony Notifier 的 KazInfoTeh 短信桥接器:DSN 配置、发送流程与 CHANGELOG 演进解读 KazInfoTeh 是哈萨克斯
后端Web框架Symfony Notifier 的 iSendPro 短信桥接器:DSN 配置、ssl 选项与版本演进全解析
Symfony Notifier 的 iSendPro 短信桥接器:DSN 配置、ssl 选项与版本演进全解析 iSendPro 是法国电信服务商提供的短信(S
后端Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考