hotmeteor/receiver
Composer 安装命令:
composer require hotmeteor/receiver
包简介
A drop-in webhook handling library for Laravel
README 文档
README
Receiver
Receiver is a drop-in webhook handling library for Laravel.
Receiver gives you a consistent, expressive way to receive, verify, and handle incoming webhooks in your Laravel app. Point a route at a controller, call three methods, and you're done.
Out of the box, Receiver supports:
| Provider | Driver |
|---|---|
| GitHub | github |
| HubSpot | hubspot |
| Mailchimp Marketing | mailchimp |
| Paddle Billing | paddle |
| Postmark | postmark |
| SendGrid Events | sendgrid |
| Shopify | shopify |
| Slack Events API | slack |
| Stripe | stripe |
| Twilio | twilio |
Any other webhook source can be added with a custom provider.
Table of Contents
- Installation
- Configuration
- Receiving Webhooks
- Handling Webhooks
- Extending Receiver
- Share Your Receivers!
- Credits
- License
Installation
Requires PHP ^8.2 and Laravel 10+.
composer require hotmeteor/receiver
Note: The Stripe provider requires
stripe/stripe-php:composer require stripe/stripe-php
Configuration
Each provider reads its secret from config/services.php. Add an entry for each source you intend to receive from.
Most providers use the same shape:
'github' => ['webhook_secret' => env('GITHUB_WEBHOOK_SECRET')], 'hubspot' => ['webhook_secret' => env('HUBSPOT_WEBHOOK_SECRET')], 'paddle' => ['webhook_secret' => env('PADDLE_WEBHOOK_SECRET')], 'shopify' => ['webhook_secret' => env('SHOPIFY_WEBHOOK_SECRET')], 'slack' => ['webhook_secret' => env('SLACK_WEBHOOK_SECRET')], 'stripe' => ['webhook_secret' => env('STRIPE_WEBHOOK_SECRET')], 'twilio' => ['webhook_secret' => env('TWILIO_AUTH_TOKEN')],
Mailchimp — Mailchimp Marketing webhooks are verified via a secret you embed in your webhook URL (?secret=...). Configure the same value here so Receiver can compare it:
'mailchimp' => ['webhook_secret' => env('MAILCHIMP_WEBHOOK_SECRET')],
SendGrid — Signature verification is opt-in. Set webhook_secret to the PEM-format public key found in the SendGrid dashboard under Settings → Mail Settings → Event Webhook. Leave it empty to accept all requests without verification.
'sendgrid' => ['webhook_secret' => env('SENDGRID_WEBHOOK_PUBLIC_KEY', '')],
Postmark — Postmark supports several verification strategies. Configure which ones to use under the webhook key:
'postmark' => [ 'token' => env('POSTMARK_TOKEN'), 'webhook' => [ // One or more of: 'auth', 'headers', 'ips' 'verification_types' => ['headers', 'ips'], // Header name => expected value pairs (used with 'headers') 'headers' => [ 'X-Custom-Header' => env('POSTMARK_WEBHOOK_HEADER'), ], // Allowed source IPs (used with 'ips') // https://postmarkapp.com/support/article/800-ips-for-firewalls#webhooks 'ips' => [ '3.134.147.250', '50.31.156.6', '50.31.156.77', '18.217.206.57', ], ], ],
Postmark verification_type |
Description |
|---|---|
auth |
HTTP Basic Auth via Auth::onceBasic() |
headers |
Validates that specific request headers match expected values |
ips |
Validates that the request originates from an allowed IP |
If verification_types is empty or not set, all Postmark requests are accepted without verification.
Receiving Webhooks
Single provider
Create a controller and route for each webhook source, then call driver(), receive(), and ok():
<?php namespace App\Http\Controllers\Webhooks; use Illuminate\Http\Request; use Receiver\Facades\Receiver; class StripeWebhookController extends Controller { public function store(Request $request) { return Receiver::driver('stripe') ->receive($request) ->ok(); } }
driver()— selects the provider and reads its configreceive()— verifies the signature and maps the eventok()— dispatches matched handlers and returns a200response
Multiple providers
If you'd rather handle all webhooks through a single controller, use a {provider} route parameter:
// routes/web.php Route::post('/webhooks/{provider}', [WebhookController::class, 'store']) ->withoutMiddleware(\Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class);
<?php namespace App\Http\Controllers\Webhooks; use Illuminate\Http\Request; use Receiver\Facades\Receiver; class WebhookController extends Controller { public function store(Request $request, string $provider) { return Receiver::driver($provider) ->receive($request) ->ok(); } }
Or use the included ReceivesWebhooks trait, which provides this exact store() method for you:
<?php namespace App\Http\Controllers\Webhooks; use Receiver\ReceivesWebhooks; class WebhookController extends Controller { use ReceivesWebhooks; }
Fallbacks
Receiver silently ignores events it has no handler for. If you'd like to do something with unhandled events, add a fallback() callback before ok():
use Receiver\Providers\Webhook; return Receiver::driver($provider) ->receive($request) ->fallback(function (Webhook $webhook) { Log::info('Unhandled webhook', ['event' => $webhook->getEvent()]); }) ->ok();
Handling Webhooks
Once a webhook is received, Receiver looks for a handler class that matches the event and dispatches it. Handlers live in App\Http\Handlers\{Driver}\ by default. If no matching handler is found the webhook is silently ignored and a 200 is returned.
Handler naming
The handler class name is derived from the event name — all non-alphanumeric characters are treated as word separators, then converted to StudlyCase:
| Event name | Handler class |
|---|---|
customer.created |
CustomerCreated |
subscription_activated |
SubscriptionActivated |
orders_created |
OrdersCreated |
invoice.payment_failed |
InvoicePaymentFailed |
For example, Stripe's customer.created event dispatches App\Http\Handlers\Stripe\CustomerCreated.
Each handler receives the $event name and the $data array, and must use the Dispatchable trait:
<?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(): void { // Your code here } }
Queueing handlers
Because Receiver calls dispatch() on each handler, making a handler queued is as simple as implementing ShouldQueue:
<?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, InteractsWithQueue, Queueable, SerializesModels; public function __construct( public string $event, public array $data, ) {} public function handle(): void { // Your code here } }
See the Laravel queue documentation for full details.
Extending Receiver
A provider is a PHP class that tells Receiver how to extract the event name, the payload data, and optionally how to verify the request's authenticity.
Generating a provider
The quickest way to scaffold a new provider is with the receiver:make Artisan command:
# Basic provider php artisan receiver:make Mailgun # With signature verification scaffolded php artisan receiver:make Mailgun --verified
The generated class is placed in App\Http\Receivers. Once created, register the driver in your AppServiceProvider:
public function boot(): void { app('receiver')->extend('mailgun', function () { return new \App\Http\Receivers\MailgunProvider( config('services.mailgun.webhook_secret') ); }); }
Defining getEvent() and getData()
Implement getEvent() to return the event name. Optionally implement getData() to return the event payload — by default it returns $request->all().
<?php namespace App\Http\Receivers; use Illuminate\Http\Request; use Receiver\Providers\AbstractProvider; class MailgunProvider extends AbstractProvider { public function getEvent(Request $request): string|array { return $request->input('event-data.event'); } public function getData(Request $request): array { return $request->input('event-data', []); } }
Securing webhooks
Implement a verify() method that returns true if the request is authentic, or false to reject it with a 401 response:
public function verify(Request $request): bool { $signature = $request->header('X-Mailgun-Signature'); $expected = hash_hmac('sha256', $request->getContent(), $this->secret); return hash_equals($expected, (string) $signature); }
The signing secret from config/services.{driver}.webhook_secret is available as $this->secret.
Handshakes
Some services send a verification request when a webhook URL is first registered. Implement handshake() to respond to it:
public function handshake(Request $request): array { return ['challenge' => $request->input('challenge')]; }
When handshake() returns a non-empty array, Receiver responds immediately with that payload and skips normal event handling. When it returns an empty array, Receiver processes the request normally.
Multiple events per request
Some services batch multiple events into a single request. Return an ['event_name' => $eventData] array from getEvent() and Receiver will dispatch a separate handler for each entry:
public function getEvent(Request $request): string|array { $events = []; foreach (json_decode($request->getContent(), true) as $event) { $type = $event['type'] ?? null; if ($type && ! isset($events[$type])) { $events[$type] = $event; } } return $events; }
Creating a community provider
If you're building a reusable provider package to share, add the --provider flag to also generate a companion ServiceProvider that registers the driver automatically:
php artisan receiver:make Mailgun --provider php artisan receiver:make Mailgun --verified --provider
This generates:
app/Http/Receivers/MailgunProvider.php— your provider classapp/Providers/MailgunReceiverServiceProvider.php— auto-registers the driver viaReceiver::extend()
To support Laravel package auto-discovery, add the service provider to your package's composer.json:
{
"extra": {
"laravel": {
"providers": [
"YourVendor\\YourPackage\\MailgunReceiverServiceProvider"
]
}
}
}
Users who install your package will have the driver available immediately, with no manual registration required.
Share Your Receivers!
Built a provider for a service not listed above? Share it with the community in the Receivers Discussion topic!
Credits
Made with contributors-img.
License
The MIT License (MIT). Please see License File for more information.
hotmeteor/receiver 适用场景与选型建议
hotmeteor/receiver 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 154.04k 次下载、GitHub Stars 达 393, 最近一次更新时间为 2022 年 08 月 22 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「laravel」 「webhooks」 「receiver」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 hotmeteor/receiver 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 hotmeteor/receiver 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 hotmeteor/receiver 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
The library for publish/receive messages from broker (RabbitMQ).
The bundle for integrate fivelab/amqp library with Symfony application
Makes your AmoCRM Webhooks looks pretty
Async send/receive events
Handle Zoom.us webhooks in a Laravel application
Production-ready third-party integrations for Laravel. Credential management, API request logging, rate limiting, sync scheduling, OAuth2, and health monitoring.
统计信息
- 总下载量: 154.04k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 394
- 点击次数: 24
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2022-08-22
