spatie/laravel-webhook-client

在 Laravel 应用中接收 webhooks

3.4.2 2024-08-07 07:31 UTC

README

Latest Version on Packagist GitHub Workflow Status Total Downloads

webhook 是一种让应用向另一个应用提供有关特定事件信息的方式。两个应用之间通过简单的 HTTP 请求进行通信。

此包允许您在 Laravel 应用中接收 webhook。它支持 验证签名调用存储有效负载并处理有效负载在队列作业中。

如果您需要发送 webhook,请查看我们的 laravel-webhook-server 包。

支持我们

我们投入了大量资源来创建 最佳开源包。您可以通过 购买我们的付费产品之一 来支持我们。

我们非常感谢您从家乡寄给我们一张明信片,说明您正在使用我们的哪个包。您可以在 我们的联系页面 找到我们的地址。我们将所有收到的明信片发布在我们的 虚拟明信片墙上

安装

您可以通过 composer 安装此包

composer require spatie/laravel-webhook-client

配置包

您可以使用以下命令发布配置文件

php artisan vendor:publish --provider="Spatie\WebhookClient\WebhookClientServiceProvider" --tag="webhook-client-config"

这是将在 config/webhook-client.php 中发布的文件的目录

<?php

return [
    'configs' => [
        [
            /*
             * This package supports multiple webhook receiving endpoints. If you only have
             * one endpoint receiving webhooks, you can use 'default'.
             */
            'name' => 'default',

            /*
             * We expect that every webhook call will be signed using a secret. This secret
             * is used to verify that the payload has not been tampered with.
             */
            'signing_secret' => env('WEBHOOK_CLIENT_SECRET'),

            /*
             * The name of the header containing the signature.
             */
            'signature_header_name' => 'Signature',

            /*
             *  This class will verify that the content of the signature header is valid.
             *
             * It should implement \Spatie\WebhookClient\SignatureValidator\SignatureValidator
             */
            'signature_validator' => \Spatie\WebhookClient\SignatureValidator\DefaultSignatureValidator::class,

            /*
             * This class determines if the webhook call should be stored and processed.
             */
            'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,

            /*
             * This class determines the response on a valid webhook call.
             */
            'webhook_response' => \Spatie\WebhookClient\WebhookResponse\DefaultRespondsTo::class,

            /*
             * The classname of the model to be used to store webhook calls. The class should
             * be equal or extend Spatie\WebhookClient\Models\WebhookCall.
             */
            'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,

            /*
             * In this array, you can pass the headers that should be stored on
             * the webhook call model when a webhook comes in.
             *
             * To store all headers, set this value to `*`.
             */
            'store_headers' => [

            ],

            /*
             * The class name of the job that will process the webhook request.
             *
             * This should be set to a class that extends \Spatie\WebhookClient\Jobs\ProcessWebhookJob.
             */
            'process_webhook_job' => '',
        ],
    ],

    /*
     * The number of days after which models should be deleted.
     *
     * Set to null if no models should be deleted.
     */
    'delete_after_days' => 30,
];

在配置文件的 signing_secret 键中,您应该添加一个有效的 webhook 密钥。此值应由将发送 webhook 给您的应用提供。

此包将尽可能快地存储和响应 webhook。通过队列作业处理请求的有效负载。建议不要使用 sync 驱动器,而使用真正的队列驱动器。您应该在配置文件的 process_webhook_job 中指定处理 webhook 请求的作业。任何扩展 Spatie\WebhookClient\Jobs\ProcessWebhookJob 并具有 handle 方法的类都是有效的作业。

准备数据库

默认情况下,所有 webhook 调用都将保存在数据库中。

要创建包含 webhook 调用的表,您必须使用以下命令发布迁移

php artisan vendor:publish --provider="Spatie\WebhookClient\WebhookClientServiceProvider" --tag="webhook-client-migrations"

在迁移发布后,您可以通过运行迁移来创建 webhook_calls

php artisan migrate

处理路由

最后,让我们处理路由。在发送 webhook 的应用中,您可能配置了一个 URL,您希望您的 webhook 请求发送到该 URL。在您应用的 routes 文件中,您必须将此路由传递给 Route::webhooks。以下是一个示例

Route::webhooks('webhook-receiving-url');

幕后,默认情况下这将注册一个 POST 路由到由本包提供的控制器。因为发送 webhook 到您的应用的应用没有获取 csrf-token 的方法,所以您必须将该路由添加到 VerifyCsrfToken 中间件的 except 数组中

protected $except = [
    'webhook-receiving-url',
];

使用

安装完成之后,让我们看看这个包如何处理webhook。首先,它将验证请求的签名是否有效。如果不有效,我们将抛出异常并触发InvalidWebhookSignatureEvent事件。具有无效签名的请求将不会存储在数据库中。

