New updates
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\LicenseWebhookEvent;
|
||||
use App\Services\Payments\LemonSqueezyWebhookVerifier;
|
||||
use App\Services\Payments\PaddleWebhookVerifier;
|
||||
use App\Services\Payments\PurchaseProvisioner;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class PaymentWebhookController extends Controller
|
||||
{
|
||||
public function __invoke(string $provider, Request $request, PurchaseProvisioner $provisioner): JsonResponse
|
||||
{
|
||||
$raw=(string)$request->getContent();
|
||||
$verifier=match($provider){'paddle'=>app(PaddleWebhookVerifier::class),'lemon-squeezy'=>app(LemonSqueezyWebhookVerifier::class),default=>null};
|
||||
if (!$verifier) return response()->json(['message'=>'Unknown webhook provider.'],404);
|
||||
try { $verifier->verify($request,$raw); } catch (\Throwable $e) { report($e); return response()->json(['message'=>'Invalid webhook signature.'],400); }
|
||||
try { $payload=json_decode($raw,true,flags:JSON_THROW_ON_ERROR); } catch (\Throwable) { return response()->json(['message'=>'Invalid JSON.'],400); }
|
||||
$externalID=(string)($provider==='paddle'?($payload['event_id']??''):($payload['meta']['event_name']??'').':'.($payload['data']['id']??''));
|
||||
$eventType=(string)($provider==='paddle'?($payload['event_type']??'unknown'):($payload['meta']['event_name']??'unknown'));
|
||||
if ($externalID==='') return response()->json(['message'=>'Webhook event has no stable identifier.'],400);
|
||||
|
||||
try {
|
||||
DB::transaction(function() use($provider,$externalID,$eventType,$payload,$raw,$provisioner){
|
||||
$event=LicenseWebhookEvent::firstOrCreate(['provider'=>$provider,'external_event_id'=>$externalID],['event_type'=>$eventType,'payload_sha256'=>hash('sha256',$raw),'payload'=>$payload]);
|
||||
if ($event->processed_at) return;
|
||||
if (!hash_equals($event->payload_sha256,hash('sha256',$raw))) throw new \RuntimeException('Webhook ID was reused with a different payload.');
|
||||
try { $provisioner->provision($provider,$payload); $event->update(['processed_at'=>now(),'processing_error'=>null]); }
|
||||
catch (\Throwable $e) { $event->update(['processing_error'=>mb_substr($e->getMessage(),0,4000)]); throw $e; }
|
||||
});
|
||||
} catch (\Throwable $e) { report($e); return response()->json(['message'=>'Webhook could not be processed.'],500); }
|
||||
return response()->json(['ok'=>true]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user