wayofdev / laravel-webhook-client
在 Laravel 应用中处理 Stripe webhook,支持 Cycle-ORM。
Requires
- php: ^8.2
- ext-pdo: *
- cycle/annotated: ^4.1
- cycle/database: ^2.8
- cycle/entity-behavior: ^1.3
- cycle/orm: ^2.7
- laravel/framework: ^v10.46
- symfony/http-foundation: ^6.4
- wayofdev/laravel-cycle-orm-adapter: ^4.7
Requires (Dev)
- ergebnis/composer-normalize: ^2.42
- larastan/larastan: ^2.9
- orchestra/testbench: ^8.21
- pestphp/pest: ^2.34
- pestphp/pest-plugin-laravel: ^2.3
- phpstan/extension-installer: ^1.3
- phpstan/phpstan: ^1.10
- phpstan/phpstan-deprecation-rules: ^1.1
- phpstan/phpstan-phpunit: ^1.3
- phpstan/phpstan-strict-rules: ^1.5
- phpunit/phpunit: ^10.5
- roave/security-advisories: dev-latest
- wayofdev/cs-fixer-config: ^1.2
- dev-master
- v1.3.22
- v1.3.21
- v1.3.20
- v1.3.19
- v1.3.18
- v1.3.17
- v1.3.16
- v1.3.15
- v1.3.14
- v1.3.13
- v1.3.12
- v1.3.11
- v1.3.10
- v1.3.9
- v1.3.8
- v1.3.7
- v1.3.6
- v1.3.5
- v1.3.4
- v1.3.3
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.19
- v1.2.18
- v1.2.17
- v1.2.16
- v1.2.15
- v1.2.14
- v1.2.13
- v1.2.12
- v1.2.11
- v1.2.10
- v1.2.9
- v1.2.8
- v1.2.7
- v1.2.6
- v1.2.5
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.88
- v1.1.87
- v1.1.86
- v1.1.85
- v1.1.84
- v1.1.83
- v1.1.82
- v1.1.81
- v1.1.80
- v1.1.79
- v1.1.78
- v1.1.77
- v1.1.76
- v1.1.75
- v1.1.74
- v1.1.73
- v1.1.72
- v1.1.71
- v1.1.70
- v1.1.69
- v1.1.68
- v1.1.67
- v1.1.66
- v1.1.65
- v1.1.64
- v1.1.63
- v1.1.62
- v1.1.61
- v1.1.60
- v1.1.59
- v1.1.58
- v1.1.57
- v1.1.56
- v1.1.55
- v1.1.54
- v1.1.53
- v1.1.52
- v1.1.51
- v1.1.50
- v1.1.49
- v1.1.48
- v1.1.47
- v1.1.46
- v1.1.45
- v1.1.44
- v1.1.43
- v1.1.42
- v1.1.41
- v1.1.40
- v1.1.39
- v1.1.38
- v1.1.37
- v1.1.36
- v1.1.35
- v1.1.34
- v1.1.33
- v1.1.32
- v1.1.31
- v1.1.30
- v1.1.29
- v1.1.28
- v1.1.27
- v1.1.26
- v1.1.25
- v1.1.24
- v1.1.23
- v1.1.22
- v1.1.21
- v1.1.20
- v1.1.19
- v1.1.18
- v1.1.17
- v1.1.16
- v1.1.15
- v1.1.14
- v1.1.13
- v1.1.12
- v1.1.11
- v1.1.10
- v1.1.9
- v1.1.8
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.16
- v1.0.15
- v1.0.14
- v1.0.13
- v1.0.12
- v1.0.11
- v1.0.10
- v1.0.9
- v1.0.8
- v1.0.7
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-renovate/phpstan-packages
- dev-renovate/laravel-framework-10.x-lockfile
- dev-renovate/cycle-orm-2.x-lockfile
- dev-renovate/orchestra-testbench-8.x-lockfile
- dev-renovate/wayofdev-cs-fixer-config-1.x-lockfile
- dev-renovate/lock-file-maintenance
- dev-renovate/major-symfony
- dev-renovate/laravel-framework-11.x
- dev-renovate/phpunit-phpunit-11.x
- dev-renovate/orchestra-testbench-9.x
- dev-codesee-arch-diagram-workflow-1691489282296
This package is auto-updated.
Last update: 2024-09-20 14:29:46 UTC
README