接下来,请求将被传递到webhook配置文件。webhook配置文件是一个类,用于确定请求是否应该由您的应用程序存储和处理。它允许您过滤掉对您的应用程序感兴趣的webhook请求。您可以轻松地创建自己的webhook配置文件

如果webhook配置文件确定请求应该被存储和处理,我们将首先将其存储在webhook_calls表中。之后,我们将这个新创建的WebhookCall模型传递给一个队列作业。大多数webhook发送应用程序都期望您能够快速响应。将实际处理工作委托出去可以快速响应。您可以在webhook-client配置文件中的process_webhook_job中指定哪个作业应该处理webhook。如果在队列作业时抛出异常,包将把该异常存储在WebhookCall模型的exception属性上。

作业分配后,请求将被传递到webhook响应。webhook响应是一个类,用于确定请求的HTTP响应。默认情况下,它返回带有200状态码的“ok”消息响应,但您可以轻松地创建自己的webhook响应

验证传入webhook的签名

此包假设传入的webhook请求有一个头部,可用于验证有效负载未被篡改。包含签名的头部的名称可以在配置文件的signature_header_name键中配置。默认情况下,包使用DefaultSignatureValidator来验证签名。这是该类计算签名的步骤。

$computedSignature = hash_hmac('sha256', $request->getContent(), $configuredSigningSecret);

如果$computedSignature与值匹配,请求将被传递给webhook配置文件。如果$computedSignature与签名头中的值不匹配,包将响应500并丢弃请求。

创建自己的签名验证器

签名验证器是实现了Spatie\WebhookClient\SignatureValidator\SignatureValidator的任何类。以下是该接口的外观。

use Illuminate\Http\Request;
use Spatie\WebhookClient\WebhookConfig;

interface SignatureValidator
{
    public function isValid(Request $request, WebhookConfig $config): bool;
}

WebhookConfig是一个数据传输对象,它允许您轻松地检索webhook请求的配置(包含包含签名的头部名称和密钥)。

创建自己的SignatureValidator后,您必须在webhook-client配置文件中的signature_validator中注册它。

确定哪些webhook请求应存储和处理

在验证传入webhook请求的签名之后,请求将被传递给webhook配置文件。webhook配置文件是一个类,用于确定请求是否应该被存储和处理。如果webhook发送应用程序发送出您的应用程序不感兴趣请求,您可以使用此类过滤掉此类事件。

默认情况下,使用\Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile类。正如其名称所暗示的,此默认类将确定所有传入请求都应该被存储和处理。

创建自己的webhook配置文件

webhook配置文件是实现了\Spatie\WebhookClient\WebhookProfile\WebhookProfile的任何类。以下是该接口的外观。

namespace Spatie\WebhookClient\WebhookProfile;

use Illuminate\Http\Request;

interface WebhookProfile
{
    public function shouldProcess(Request $request): bool;
}

创建自己的WebhookProfile后,您必须在webhook-client配置文件中的webhook_profile键中注册它。

存储和处理webhook

签名验证通过且webhook配置确定请求应被处理后,包将存储和处理请求。

请求首先将被存储在webhook_calls表中。这是使用WebhookCall模型完成的。

如果您想自定义表名或存储行为,可以让包使用一个替代模型。可以在webhook_model中指定一个webhook存储模型。确保您的模型扩展了Spatie\WebhookClient\Models\WebhookCall

您可以通过重写WebhookCallstoreWebhook方法来更改webhook的存储方式。在storeWebhook方法中,您应该返回一个已保存的模型。

接下来,新创建的WebhookCall模型将被传递给一个队列作业来处理请求。任何扩展了\Spatie\WebhookClient\Jobs\ProcessWebhookJob的类都是有效的作业。以下是一个示例

namespace App\Jobs;

use Spatie\WebhookClient\Jobs\ProcessWebhookJob as SpatieProcessWebhookJob;

class ProcessWebhookJob extends SpatieProcessWebhookJob
{
    public function handle()
    {
        // $this->webhookCall // contains an instance of `WebhookCall`

        // perform the work here
    }
}

您应该在webhook-client配置文件的process_webhook_job中指定您作业的类名。

创建自己的webhook响应

webhook响应是任何实现了\Spatie\WebhookClient\WebhookResponse\RespondsToWebhook接口的类。这个接口看起来是这样的

namespace Spatie\WebhookClient\WebhookResponse;

use Illuminate\Http\Request;
use Spatie\WebhookClient\WebhookConfig;

interface RespondsToWebhook
{
    public function respondToValidWebhook(Request $request, WebhookConfig $config);
}

创建自己的WebhookResponse后,您必须在webhook-client配置文件的webhook_response键中注册它。

处理多个应用的入站webhook请求

