vanthao03596/laravel-paddle-webhooks

在 Laravel 应用中处理 paddle webhooks

1.0.0 2021-08-19 16:45 UTC

This package is auto-updated.

Last update: 2024-09-20 00:17:04 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Paddle 可以通过 webhooks 通知您的应用事件。此包可以帮助您处理这些 webhooks。默认情况下,它将验证所有传入请求的 Paddle 签名。所有有效的调用都将记录到数据库中。您可以轻松定义当特定事件触发您的应用时应调度的作业或事件。

此包不会处理在验证 webhook 请求后以及正确调用作业或事件后应该做什么。您仍然需要自己编写任何工作(例如,关于支付的工作)的代码。

强烈建议在使用此包之前阅读 Paddle 上的关于 webhooks 的完整文档

安装

您可以通过 composer 安装此包

composer require vanthao03596/laravel-paddle-webhooks

服务提供器将自动注册自身。

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

php artisan vendor:publish --provider="Vanthao03596\PaddleWebhooks\PaddleWebhooksServiceProvider" --tag="config"

这是将要发布到 config/paddle-webhooks.php 的配置文件内容

这是已发布配置文件的内容

return [
    /*
     * Paddle will sign each webhook using a public key to create signature . You can find the used public key at the
     * webhook configuration settings: https://vendors.paddle.com/public-key.
     */
    'signing_secret' => env('PADDLE_PUBLIC_KEY'),

    /*
     * You can define the job that should be run when a certain webhook hits your application
     * here. The key is the name of the Paddle event type.
     *
     * You can find a list of Paddle webhook types here:
     * https://developer.paddle.com/webhook-reference/intro.
     */
    'jobs' => [
        // 'subscription_created' => \App\Jobs\PaddleWebhooks\HandleSubscriptionCreated::class,
        // 'payment_succeeded' => \App\Jobs\PaddleWebhooks\HandlePaymentSucceeded::class,
    ],

    /*
     * The classname of the model to be used. The class should equal or extend
     * Vanthao03596\PaddleWebhooks\ProcessPaddleWebhookJob.
     */
    'model' => \Vanthao03596\PaddleWebhooks\ProcessPaddleWebhookJob::class,

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

    /*
     * When disabled, the package will not verify if the signature is valid.
     * This can be handy in local environments.
     */
    'verify_signature' => env('PADDLE_SIGNATURE_VERIFY', true),
];

接下来,您必须使用以下命令发布迁移

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

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

php artisan migrate

最后,注意路由:在 Paddle 控制台,您必须配置 Paddle webhooks 应该击中您的应用的 URL。在您的应用的 routes 文件中,您必须将此路由传递给 Route::paddleWebhooks

Route::paddleWebhooks('webhook-route-configured-at-the-paddle-dashboard');

幕后,这将在此包提供的控制器上注册一个 POST 路由。因为 Paddle 没有获取 csrf-token 的方法,所以您必须将该路由添加到 VerifyCsrfToken 中间件的 except 数组中

protected $except = [
    'webhook-route-configured-at-the-paddle-dashboard',
];

用法

Paddle 会为几种事件类型发送 webhooks。您可以在 Paddle 文档中找到 事件类型的完整列表

Paddle 将为击中您的应用 webhook url 的所有请求签名。此包将自动验证签名是否有效。如果签名无效,则请求可能不是由 Paddle 发送的。

除非发生严重错误,否则此包将始终对 webhook 请求响应 200。发送 200 将防止 Paddle 重复发送相同的事件。所有带有有效签名的 webhook 请求都将记录在 webhook_calls 表中。该表有一个 payload 列,其中保存了传入 webhook 的整个有效负载。

如果签名无效,则请求将不会记录在 webhook_calls 表中,但会抛出一个 Vanthao03596\PaddleWebhooks\Exceptions\WebhookFailed 异常。如果在 webhook 请求过程中发生错误,则抛出的异常将保存在 exception 列中。在这种情况下,控制器将发送 500 而不是 200

此包提供两种处理 webhook 请求的方式:您可以选择排队一个作业或监听包将触发的事件。

使用作业处理 webhook 请求

如果您想在特定事件类型到来时执行某些操作,可以定义一个执行该工作的作业。以下是一个此类作业的示例

<?php

namespace App\Jobs\PaddleWebhooks;

use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Spatie\WebhookClient\Models\WebhookCall;

class HandleChargeableSource implements ShouldQueue
{
    use InteractsWithQueue, Queueable, SerializesModels;

