wayofdev / laravel-stripe-webhooks
使用 Cycle-ORM 支持在 Laravel 应用中处理 Stripe webhooks。
Requires
- php: ^8.2
- cycle/database: ^2.8
- cycle/orm: ^2.7
- laravel/framework: ^v10.46
- stripe/stripe-php: ^14.0
- wayofdev/laravel-webhook-client: ^1.3
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
- v2.1.47
- v2.1.46
- v2.1.45
- v2.1.44
- v2.1.43
- v2.1.42
- v2.1.41
- v2.1.40
- v2.1.39
- v2.1.38
- v2.1.37
- v2.1.36
- v2.1.35
- v2.1.34
- v2.1.33
- v2.1.32
- v2.1.31
- v2.1.30
- v2.1.29
- v2.1.28
- v2.1.27
- v2.1.26
- v2.1.25
- v2.1.24
- v2.1.23
- v2.1.22
- v2.1.21
- v2.1.20
- v2.1.19
- v2.1.18
- v2.1.17
- v2.1.16
- v2.1.15
- v2.1.14
- v2.1.13
- v2.1.12
- v2.1.11
- v2.1.10
- v2.1.9
- v2.1.8
- v2.1.7
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.0
- v1.1.94
- v1.1.93
- v1.1.92
- v1.1.91
- v1.1.90
- v1.1.89
- 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.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-renovate/phpstan-packages
- 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/stripe-stripe-php-14.x-lockfile
- dev-renovate/lock-file-maintenance
- dev-renovate/laravel-framework-11.x
- dev-renovate/phpunit-phpunit-11.x
- dev-renovate/orchestra-testbench-9.x
- dev-renovate/wayofdev-laravel-webhook-client-1.x-lockfile
- dev-codesee-arch-diagram-workflow-1691510819028
This package is auto-updated.
Last update: 2024-09-20 16:31:47 UTC
README


