hotmeteor/receiver

Laravel的即插即用webhook处理库

资助包维护!
hotmeteor
Ko Fi

v0.3 2024-03-19 14:51 UTC

README

Receiver

Receiver

Receiver是一个为Laravel提供的即插即用webhook处理库。

Webhooks是任何API生命周期中的强大部分。《Receiver》旨在使在Laravel应用程序中处理传入的webhooks变得一致且简单。

默认情况下,Receiver内置了对以下内容的支持

当然,Receiver可以使用自定义提供者接收来自任何来源的webhooks。

Tests Latest Version on Packagist PHP from Packagist

目录

安装

需求

  • PHP ^8.1
  • Laravel 9+
composer require hotmeteor/receiver

可选

Stripe支持需要stripe/stripe-php

接收Webhooks

基础知识

Webhooks需要一个暴露的端点来POST到。Receiver旨在使这成为一个一次性的设置,支持任何传入的webhooks。

  1. 为预期的webhooks创建一个控制器和路由。
  2. 接收webhook并按需处理它
    <?php
    
    namespace App\Http\Controllers\Webhooks;
    
    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    
    class WebhooksController extends Controller
    {
       public function store(Request $request)
       {
           return Receiver::driver('slack')
               ->receive($request)
               ->ok();
       }
    }

所使用的方法很简单

  • 定义应该处理webhook的driver
  • 接收用于处理的请求receive
  • 向发送方响应一个200 ok响应

接收来自多个应用程序的数据

也许你的webhooks来自多个服务 -- 使用路由中的驱动变量从一个控制器处理它们所有。

<?php

namespace App\Http\Controllers\Webhooks;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class WebhooksController extends Controller
{
   public function store(Request $request, string $driver)
   {
       return Receiver::driver($driver)
           ->receive($request)
           ->ok();
   }
}

提供的ReceivesWebhooks特质将为你处理这些。

<?php

namespace App\Http\Controllers\Webhooks;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Receiver\ReceivesWebhooks;

class WebhooksController extends Controller
{
   use ReceivesWebhooks;
}

注意:你仍然需要创建到这个操作的路线。 示例

Route::post('/hooks/{driver}', [\App\Http\Controllers\Webhooks\WebhooksController::class, 'store'])
    ->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);

高级使用

回退

Receiver允许你安全地处理你未处理的事件的webhooks。在ok之前添加一个fallback方法 -- 它接受一个回调,该回调接收webhook对象。

<?php

namespace App\Http\Controllers\Webhooks;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Receiver\Providers\Webhook;

class WebhooksController extends Controller
{
   public function store(Request $request, string $driver)
   {
       return Receiver::driver($driver)
           ->receive($request)
           ->fallback(function(Webhook $webhook) {
               // Do whatever you like here...
           })
           ->ok();
   }
}

处理Webhooks

基础知识

现在webhooks已被接收,需要处理。Receiver将在App\Http\Handlers\[Driver]命名空间中寻找为每个事件类型指定的Handler类。Receiver 提供这些处理器 -- 你需要根据需要提供。如果Receiver找不到匹配的处理器,它将简单地忽略该事件并响应200状态码。

例如,Stripe webhook处理器对于传入的customer.created事件将是App\Http\Handlers\Stripe\CustomerCreated

每个处理器都使用event(webhook事件的名称)和data属性构建。

每个处理器还必须使用Dispatchable特质。

<?php

namespace App\Http\Handlers\Stripe;

use Illuminate\Foundation\Bus\Dispatchable;

class CustomerCreated
{
    use Dispatchable;
    
    public function __construct(public string $event, public array $data)
    {
    }

    public function handle()
    {
        // Your code here
    }
}

队列处理器

当然,由于你的应用程序可能正在接收大量的webhooks,所以将处理器排队可能是一个更好的做法。这样,你的应用程序可以高效地响应接收webhook的服务,并且请求在处理事件时不会被阻塞。

Receiver尝试为每个处理的事件执行dispatch,所以排队处理器只是像设置任何Laravel队列作业一样设置它们。

<?php

namespace App\Http\Handlers\Stripe;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class CustomerCreated implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public function __construct(public string $event, public array $data)
    {
    }

    public function handle()
    {
        // Your code here
    }
}

扩展Receiver

如前所述,接收器可以处理来自任何来源的webhooks。尽管该软件包中包含了一些提供者,但接收器可以轻松扩展以与其他应用程序协同工作。

添加自定义提供者

添加新提供者的最简单方法是使用包含的Artisan命令

php artisan receiver:make <name>

此命令将根据您定义的名称生成一个新提供者。此类将在App\Http\Receivers命名空间中创建。

如果您的提供者需要能够验证webhook签名,请将--verified标志添加到命令中

php artisan receiver:make <name> --verified

一旦您创建了新的提供者,您可以在您的AppServiceProvider中简单地扩展接收器,以便接收器可以使用它

<?php

namespace App\Providers;

use App\Http\Receivers\MailchimpProvider;
use App\Http\Receivers\MailgunProvider;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        // 
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        $receiver = app('receiver');

        $receiver->extend('mailchimp', function ($app) {
            return new MailchimpProvider(
                config('services.mailchimp.webhook_secret')
            );
        });
        
        $receiver->extend('mailgun', function ($app) {
            return new MailgunProvider(
                config('services.mailgun.webhook_secret')
            );
        });
    }
}

定义属性

接收器需要两块信息来接收和处理webhook事件

  • 事件name
  • 事件的data

由于这些信息可能位于webhook的不同属性或头中,因此接收器使您能够在提供者中轻松定义它们。

<?php

namespace Receiver\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CustomProvider extends AbstractProvider
{
    /**
     * @param Request $request
     * @return string
     */
    public function getEvent(Request $request): string
    {
        return $request->input('event.name');
    }
    
    /**
     * @param Request $request
     * @return array
     */
    public function getData(Request $request): array
    {
        return $request->all();
    }
}

使用getEvent()方法返回webhook事件的名称,即customer.created

使用getData()方法返回可以在您的处理器内部使用的数据负载。默认情况下,这设置为$request->all()

保护webhooks

许多webhooks都有在接收时验证其真实性的方式,最常见的是通过签名或基本认证。无论策略如何,接收器都允许您根据需要编写自定义验证代码。只需在您的提供者中实现verify方法并返回true或false即可。

返回false将导致返回401响应给webhook发送者。

<?php

namespace Receiver\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CustomProvider extends AbstractProvider
{
    public function verify(Request $request): bool
    {
        // return result of verification
    }
}

握手

某些webhooks希望在首次设置时执行“握手”以检查您的端点是否存在,并返回有效的响应。为此,在您的提供者中实现handshake方法

<?php

namespace Receiver\Providers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CustomProvider extends AbstractProvider
{
    public function handshake(Request $request): array
    {
        // return result of handshake
    }
}

verify方法不同,handshake期望返回一个数组,因为很多时候webhook发送者期望一个特定的“挑战”响应。握手方法的返回值将发送回webhook发送者。

分享您的接收器!

您是否创建了一个自定义接收器? 在我们的 接收器讨论主题 中与社区分享!

致谢

contributors-img制作。

许可

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