Files
ABSDEV/Modules/Api/Services/WebhookDispatcher.php
T
Mark Gregory 2b949cb354 phases 9
* Versioned REST API under /api/v1
* Published Pages API
* Published Blog API
* Published News API
* Secure bearer API tokens
* SHA-256 token storage
* Token abilities
* Token expiry and revocation
* Token usage tracking
* Webhook subscriptions
* Site-specific webhooks
* HMAC-SHA256 webhook signatures
* Webhook delivery history
* Failure tracking
* OpenAPI 3.1 JSON documentation
* API administration screen
* Administration navigation
* API permissions
* Module registration
* Feature tests
2026-07-24 12:09:36 +01:00

5 lines
1.3 KiB
PHP

<?php
namespace Modules\Api\Services;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Str; use Modules\Api\Models\Webhook; use Modules\Api\Models\WebhookDelivery;
final class WebhookDispatcher {public function dispatch(string $event,array $payload,?int $siteId=null): void{Webhook::where('is_active',true)->get()->filter(fn(Webhook $h)=>($h->site_id===null||$h->site_id===$siteId)&&$h->subscribesTo($event))->each(function(Webhook $h)use($event,$payload):void{$uuid=(string)Str::uuid();$json=json_encode($payload,JSON_UNESCAPED_SLASHES)?:'{}';$delivery=WebhookDelivery::create(['webhook_id'=>$h->id,'uuid'=>$uuid,'event'=>$event,'payload'=>$payload,'attempts'=>1]);try{$res=Http::timeout((int)config('api.webhook_timeout',10))->withHeaders(['X-CMS-Event'=>$event,'X-CMS-Delivery'=>$uuid,'X-CMS-Signature'=>'sha256='.hash_hmac('sha256',$json,$h->getRawOriginal('secret'))])->withBody($json,'application/json')->post($h->url);$delivery->update(['response_status'=>$res->status(),'response_body'=>Str::limit($res->body(),10000),'delivered_at'=>$res->successful()?now():null,'failed_at'=>$res->successful()?null:now()]);$h->update(['last_triggered_at'=>now(),'failure_count'=>$res->successful()?0:$h->failure_count+1]);}catch(\Throwable $e){$delivery->update(['response_body'=>$e->getMessage(),'failed_at'=>now()]);$h->increment('failure_count');}});}}