使用 Cycle-ORM 集成在 Laravel 应用中处理 Stripe Webhooks
Stripe 可以通过 webhooks 通知应用程序各种事件。此包简化了处理这些 webhooks 的过程。默认情况下,它会验证所有传入请求的 Stripe 签名。
验证后,所有有效的 webhook 调用都将使用 Cycle-ORM 记录到数据库中。您可以在接收到特定事件时轻松定义要分发的作业或事件。
请注意,此包仅管理初始 webhook 请求验证和相应作业或事件的分发。
后续操作(例如,有关支付的操作)应由开发者单独实现。在深入了解此包之前,强烈建议您熟悉 Stripe 关于 webhooks 的全面文档。
如果您 喜欢/使用 此包,请考虑 星标 它。谢谢!
💿 安装
→ 使用 Composer
作为依赖项要求
$ composer req wayofdev/laravel-stripe-webhooks
服务提供程序将自动注册自身。
→ 配置包
您必须使用以下命令发布配置文件
$ php artisan vendor:publish \ --provider="WayOfDev\StripeWebhooks\Bridge\Laravel\Providers\StripeWebhooksServiceProvider" \ --tag="config"
这是将发布到 config/stripe-webhooks.php
的配置文件内容
<?php declare(strict_types=1); use WayOfDev\StripeWebhooks\Profile\StripeWebhookProfile; use WayOfDev\WebhookClient\Entities\WebhookCall; use WayOfDev\WebhookClient\Persistence\ORMWebhookCallRepository; return [ /* * Stripe will sign each webhook using a secret. You can find the used secret at the * webhook configuration settings: https://dashboard.stripe.com/account/webhooks. */ 'signing_secret' => env('STRIPE_WEBHOOK_SECRET'), /* * You can define a default job that should be run for all other Stripe event type * without a job defined in next configuration. * You may leave it empty to store the job in database but without processing it. */ 'default_job' => '', /* * You can define the job that should be run when a certain webhook hits your application * here. The key is the name of the Stripe event type with the `.` replaced by a `_`. * * You can find a list of Stripe webhook types here: * https://stripe.com/docs/api#event_types. */ 'jobs' => [ // 'source_chargeable' => \App\Jobs\StripeWebhooks\HandleChargeableSource::class, // 'charge_failed' => \App\Jobs\StripeWebhooks\HandleFailedCharge::class, ], /* * The classname of the entity to be used to store webhook calls. The class should * be equal or extend WayOfDev\WebhookClient\Entities\WebhookCall. */ 'entity' => WebhookCall::class, /* * The classname of the repository to be used to store webhook calls. The class should * implement WayOfDev\WebhookClient\Contracts\WebhookCallRepository. */ 'entity_repository' => ORMWebhookCallRepository::class, /* * This class determines if the webhook call should be stored and processed. */ 'profile' => StripeWebhookProfile::class, /* * Specify a connection and or a queue to process the webhooks */ 'connection' => env('STRIPE_WEBHOOK_CONNECTION'), 'queue' => env('STRIPE_WEBHOOK_QUEUE'), /* * When disabled, the package will not verify if the signature is valid. * This can be handy in local environments. */ 'verify_signature' => env('STRIPE_SIGNATURE_VERIFY', true), ];
在配置文件的 signing_secret
键中,您应添加一个有效的 webhook 密钥。您可以在 Stripe 控制面板上的 webhook 配置设置 中找到该密钥。
→ 准备数据库
默认情况下,所有 webhook 调用都将保存到数据库中。
要创建存储 webhook 调用的表
-
请确保您已经在您的 Laravel 项目中设置并运行了 wayofdev/laravel-cycle-orm-adapter 包。
-
修改
cycle.php
配置以将WebhookCall
实体包含在搜索路径中// ... 'tokenizer' => [ /* * Directories to 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 路由
在 Stripe 控制面板 上,指定 Stripe 应发送 webhook 请求的 URL。在应用程序的路由文件中,使用 Route::stripeWebhooks
映射此 URL
Route::stripeWebhooks('webhook-route-configured-at-the-stripe-dashboard');
内部,此命令注册了一个由此包提供的控制器的 POST
路由。由于 Stripe 无法检索 csrf-token,请排除此路由的 VerifyCsrfToken
中间件
protected $except = [ 'webhook-route-configured-at-the-stripe-dashboard', ];
💻 使用
Stripe 为各种事件类型分发了 webhook。查看 Stripe 官方文档中的 完整事件类型列表。
Stripe将对访问您的应用程序webhook URL的所有请求进行签名。此包将自动验证签名是否有效。如果签名无效,则请求可能不是由Stripe发送的。
除非出现严重错误,否则此包将始终以200
响应webhook请求。发送200
将防止Stripe反复重新发送相同的事件。Stripe可能会偶尔发送重复的webhook请求多次。此包确保每个请求只处理一次。所有带有有效签名的webhook请求都将记录在webhook_calls
表中。该表有一个payload
列,其中保存了传入webhook的整个负载。
如果签名无效,则包不会记录请求,但会抛出WayOfDev\StripeWebhooks\Exceptions\WebhookFailed
异常。在webhook调用过程中发生的任何错误都将记录在exception
列中。如果有错误,将发送500
响应,否则发送200
响应。
您可以使用此包以两种方式处理webhook请求:排队作业或监听包的事件。
→ 使用作业处理Webhook请求
要接收特定事件类型的操作,请定义一个作业。以下是一个作业示例
<?php declare(strict_types=1); namespace Infrastructure\Stripe\Webhooks\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use WayOfDev\WebhookClient\Entities\WebhookCall; class HandleChargeableSource implements ShouldQueue { use InteractsWithQueue, Queueable, SerializesModels; public WebhookCall $webhookCall; public function __construct(WebhookCall $webhookCall) { $this->webhookCall = $webhookCall; } public function handle() { // do your work here // you can access the payload of the webhook call with `$this->webhookCall->payload()` } }
为确保对webhook请求的及时响应,请考虑将作业设置为可排队。这允许高效地处理多个Stripe webhook请求,降低超时的可能性。
创建作业后,在stripe-webhooks.php
配置文件的jobs
数组中注册它。键应该是Stripe事件类型的名称,但将.
替换为_
。值应该是完全限定的类名。
// config/stripe-webhooks.php 'jobs' => [ 'source_chargeable' => \Infrastructure\Stripe\Webhooks\Jobs\HandleChargeableSource::class, ], // ...
如果您想将一个作业配置为默认处理所有未定义的事件,您可以在stripe-webhooks.php
配置文件中将作业设置为default_job
。值应该是完全限定的类名。
默认情况下,配置为空字符串''
,这只会将事件存储在数据库中,但不会处理。
// config/stripe-webhooks.php 'default_job' => \Infrastructure\Stripe\Webhooks\Jobs\HandleOtherEvent::class, // ...
→ 使用事件处理Webhook请求
您可以选择监听此包将触发的事件,而不是排队作业以在收到webhook请求时执行某些工作。每当有效的请求击中您的应用程序时,该包将触发一个stripe-webhooks::<event-name>
事件。
事件的负载将是为传入请求创建的WebhookCall
实例。
让我们看看如何监听此类事件。在EventServiceProvider
中,您可以注册监听器。
/** * The event listener mappings for the application. * * @var array */ protected $listen = [ 'stripe-webhooks::source.chargeable' => [ Infrastructure\Stripe\Listeners\ChargeSource::class, ], ];
以下是一个此类监听器的示例
<?php namespace Infrastructure\Stripe\Listeners; use Illuminate\Contracts\Queue\ShouldQueue; use WayOfDev\WebhookClient\Entities\WebhookCall; class ChargeSource implements ShouldQueue { public function handle(WebhookCall $webhookCall) { // do your work here // you can access the payload of the webhook call with `$webhookCall->payload()` } }
我们强烈建议您将事件监听器设置为可排队,因为这将最小化webhook请求的响应时间。这允许您处理更多的Stripe webhook请求并避免超时。
有关在Laravel中处理事件的其它方法的更多信息,请查看Laravel官方关于事件处理的文档。
⚙️ 高级使用
→ 重试处理Webhook
所有传入的webhook请求都写入数据库。当处理webhook调用时出现问题时,这非常有价值。您可以在调查并修复失败原因后轻松地重试处理webhook调用,如下所示
use WayOfDev\WebhookClient\Contracts\WebhookCallRepository; use WayOfDev\StripeWebhooks\Bridge\Laravel\Jobs\ProcessStripeWebhookJob; class RetryWebhooks { public function __construct(private WebhookCallRepository $repository) { } public function handle() { dispatch(new ProcessStripeWebhookJob($repository->findById($id))); } }
→ 执行自定义逻辑
您可以通过在stripe-webhooks
配置文件的entity
键中指定自己的实体来添加一些应在排队作业调度之前和/或之后执行的自定义逻辑。您可以通过指定自己的实体在stripe-webhooks
配置文件中的entity
键来完成此操作。该类应扩展WayOfDev\StripeWebhooks\Bridge\Laravel\Jobs\ProcessStripeWebhookJob
。
以下是一个示例
use WayOfDev\StripeWebhooks\Bridge\Laravel\Jobs\ProcessStripeWebhookJob; class MyCustomStripeWebhookJob extends ProcessStripeWebhookJob { public function handle(): void { // do some custom stuff beforehand parent::handle(); // do some custom stuff afterwards } }
→ 确定是否应处理请求
您可以自行编写逻辑来判断是否处理请求。您可以通过在 stripe-webhooks
配置文件中的 profile
键中指定自己的配置来实现。该类应实现 WayOfDev\WebhookClient\Contracts\WebhookProfile
接口。
在本例中,我们将确保仅处理尚未处理过的请求。
<?php declare(strict_types=1); namespace WayOfDev\StripeWebhooks\Profile; use Cycle\Database\Injection\Parameter; use Cycle\ORM\ORMInterface; use Illuminate\Http\Request; use WayOfDev\WebhookClient\Contracts\WebhookProfile; use WayOfDev\WebhookClient\Entities\WebhookCall; use WayOfDev\WebhookClient\Persistence\ORMWebhookCallRepository; class StripeWebhookProfile implements WebhookProfile { public function __construct(private readonly ORMInterface $orm) { } public function shouldProcess(Request $request): bool { /** @var ORMWebhookCallRepository $webhookCallsRepository */ $webhookCallsRepository = $this->orm->getRepository(WebhookCall::class); $exists = $webhookCallsRepository ->select() ->where(['name' => 'stripe']) ->andWhere("JSON_EXTRACT(payload, '$.id')", '=', new Parameter(['payloadId' => $request->get('id')])) ->count(); return 0 === $exists; } }
→ 处理多个签名密钥
当使用 Stripe Connect 时,您可能希望包能够处理多个端点和密钥。以下是如何配置此行为。
如果您使用的是 Route::stripeWebhooks
宏,您可以按如下方式附加 configKey
Route::stripeWebhooks('webhook-url/{configKey}');
或者,如果您手动定义路由,您可以像这样添加 configKey
Route::post( 'webhook-url/{configKey}', \WayOfDev\StripeWebhooks\Bridge\Laravel\Http\Controllers\StripeWebhooksController::class, );
如果此路由参数存在,验证中间件将使用不同的配置键查找密钥,通过将给定的参数值附加到默认配置键。例如,如果 Stripe 将数据发送到 webhook-url/my-named-secret
,您将添加一个新的配置名为 signing_secret_my-named-secret
。
Connect 的示例配置可能如下所示
// secret for when Stripe posts to webhook-url/account 'signing_secret_account' => 'whsec_abc', // secret for when Stripe posts to webhook-url/connect 'signing_secret_connect' => 'whsec_123',
→ 将 Webhook 有效负载转换为 Stripe 对象
您可以将 Webhook 有效负载转换为 Stripe 对象,以便辅助访问其各种方法和属性。
为此,使用 Stripe\Event::constructFrom($payload)
方法,并传入 WebhookCall
的有效负载
use Stripe\Event; // ... public function handle(WebhookCall $webhookCall) { /** @var \Stripe\StripeObject|null */ $stripeObject = Event::constructFrom($webhookCall->payload())->data?->object; }
例如,如果您已为 invoice.created
事件设置 Stripe Webhook,则可以将有效负载转换为 StripeInvoice
对象
/** @var \Stripe\StripeInvoice|null */ $stripeInvoice = Event::constructFrom($webhookCall->payload())->data?->object; // $stripeInvoice->status // $stripeInvoice->amount_due // $stripeInvoice->amount_paid // $stripeInvoice->amount_remaining foreach ($stripeInvoice->lines as $invoiceLine) { // ... }
⚡️序列图
🧪 运行测试
→ PHPUnit 测试
要运行测试,请运行以下命令
$ make test
→ 静态分析
使用 PHPStan 进行代码质量分析
$ make lint-stan
→ 编码标准修复
使用 The PHP Coding Standards Fixer (PHP CS Fixer) 修复代码以遵循我们的标准
$ make lint-php
🤝 许可证
🧱 致谢和有用资源
此存储库基于 spatie/laravel-stripe-webhooks 的工作。
🙆♂️ 作者信息
由 lotyp / wayofdev 在 2023 创建
🙌 想要贡献?
感谢您考虑为 wayofdev 社区做出贡献!我们欢迎各种形式的贡献。如果您想
- 🤔 建议一个功能
- 🐛 报告一个问题
- 📖 改进文档
- 👨💻 为代码做出贡献