这个包允许从多个不同的应用接收webhook。让我们看看一个示例配置文件,我们在其中添加了对两个webhook URL的支持。为了简洁,所有配置中的注释都已删除。

return [
    'configs' => [
        [
            'name' => 'webhook-sending-app-1',
            'signing_secret' => 'secret-for-webhook-sending-app-1',
            'signature_header_name' => 'Signature-for-app-1',
            'signature_validator' => \Spatie\WebhookClient\SignatureValidator\DefaultSignatureValidator::class,
            'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,
            'webhook_response' => \Spatie\WebhookClient\WebhookResponse\DefaultRespondsTo::class,
            'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,
            'process_webhook_job' => '',
        ],
        [
            'name' => 'webhook-sending-app-2',
            'signing_secret' => 'secret-for-webhook-sending-app-2',
            'signature_header_name' => 'Signature-for-app-2',
            'signature_validator' => \Spatie\WebhookClient\SignatureValidator\DefaultSignatureValidator::class,
            'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,
            'webhook_response' => \Spatie\WebhookClient\WebhookResponse\DefaultRespondsTo::class,
            'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,
            'process_webhook_job' => '',
        ],
    ],
];

在为包注册路由时,您应该将配置的name作为第二个参数传递。

Route::webhooks('receiving-url-for-app-1', 'webhook-sending-app-1');
Route::webhooks('receiving-url-for-app-2', 'webhook-sending-app-2');

更改路由方法

作为一个入站webhook客户端,有些时候您可能想设置默认的post方法以外的路由方法。您可以将标准post方法更改为如getputpatchdelete等。

Route::webhooks('receiving-url-for-app-1', 'webhook-sending-app-1', 'get');
Route::webhooks('receiving-url-for-app-1', 'webhook-sending-app-1', 'put');
Route::webhooks('receiving-url-for-app-1', 'webhook-sending-app-1', 'patch');
Route::webhooks('receiving-url-for-app-1', 'webhook-sending-app-1', 'delete');

在不使用控制器的情况下使用包

如果您不想使用宏提供的路由和控制器,您可以程序化地向自己的控制器添加对webhook的支持。

Spatie\WebhookClient\WebhookProcessor是一个类,它验证签名、调用web配置、存储webhook请求,并启动一个队列作业来处理存储的webhook请求。该包提供的控制器也使用这个类内部使用

它可以这样使用

$webhookConfig = new \Spatie\WebhookClient\WebhookConfig([
    'name' => 'webhook-sending-app-1',
    'signing_secret' => 'secret-for-webhook-sending-app-1',
    'signature_header_name' => 'Signature',
    'signature_validator' => \Spatie\WebhookClient\SignatureValidator\DefaultSignatureValidator::class,
    'webhook_profile' => \Spatie\WebhookClient\WebhookProfile\ProcessEverythingWebhookProfile::class,
    'webhook_response' => \Spatie\WebhookClient\WebhookResponse\DefaultRespondsTo::class,
    'webhook_model' => \Spatie\WebhookClient\Models\WebhookCall::class,
    'process_webhook_job' => '',
]);

(new \Spatie\WebhookClient\WebhookProcessor($request, $webhookConfig))->process();

删除模型

每当有webhook到来时,这个包都会将其存储为WebhookCall模型。过一段时间后,您可能想删除旧模型。

WebhookCall模型应用了Laravel的MassPrunable特质。您可以在webhooks配置文件中自定义截止日期。

在这个例子中,所有模型将在超过30天后被删除。

return [
    'configs' => [
        // ...
    ],

    'delete_after_days' => 30,
];

配置模型后,您应该在应用程序的route/console.php中安排执行model:prune Artisan命令。不要忘记明确提及WebhookCall类。您可以自由选择此命令应该运行的适当间隔。

use Illuminate\Support\Facades\Schedule;
use Spatie\WebhookClient\Models\WebhookCall;

Schedule::command('model:prune', [
    '--model' => [WebhookCall::class],
])->daily();

// This will not work, as models in a package are not used by default
// Schedule::command('model:prune')->daily();

测试

composer test

变更日志

有关最近更改的更多信息,请参阅变更日志

贡献

请参阅CONTRIBUTING以获取详细信息。

安全性

如果您发现任何安全相关的问题,请发送电子邮件至freek@spatie.be,而不是使用问题跟踪器。

明信片软件

您可以使用此软件包,但如果它进入了您的生产环境,我们非常感激您从您的家乡给我们寄一张明信片,并说明您正在使用我们的哪个软件包。

我们的地址是:Spatie,Kruikstraat 22,2018 安特卫普,比利时。

我们将在公司的网站上发布所有收到的明信片

致谢

许可证

MIT 许可证(MIT)。有关更多信息,请参阅许可证文件