    /** @var \Spatie\WebhookClient\Models\WebhookCall */
    public $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请求的响应时间。这允许您处理更多的Paddle webhook请求并避免超时。

创建作业后,您必须在paddle-webhooks.php配置文件的jobs数组中注册它。键应该是Paddle事件类型的名称,其中,只有履行webhook将返回履行

// config/paddle-webhooks.php

'jobs' => [
    'subscription_created' => \App\Jobs\PaddleWebhooks\HandleSubscriptionCreated::class
],

使用事件处理webhook请求

您可以选择监听此包将触发的事件,而不是在webhook请求到来时排队作业以执行某些工作。每当有效的请求击中您的应用程序时,该包将触发一个paddle-webhooks::<事件名称>事件。

事件的负载将是为传入请求创建的WebhookCall实例。

让我们看看如何监听此类事件。在EventServiceProvider中,您可以注册监听器。

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'paddle-webhooks::subscription_created' => [
        App\Listeners\ChargeSource::class,
    ],
];

以下是一个此类监听器的示例

<?php

namespace App\Listeners;

use Illuminate\Contracts\Queue\ShouldQueue;
use Spatie\WebhookClient\Models\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请求的响应时间。这允许您处理更多的Paddle webhook请求并避免超时。

上述示例只是Laravel中处理事件的一种方式。要了解其他选项,请阅读Laravel处理事件的文档

高级用法

重试处理webhook

所有传入的webhook请求都写入数据库。当处理webhook调用时出现问题时,这一点非常有价值。您可以在调查并修复失败原因后轻松重试处理webhook调用,如下所示

use Spatie\WebhookClient\Models\WebhookCall;
use Spatie\PaddleWebhooks\ProcessPaddleWebhookJob;

dispatch(new ProcessPaddleWebhookJob(WebhookCall::find($id)));

执行自定义逻辑

您可以通过指定自己的模型来在paddle-webhooks配置文件的model键中添加一些自定义逻辑,这些逻辑应在排队的作业调度之前和/或之后执行。您可以通过指定自己的模型在paddle-webhooks配置文件的model键中这样做。该类应该扩展Spatie\PaddleWebhooks\ProcessPaddleWebhookJob

以下是一个示例

use Spatie\PaddleWebhooks\ProcessPaddleWebhookJob;

class MyCustomPaddleWebhookJob extends ProcessPaddleWebhookJob
{
    public function handle()
    {
        // do some custom stuff beforehand

        parent::handle();

        // do some custom stuff afterwards
    }
}

确定是否应处理请求

您可以使用自己的逻辑来确定是否应处理请求。您可以通过指定自己的配置文件在paddle-webhooks配置文件的profile键中这样做。该类应实现Spatie\WebhookClient\WebhookProfile\WebhookProfile

Paddle有时可能会发送一个webhook请求超过一次。在这个例子中,我们将确保只有在请求之前未处理的情况下才处理请求。

use Illuminate\Http\Request;
use Spatie\WebhookClient\Models\WebhookCall;
use Spatie\WebhookClient\WebhookProfile\WebhookProfile;

class PaddleWebhookProfile implements WebhookProfile
{
    public function shouldProcess(Request $request): bool
    {
        return ! WebhookCall::where('payload->id', $request->get('id'))->exists();
    }
}

处理多个签名密钥

您可能希望包处理多个端点和密钥。以下是配置该行为的方法。

如果您正在使用Route::paddleWebhooks宏,您可以按如下方式附加configKey

Route::paddleWebhooks('webhook-url/{configKey}');

或者,如果您正在手动定义路由,您可以像这样添加configKey

Route::post('webhook-url/{configKey}', '\Vanthao03596\PaddleWebhooks\PaddleWebhooksController');

如果此路由参数存在,verify中间件将使用不同的配置密钥查找密钥,即将给定的参数值附加到默认配置密钥上。例如,如果Paddle将请求发送到webhook-url/my-named-secret,则添加一个名为signing_secret_my-named-secret的新配置。

Connect的示例配置可能如下所示

// secret for when Paddle posts to webhook-url/account
'signing_secret_account' => 'whsec_abc',
// secret for when Paddle posts to webhook-url/connect
'signing_secret_connect' => 'whsec_123',

测试

composer test

变更日志

请参阅CHANGELOG以了解最近的变化。

贡献

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

安全漏洞

请参阅我们的安全策略,了解如何报告安全漏洞。

致谢

许可证

MIT 许可证(MIT)。请参阅许可证文件以获取更多信息。