在 Laravel 应用中接收 webhook
Webhook 提供了一种机制,允许一个应用程序通知另一个应用程序关于特定事件,通常使用简单的 HTTP 请求。
由 wayofdev/laravel-webhook-client 包促进 Laravel 应用中 webhook 的接收,利用 cycle-orm 的力量。功能包括验证签名调用、存储有效负载数据和在队列作业中处理有效负载。
此包受 spatie/laravel-webhook-client 的启发并重新编写,以支持 Cycle-ORM。
💿 安装
→ 使用 composer
作为依赖项要求
$ composer req wayofdev/laravel-webhook-client
→ 配置包
您可以使用以下命令发布配置文件
php artisan vendor:publish \ --provider="WayOfDev\WebhookClient\Bridge\Laravel\Providers\WebhookClientServiceProvider" \ --tag="config"
这是将发布到 config/webhook-client.php
的文件内容
<?php use WayOfDev\WebhookClient\Entities\WebhookCall; use WayOfDev\WebhookClient\Persistence\ORMWebhookCallRepository; use WayOfDev\WebhookClient\Profile\ProcessEverythingWebhookProfile; use WayOfDev\WebhookClient\Response\DefaultRespondsTo; use WayOfDev\WebhookClient\SignatureValidator\DefaultSignatureValidator; 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 \WayOfDev\WebhookClient\Contracts\SignatureValidator */ 'signature_validator' => DefaultSignatureValidator::class, /* * This class determines if the webhook call should be stored and processed. */ 'webhook_profile' => ProcessEverythingWebhookProfile::class, /* * This class determines the response on a valid webhook call. */ 'webhook_response' => DefaultRespondsTo::class, /* * The classname of the entity to be used to store webhook calls. The class should * be equal or extend WayOfDev\WebhookClient\Entities\WebhookCall. */ 'webhook_entity' => WebhookCall::class, /* * The classname of the repository to be used to store webhook calls. The class should * implement WayOfDev\WebhookClient\Contracts\WebhookCallRepository. */ 'webhook_entity_repository' => ORMWebhookCallRepository::class, /* * In this array, you can pass the headers that should be stored on * the webhook call entity 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 \WayOfDev\WebhookClient\Jobs\ProcessWebhookJob. */ 'process_webhook_job' => '', ], ], /* * The integer amount of days after which database records should be deleted. * * 7 deletes all records after 1 week. Set to null if no database records should be deleted. */ 'delete_after_days' => 30, ];
在配置文件的 signing_secret
键中,您应该添加一个有效的 webhook 密钥。此值应由发送 webhook 的应用程序提供。
此包将尽可能快地存储和响应 webhook。请求的有效负载处理是通过队列作业完成的。建议不要使用 sync
驱动器,而使用真实的队列驱动器。您应该在配置文件的 process_webhook_job
中指定将处理 webhook 请求的作业。任何扩展 WayOfDev\WebhookClient\Bridge\Laravel\Jobs\ProcessWebhookJob
并具有 handle
方法的有效类都是有效的作业。
→ 准备数据库
默认情况下,所有 webhook 调用都将保存到数据库中。
要创建包含 webhook 调用的表
-
您必须在您的 Laravel 项目中配置并运行 wayofdev/laravel-cycle-orm-adapter 包。
-
编辑
cycle.php
配置以将 WebhookCall 实体添加到搜索路径// ... 'tokenizer' => [ /* * Where should class locator scan for entities? */ 'directories' => [ __DIR__ . '/../src/Domain', // Your current project Entities __DIR__ . '/../vendor/wayofdev/laravel-webhook-client/src/Entities', // Register new Entity ], // ... ],
-
编辑配置后,运行命令以从新出现的实体生成新的迁移
$ php artisan cycle:orm:migrate
(可选) 查看要执行的迁移列表
$ php artisan cycle:migrate:status
-
使用以下命令运行悬而未决的迁移
$ php artisan cycle:migrate
→ 注意路由
最后,让我们处理路由。在发送 webhook 的应用程序中,您可能已经配置了一个您希望 webhook 请求发送到的 URL。在您的应用程序的路由文件中,您必须将此路由传递给 Route::webhooks
。以下是一个示例
Route::webhooks('webhook-receiving-url');
在幕后,默认情况下这将注册一个到由此包提供的控制器的 POST
路由。因为发送 webhook 到您的应用程序的应用程序无法获取 csrf-token,您必须将此路由添加到 VerifyCsrfToken
中间件的 except
数组。
protected $except = [ 'webhook-receiving-url', ];
💻 使用
完成安装后,以下是该包功能的一个全面概述
- 签名验证
- 该包首先验证传入请求的签名。
- 如果签名未通过验证,则会抛出异常,触发
InvalidSignatureEvent
事件,并且请求不会被保存到数据库。
- Webhook 配置评估
- 每个入站请求都与一个webhook配置文件交互,这个配置文件本质上是一个类,用于评估请求是否应该在您的应用程序中保存和处理。
- 此配置文件可以根据应用程序的要求过滤特定的webhook请求。
- 您可以根据需要创建自己的自定义webhook配置文件,以更改或扩展此逻辑。您的自定义webhook配置文件。
- 存储与处理
- 如果配置文件允许,则请求首先被保存在
webhook_calls
表中。 - 随后,一个排队的工作处理
WebhookCall
实体。 - Webhooks通常期望快速响应,因此通过排队作业,我们可以快速响应。
- 处理webhook作业的配置位于
webhook-client
配置文件中的process_webhook_job
下。 - 如果在作业排队过程中出现任何问题,该包将在
WebhookCall
实体的exception
字段中记录异常。
- 如果配置文件允许,则请求首先被保存在
- Webhook响应
- 一旦作业被分发,webhook响应就负责。此类确定请求的HTTP响应。
- 默认情况下,返回带有'ok'消息的
200
状态码。但是,您也可以自定义webhook响应。了解如何轻松创建自己的webhook响应。
→ 验证入站webhook的签名
此包假设入站webhook请求有一个可以用来验证有效负载未被篡改的头部。包含签名的头部的名称可以在配置文件的signature_header_name
键中进行配置。默认情况下,该包使用DefaultSignatureValidator
来验证签名。这是该类将如何计算签名的。
$computedSignature = hash_hmac( 'sha256', $request->getContent(), $configuredSigningSecret );
如果$computedSignature
与值匹配,则请求将被传递给webhook配置文件。如果$computedSignature
与签名头部中的值不匹配,则该包将响应500
并丢弃请求。
→ 创建自己的签名验证器
签名验证器是实现WayOfDev\WebhookClient\Contracts\SignatureValidator
的任何类。下面是这个接口的样子。
<?php declare(strict_types=1); namespace WayOfDev\WebhookClient\Contracts; use Illuminate\Http\Request; use WayOfDev\WebhookClient\Config; interface SignatureValidator { public function isValid(Request $request, Config $config): bool; }
WebhookConfig
是一个数据传输对象,它允许您轻松检索webhook请求的配置(包含包含签名的头部名称和密钥)。
在创建自己的SignatureValidator
之后,您必须在webhook-client
配置文件中的signature_validator
中注册它。
→ 确定哪些webhook请求应该被存储和处理
在验证入站webhook请求的签名后,请求将被传递给webhook配置文件。webhook配置文件是一个类,用于确定请求是否应该被存储和处理。如果发送webhook的应用程序发送了您的应用程序不感兴趣的需求,则可以使用此类过滤出此类事件。
默认情况下,使用\WayOfDev\WebhookClient\Profile\ProcessEverythingWebhookProfile
类。正如其名称所暗示的,这个默认类将确定所有入站请求都应该被存储和处理。
→ 创建自己的webhook配置文件
webhook配置文件是实现\WayOfDev\WebhookClient\Contracts\WebhookProfile
的任何类。下面是这个接口的样子。
<?php declare(strict_types=1); namespace WayOfDev\WebhookClient\Contracts; use Illuminate\Http\Request; interface WebhookProfile { public function shouldProcess(Request $request): bool; }
在创建自己的WebhookProfile
之后,您必须在webhook-client
配置文件中的webhook_profile
键中注册它。
→ 存储和处理webhook
在验证签名并且webhook配置文件确定请求应该被处理之后,该包将存储并处理请求。
请求首先将被存储在webhook_calls
表中,涉及WebhookCall
实体和WebhookCallRepository
。
如果您想自定义表名或存储行为中的任何内容,该包提供了灵活性,可以使用替代实体。这可以通过在 webhook_entity
中设置所需的实体来实现。
请确保您的实体继承自 WayOfDev\WebhookClient\Entities\WebhookCall
。为了存储目的,WebhookCallRepository
接口及其实现 ORMWebhookCallRepository
都会发挥作用。可以通过 webhook_entity_repository
来修改默认存储库。
您可以通过覆盖 ORMWebhookCallRepository
的 store
方法来更改 webhook 的存储方式。在 store
方法中,您应该返回持久化实体。
接下来,新创建的 WebhookCall
实体将被传递给一个队列作业,该作业将处理请求。任何扩展 \WayOfDev\WebhookClient\Bridge\Laravel\Jobs\ProcessWebhookJob
的类都是一个有效的作业。以下是一个示例
<?php declare(strict_types=1); namespace Infrastructure\Jobs; use WayOfDev\WebhookClient\Bridge\Laravel\Jobs\ProcessWebhookJob as AbstractProcessWebhookJob; class ProcessWebhookJob extends AbstractProcessWebhookJob { public function handle() { // $this->webhookCall // contains an instance of `WebhookCall` // perform the work here } }
您应该在 webhook-client
配置文件的 process_webhook_job
中指定您的作业类的名称。
→ 创建自己的 webhook 响应
webhook 响应是任何实现了 \WayOfDev\WebhookClient\Contracts\RespondsToWebhook
接口的类。以下是该接口的示例
<?php declare(strict_types=1); namespace WayOfDev\WebhookClient\Contracts; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; use WayOfDev\WebhookClient\Config; interface RespondsToWebhook { public function respondToValidWebhook(Request $request, Config $config): Response; }
创建自己的 WebhookResponse
后,您必须在 webhook-client
配置文件的 webhook_response
键中注册它。
→ 处理多个应用的 incoming webhook 请求
该包允许从多个不同的应用接收 webhook。让我们看看一个示例配置文件,其中我们添加了对两个 webhook URL 的支持。为了简洁起见,所有配置中的注释都已删除。
<?php declare(strict_types=1); use WayOfDev\WebhookClient\Entities\WebhookCall; use WayOfDev\WebhookClient\Persistence\ORMWebhookCallRepository; use WayOfDev\WebhookClient\Profile\ProcessEverythingWebhookProfile; use WayOfDev\WebhookClient\Response\DefaultRespondsTo; use WayOfDev\WebhookClient\SignatureValidator\DefaultSignatureValidator; return [ 'configs' => [ [ 'name' => 'webhook-sending-app-1', 'signing_secret' => 'secret-for-webhook-sending-app-1', 'signature_header_name' => 'Signature-for-app-1', 'signature_validator' => DefaultSignatureValidator::class, 'webhook_profile' => ProcessEverythingWebhookProfile::class, 'webhook_response' => DefaultRespondsTo::class, 'webhook_entity' => WebhookCall::class, 'webhook_entity_repository' => ORMWebhookCallRepository::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' => DefaultSignatureValidator::class, 'webhook_profile' => ProcessEverythingWebhookProfile::class, 'webhook_response' => DefaultRespondsTo::class, 'webhook_entity' => WebhookCall::class, 'webhook_entity_repository' => ORMWebhookCallRepository::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');
→ 修改路由方法
作为 incoming webhook 客户端,有时您可能想要使用除了默认的 post
之外的路线方法。您有灵活性,可以将标准 post 方法修改为 get
、put
、patch
或 delete
等方法。
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 的支持。
WayOfDev\WebhookClient\WebhookProcessor
是一个类,它验证签名,调用 web 配置文件,存储 webhook 请求,并启动一个队列作业以处理存储的 webhook 请求。该包提供的控制器也使用该类 内部。
它可以这样使用
use WayOfDev\WebhookClient\Entities\WebhookCall; use WayOfDev\WebhookClient\Persistence\ORMWebhookCallRepository; use WayOfDev\WebhookClient\Profile\ProcessEverythingWebhookProfile; use WayOfDev\WebhookClient\Response\DefaultRespondsTo; use WayOfDev\WebhookClient\SignatureValidator\DefaultSignatureValidator; use WayOfDev\WebhookClient\Config; use WayOfDev\WebhookClient\WebhookProcessor; $webhookConfig = new Config([ 'name' => 'webhook-sending-app-1', 'signing_secret' => 'secret-for-webhook-sending-app-1', 'signature_header_name' => 'Signature', 'signature_validator' => DefaultSignatureValidator::class, 'webhook_profile' => ProcessEverythingWebhookProfile::class, 'webhook_response' => DefaultRespondsTo::class, 'webhook_entity' => WebhookCall::class, 'webhook_entity_repository' => ORMWebhookCallRepository::class, 'process_webhook_job' => '', ]); (new WebhookProcessor($request, $webhookConfig))->process();
→ 删除实体
每当有 webhook 传入时,此包都会将其存储为 WebhookCall
实体。过一段时间后,您可能想要删除旧实体。
@todo Laravel 版本使用可大量删除的特质,因此,实体删除逻辑应使用 Laravel 控制台命令或通过提交到 cycle-orm 重新编写。
在此示例中,所有实体在 30 天后都将被删除。
return [ 'configs' => [ // ... ], 'delete_after_days' => 30, ];
🧪 运行测试
→ PHPUnit 测试
要运行测试,请运行以下命令
$ make test
→ 静态分析
使用 PHPStan 进行代码质量检查
$ make lint-stan
→ 代码规范修复
使用 The PHP Coding Standards Fixer (PHP CS Fixer) 修复代码以遵循我们的标准
$ make lint-php
🤝 许可证
🧱 贡献和有用资源
此存储库基于 spatie/laravel-webhook-client 的工作。
🙆🏼♂️ 作者信息
由 lotyp / wayofdev 创建于 2023
🙌 想要贡献?
感谢您考虑为wayofdev社区做出贡献!我们欢迎所有类型的贡献。如果您想
- 🤔 提出一个功能建议
- 🐛 报告一个问题
- 📖 改进文档
- 👨💻 为代码做出贡献