Sign inGet Started

PHP SDK

messagebird/sdk 是 Bird API 的官方 PHP SDK:在生成的通信层之上提供有类型的手写接口。它面向 PHP 8.2+,采用同步模式;HTTP 通过你已有的任何 PSR-18 客户端(Guzzle、Symfony HttpClient 等)发送,自动发现可用实现。本页介绍客户端本身;如需端到端发送邮件,请从 PHP 邮件快速入门开始。

安装

代码示例
composer require messagebird/sdk

该包已发布为 Packagist 上的 messagebird/sdk。

构造客户端

代码示例
$bird = new Bird(
    getenv('BIRD_API_KEY') ?: '',
    region: 'eu1',                                          // optional; overrides the region inferred from the key prefix
    maxRetries: 2,                                          // retry budget for transient failures (default 2)
    email: new EmailDefaults(from: 'hello@acme.com'),       // optional channel defaults, such as a default sender
    webhookSecret: getenv('BIRD_WEBHOOK_SECRET') ?: null,   // signing secret for $bird->webhooks->unwrap()
);

只有 API 密钥是必需的。区域从密钥的 bk_{region}_ 前缀推断(bk_eu1_… 密钥路由到 https://eu1.platform.bird.com),因此大多数客户端仅用密钥即可构造;规则详见区域推断。baseUrl 可完全覆盖区域(本地或自托管)。此处设置的渠道默认值(例如 email: new EmailDefaults(from: "hello@acme.com"))使该字段在每次发送时变为可选,webhookSecret 是 $bird->webhooks->unwrap() 用于验证的密钥。在你传给 Bird 的 PSR-18 客户端上配置每请求超时。PSR-18 没有可移植的超时设置,因此该设置由传输层负责。

第一次调用

代码示例
$message = $bird->email->send(
    from: 'Bird <onboarding@messagebird.dev>',
    to: ['delivered@messagebird.dev'],
    subject: 'Hello from Bird',
    html: '<p>My first Bird email.</p>',
);
echo $message->getId(), ' ', $message->getStatus();

调用直接返回 API 结果:此处为一封包含 em_* id 的邮件消息。如需可运行的完整演练,请参阅 PHP 快速入门。

双层设计

SDK 结合了生成层和手写层。MessageBird\Wire 下的通信类型通过 jane-php 从 Bird 的 OpenAPI 规范生成,确保请求和响应结构与契约一致。手写层提供 $bird->email->send(...)、重试、幂等性、分页、错误处理和 webhook 验证。通信字段在 snake_case 中原样传递,例如 category 和 created_at。只有 SDK 定义的标识符(包括方法和选项名称,如 idempotencyKey)使用 camelCase。TypeScript、Go 和 Python SDK 共享此架构;详见 SDK 概念。

自动幂等性和重试

每个修改操作(POST、PUT、PATCH、DELETE)都会获得自动生成的 Idempotency-Key 请求头,每次重试都会复用同一个键,因此匹配的重试可以重放保留的响应。重试默认启用(maxRetries: 2):客户端会在发生暂时性故障(429、除 501 以外的 5xx,以及 PSR-18 传输错误)时,采用带随机抖动的指数退避进行重试,并遵循服务器的 Retry-After 响应头。确定性故障(例如 401、404、422 等 4xx)不会重试。有关不同 SDK 调用之间的自定义键和重放限制,请参阅幂等性。您可以为每次调用覆盖幂等性和重试设置:

代码示例
$bird->email->send(
    from: 'Bird <onboarding@messagebird.dev>',
    to: ['delivered@messagebird.dev'],
    subject: 'Hello from Bird',
    html: '<p>My first Bird email.</p>',
    options: new RequestOptions(idempotencyKey: 'order-1234', maxRetries: 0),
);

错误

失败的调用会抛出异常。MessageBird\Exception\ApiException 涵盖服务器返回的所有错误响应,并携带 status(HTTP 状态码)、type(粗略分类)和 errorCode(稳定的 E##### 代码)。传输层故障在耗尽重试预算后抛出 MessageBird\Exception\ConnectionException,因为不存在 HTTP 响应。两者都继承自 MessageBird\Exception\BirdException,捕获它即可统一处理。

代码示例
try {
    $bird->email->send(
        from: 'Bird <onboarding@messagebird.dev>',
        to: ['delivered@messagebird.dev'],
        subject: 'Hello from Bird',
        html: '<p>My first Bird email.</p>',
    );
} catch (ApiException $e) {
    // The server returned an error response. $status is the HTTP status, $type
    // the coarse category, $errorCode the stable E##### code.
    echo $e->status, ' ', $e->errorCode ?? $e->type ?? 'error';
} catch (ConnectionException $e) {
    // All retry attempts failed, so no HTTP response is available.
    echo 'transport error: ', $e->getMessage();
}

分页

列表方法返回一个惰性 Core\Page;用 foreach 迭代时会自动跨游标分页,按需获取每一页:

代码示例
foreach ($bird->email->list(['status' => 'delivered']) as $message) {
    echo $message->getId(), "\n";
}

如需手动控制游标,fetch() 返回单页:其 data 加上向前的 nextCursor,将其作为 starting_after 传回即可翻页:

代码示例
$page = $bird->email->list(['status' => 'delivered'])->fetch();
foreach ($page->data as $message) {
    echo $message->getId(), "\n";
}
$next = $page->nextCursor; // pass back as starting_after to fetch the next page

兜底通道

尚未纳入类型化接口的端点可通过 $bird->get / post / put / patch / delete 访问,认证、重试、幂等性和 base-URL 处理与类型化方法相同:

代码示例
// The verb methods (get/post/put/patch/delete) run through the same auth,
// retries, idempotency, and base-URL handling as the typed methods; pass a
// path and, for writes, a body array.
$messages = $bird->get('/v1/sms/messages', query: ['limit' => 10]);
$created = $bird->post('/v1/sms/messages', body: [
    'from' => '+15557654321',
    'to' => '+15551234567',
    'text' => 'Your code is 123456.',
    'category' => 'authentication',
]);

路径可在 API 参考文档中查找。

Webhooks

验证已送达 webhook 的 Standard Webhooks 签名并获取解码后的事件。在客户端上设置签名密钥(或按调用传入),并传入原始请求体:签名是对原始字节计算的,因此在验证前解析请求体是经典的 webhook 错误。

代码示例
// Pass the raw request body because parsing changes the bytes used to compute
// the signature.
$rawBody = file_get_contents('php://input') ?: '';
try {
    $event = $bird->webhooks->unwrap($rawBody, getallheaders());
    // $event is the decoded payload as an array; branch on $event['type'].
    echo $event['type'];
} catch (WebhookVerificationError) {
    http_response_code(400); // bad signature, stale timestamp, or missing/malformed headers
}

后续步骤