25: 集成
大多数应用程序最终都会与外部服务进行交互:聊天服务、日历、会计后端、刷卡终端、支付处理器。Phlo 提供了两种用于此的功能,均在运行时中,因此无需额外的 SDK 进行集成,也无需单独的客户端进行连接。连接器是围绕 JSON REST API 的轻量级统一封装;支付资源封装了 Stripe 和 SumUp。
25.1: 连接器
连接器是一个小类,用于一个第三方 REST API。每个连接器都扩展 Connector,读取其自己的凭据部分,并返回相同的结果形状,因此调用 Slack 的方式与调用 Shopify 的方式相同。
$slack = Slack::make()
$res = $slack->send('#general', 'Deploy finished')
if ($res->ok) log('sent') else log($res->error)
make() 从 data/creds.ini 中加载连接器的凭据(Slack 读取 [Slack],Shopify 读取 [Shopify],依此类推)。每次调用都会返回一个标准化的对象,因此你可以根据 ->ok 进行分支,并读取 ->data,而不是为每个服务解析不同的错误格式:
obj(ok: true, status: 200, data: {...}) // success
obj(ok: false, status: 401, error: '...') // failure
在底层,Connector 处理请求动词(get/post/put/patch/del/form)、分页(paginate())和身份验证头。每个连接器还公开一个 static fields 凭证架构,因此设置屏幕或 CMS 可以在不硬编码的情况下进行配置。
可用连接器
| 组别 | 连接器 |
|---|---|
| 消息 | Slack, Telegram, Twilio, MessageBird, Resend |
| 云 | GoogleCalendar, GoogleSheets, MicrosoftGraph |
| 财务 | ExactOnline, Moneybird, EBoekhouden |
| 商务 | Lightspeed, Shopify |
使用 OAuth2 进行身份验证的服务(如 Google、Exact)扩展 OAuthConnector 而不是 Connector。它在 TokenStore 中保持一个自动刷新的承载令牌(持久化在 data/tokens/ 下,使用独占锁刷新),因此您的代码只需调用 ->events(...),令牌的处理保持不可见。
每个连接器的方法列表在 Manual 的 connectors 下实时更新。它是从资源文件生成的,因此不会与代码偏离。
25.2: 支付
Stripe
Stripe 资源是官方 stripe/stripe-php SDK 的一个薄层(通过 Composer 添加)。使用您的密钥调用一次 Stripe::boot(),然后使用静态助手:
Stripe::boot(%creds->Stripe)
$session = Stripe::checkout([
'mode' => 'subscription',
'line_items' => [['price' => 'price_123', 'quantity' => 1]],
'success_url' => 'https://example.com/done',
'cancel_url' => 'https://example.com/pricing',
])
location($session->url)
checkout() 创建一个结账会话,portal($customerId, $returnUrl) 打开账单门户,verifyWebhook($payload, $sigHeader, $secret) 在您采取行动之前验证传入事件。customer、createCustomer、subscription、subscriptions、product 和 price 涵盖了其余的常见接口。
SumUp
SumUp 通过 Cloud API 在配对的 SumUp Solo 读卡器上处理面对面支付。它是一个连接器(SumUp::make(),[SumUp] 凭据),因此返回相同的 obj(ok, ...) 结果:
$res = SumUp::make()->createReaderCheckout(1250, 'EUR', description: 'Table 4')
createReaderCheckout($amountMinor, $currency, ...) 将结账推送到读卡器(金额以小单位表示,因此 1250 是 €12.50)。transaction() 和 transactions() 用于查找结果,而 terminateReaderCheckout() 则取消一个待处理的结账。