Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce sisteminizde PHP 8.2+ ve Laravel 11 yüklü olmalıdır. Webhook'ları yerel geliştirme ortamınızda test edebilmek için Expose veya ngrok gibi bir tünel servisine ihtiyacınız olacak. Bu araçlar, yerel sunucunuzu dış dünyaya açarak webhook sağlayıcılarının uygulamanıza erişmesini sağlar.
- PHP 8.2 veya üzeri sürüm.
- Composer paket yöneticisi.
- Yerel geliştirme için ngrok veya benzeri bir tünel servisi.
- Temel düzeyde Laravel Routing ve Controller bilgisi.
Adım 1: Webhook Rotasının Tanımlanması
İlk adım, dış dünyadan gelen POST isteklerini karşılayacak bir rota tanımlamaktır. Laravel'de webhook'lar genellikle routes/api.php dosyasında tanımlanır. Ancak, CSRF (Cross-Site Request Forgery) koruması nedeniyle bu rotanın VerifyCsrfToken ara katmanından (middleware) hariç tutulması gerekir.
// routes/api.php
use App\Http\Controllers\WebhookController;
use Illuminate\Support\Facades\Route;
Route::post('/webhooks/handle', [WebhookController::class, 'handle']);
Yukarıdaki kod, /api/webhooks/handle adresine gelen tüm POST isteklerini WebhookController içerisindeki handle metoduna yönlendirir. Bu rotayı bootstrap/app.php dosyasında CSRF korumasından çıkarmayı unutmayın.
Adım 2: Webhook Kontrolcüsünün Oluşturulması
Gelen veriyi karşılayacak kontrolcüyü oluşturmak için artisan komutunu kullanın: php artisan make:controller WebhookController. Bu kontrolcü, gelen isteğin doğruluğunu kontrol etmeli ve veriyi uygun bir işleme kuyruğuna (queue) göndermelidir.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class WebhookController extends Controller
{
public function handle(Request $request)
{
// Gelen veriyi loglayarak test edebilirsiniz
Log::info('Webhook alındı:', $request->all());
// İşlemi kuyruğa ekle (Performans için önemlidir)
// ProcessWebhookJob::dispatch($request->all());
return response()->json(['status' => 'success'], 200);
}
}
Bu aşamada, gelen tüm veriyi logluyoruz. Neden kuyruk yapısı kullanıyoruz? Çünkü webhook sağlayıcıları genellikle kısa sürede yanıt bekler. Eğer işlem uzun sürerse, sağlayıcı isteği başarısız sayabilir.
Adım 3: İstek Güvenliği ve Doğrulama
Webhook'lar herkese açıktır; bu nedenle gelen isteğin gerçekten beklediğiniz kaynaktan geldiğini doğrulamak zorundasınız. Çoğu servis, isteği bir "imza" (signature) ile imzalar. Bu imzayı kendi gizli anahtarınızla (secret key) karşılaştırmalısınız.
public function handle(Request $request)
{
$signature = $request->header('X-Webhook-Signature');
$payload = $request->getContent();
$secret = config('services.webhook.secret');
if (!hash_equals(hash_hmac('sha256', $payload, $secret), $signature)) {
return response()->json(['error' => 'Geçersiz imza'], 403);
}
return response()->json(['status' => 'verified'], 200);
}
hash_equals kullanımı, zamanlama saldırılarına (timing attacks) karşı koruma sağlar. Güvenlik için asla basit bir karşılaştırma operatörü (==) kullanmayın.
Kritik Güvenlik Uyarısı: Webhook gizli anahtarınızı (secret key) asla kod içerisinde doğrudan yazmayın. .env dosyasında saklayın ve config/services.php üzerinden erişin. Aksi takdirde sunucu güvenliğiniz tehlikeye girebilir.
Adım 4: Webhook İşleme Stratejileri
İşleme mantığını kontrolcüden ayırmak, kodun sürdürülebilirliği için şarttır. "Job" (İş) sınıfları, webhook verilerini arka planda işlemek için en iyi yöntemdir.
// app/Jobs/ProcessWebhookJob.php
public function handle(): void
{
// Veriyi veritabanına kaydet veya ilgili servisi tetikle
// Örn: Order::updateOrCreate(['id' => $this->data['id']], [...]);
}
Bu yaklaşım, sisteminizde bir hata oluşsa bile işin tekrar denenmesini (retry) sağlar. Laravel'in php artisan queue:work komutuyla bu işleri arka planda yönetebilirsiniz.
Webhook Yönetim Yöntemlerinin Karşılaştırılması
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Doğrudan Kontrolcü | Hızlı kurulum | Yavaş yanıt süresi |
| Kuyruk (Queue) | Yüksek performans | Ek altyapı gereksinimi |
| Event-Listener | Modüler yapı | Karmaşık hata yönetimi |
Adım 5: Hata Yönetimi ve Loglama
Webhook'lar bazen beklenmedik formatlarda gelebilir. Bu durumları try-catch blokları ile sarmalamak ve hataları loglamak, sistemin kararlılığı için hayati önem taşır.
try {
$this->processData($request->all());
} catch (\Exception $e) {
Log::error('Webhook işleme hatası: ' . $e->getMessage());
return response()->json(['error' => 'İşleme hatası'], 500);
}
Her zaman 500 hatası döndürmek yerine, hatanın türüne göre (örneğin doğrulama hatası) 400 gibi uygun HTTP kodları döndürmeyi tercih edin.
Sıkça Sorulan Sorular
Webhook isteği neden 403 hatası veriyor?
Genellikle imza doğrulaması başarısız olmuştur. Gönderilen X-Webhook-Signature başlığının ve kullandığınız secret anahtarının doğru olduğundan emin olun.
Neden kuyruk (queue) kullanmalıyım?
Webhook sağlayıcıları isteğe hızlı yanıt (genellikle 2-5 saniye içinde) bekler. Veritabanı işlemleri veya API çağrıları uzun sürerse, sağlayıcı isteği başarısız sayıp tekrar gönderebilir.
Yerel ortamda webhook'ları nasıl test ederim?
ngrok veya Laravel Expose kullanarak yerel portunuzu (örn: 8000) dış dünyaya açabilir ve webhook URL'sini sağlayıcı panelinde bu tünele yönlendirebilirsiniz.
Aynı webhook birden fazla kez gelirse ne olur?
Webhook sağlayıcıları bazen aynı bildirimi tekrar gönderebilir (at-least-once delivery). Veritabanı işlemlerinizde updateOrCreate gibi "idempotent" (tekrarlansa da aynı sonucu veren) yöntemler kullanmalısınız.
Webhook verisini nasıl doğrularım?
Laravel'in Validator sınıfını kullanarak gelen verinin yapısını (schema) mutlaka kontrol edin. Beklenmedik alanlar veritabanınızı bozabilir.
Sorumluluk Reddi: Bu rehberdeki kod örnekleri genel eğitim amaçlıdır. Uygulamanızın güvenlik gereksinimlerine göre (örneğin, IP beyaz listesi ekleme veya SSL doğrulaması) ek önlemler almanız gerekebilir. Kodların üretim (production) ortamında kullanılmadan önce kapsamlı testlerden geçirilmesi geliştiricinin sorumluluğundadır.
Webhook Sistemlerinde Performans Optimizasyonu ve Ölçeklendirme
Webhook trafiği, özellikle yoğun kampanya dönemlerinde veya yüksek işlem hacimli servislerde aniden artış gösterebilir. Uygulamanızın bu yük altında çökmemesi için sadece kuyruk kullanmak yeterli değildir; aynı zamanda veritabanı etkileşimlerini ve kaynak tüketimini optimize etmeniz gerekir.
Veritabanı Yazma İşlemlerini Toplu (Batch) Gerçekleştirme
Her gelen webhook için ayrı bir veritabanı sorgusu çalıştırmak, özellikle yüksek trafikli sistemlerde darboğaza yol açar. Bunun yerine gelen verileri önbellekte (Redis gibi) biriktirip belirli aralıklarla toplu olarak işlemek performansı ciddi oranda artırır.
// Redis kullanarak gelen verileri kuyruğa almadan önce gruplama örneği
public function handle(Request $request)
{
$payload = $request->all();
// Veriyi Redis listesine ekle
Redis::rpush('webhook_queue_buffer', json_encode($payload));
// Eğer buffer boyutu 100'e ulaştıysa işleme tetikle
if (Redis::llen('webhook_queue_buffer') >= 100) {
ProcessWebhookBatch::dispatch();
}
return response()->json(['status' => 'accepted'], 202);
}
İleri Düzey Hata Ayıklama: Webhook İzleme Paneli
Üretim ortamında gelen webhook'ların içeriğini görmek ve başarısız olanları yeniden tetiklemek için basit bir "Webhook Log" tablosu oluşturmak hayat kurtarıcıdır. Bu tablo üzerinden hatalı istekleri filtreleyebilir ve payload verisini inceleyebilirsiniz.
Webhook Log Tablosu İçin İpuçları
- Payload Sütunu: JSON formatında saklayın, böylece Laravel'in
jsoncast özelliğini kullanabilirsiniz. - Status Sütunu: 'pending', 'processed', 'failed' gibi durumlar tanımlayın.
- Attempt Count: Başarısız olan istekleri kaç kez denediğinizi takip edin.
// Başarısız olan bir webhook'u manuel olarak tekrar işleme (Retry)
public function retryWebhook($id)
{
$log = WebhookLog::findOrFail($id);
// İş mantığını yeniden tetikle
ProcessWebhookJob::dispatch($log->payload);
$log->update(['status' => 'retrying']);
}
Webhook Güvenliğinde İleri Seviye Yaklaşımlar
İmza doğrulaması (Signature Verification) temel güvenlik katmanıdır; ancak kurumsal seviyede projeler geliştiriyorsanız, IP kısıtlamaları ve zaman damgası (timestamp) kontrolleri ile güvenliği bir üst seviyeye taşıyabilirsiniz.
Zaman Damgası (Timestamp) Kontrolü
Bir saldırgan, yakaladığı geçerli bir webhook isteğini tekrar tekrar göndererek (Replay Attack) sisteminizi manipüle edebilir. Bunu önlemek için gelen isteğin başlığındaki (header) zaman damgasını kontrol ederek isteğin çok eski olup olmadığını denetleyin.
public function verifyTimestamp(Request $request)
{
$timestamp = $request->header('X-Webhook-Timestamp');
$tolerance = 300; // 5 dakika tolerans
if (abs(time() - $timestamp) > $tolerance) {
throw new \Exception('Webhook isteği zaman aşımına uğradı.');
}
}
Profesyonel İpucu: Eğer webhook gönderen servis (örneğin Stripe veya GitHub) kendi zaman damgası başlığını sağlıyorsa, mutlaka bu değeri kendi sunucu saatinizle kıyaslayarak doğrulama yapın.
Sonuç
Laravel ile dinamik bir webhook bildirim dinleyicisi kurmak, uygulamanızı dış servislerle entegre etmenin en verimli yoludur. Bu rehberde; rotaların tanımlanması, güvenlik imzalarının doğrulanması, kuyruk yönetimi ve hata ayıklama süreçlerini adım adım inceledik. Bir sonraki adım olarak, gelen verileri görselleştiren bir dashboard veya webhook geçmişini tutan bir veritabanı tablosu oluşturarak sistemi daha izlenebilir hale getirebilirsiniz.
Yorumlar (0)
Yorum Yaz