Özet (TL;DR): Özel bir Drupal 10 modülü oluşturun, `@http_client` servisini enjekte edin, token'ı Key modülünde saklayın ve `POST /messages/text` uç noktasını çağıran tek bir Drush komutuyla kurulumu doğrulayın. Bunu webhook'lar, kuyruklar veya yönetim arayüzünden önce yapın. Mimarinin doğruluğunu kanıtlamak için ücretsiz bir Whapi.Cloud sandbox hesabı yeterlidir.
Drupal 10'da Ne Zaman Özel Bir WhatsApp Modülü Yazılmalıdır?
Amacınız Drupal 10 içinde yeniden kullanılabilir bir giden WhatsApp çağrısı yapmaksa, işe özel bir modülle başlayın. Widget modülleri ve yalnızca yöneticiye yönelik contrib ekranları farklı bir amaca hizmet eder.
Drupal tabanlı doğal bir WhatsApp entegrasyonu bir widget ile değil, bir servis ile başlar. Bu, ilk başarınızın sürdürülebilir bir koda mı yoksa bir olay abonesi (event subscriber), kuyruk çalışanı (queue worker) veya komuttan yeniden kullanamayacağınız sıradan bir yönetim ekranına mı dönüşeceğini belirleyen mimari bir yol ayrımıdır.
| Seçenek | En Uygun Kullanım | Programlı Giden Gönderim | Drupal'a Özgü Yeniden Kullanım | Bakım Durumu Sinyali | Şu Durumda Seçin |
|---|---|---|---|---|---|
| `whatsapp_button` veya `whatsapp_bubble` gibi arayüz modülleri | Tıkla-sohbet-et giriş noktaları | Modül mantığınız için taşıma katmanı (transport layer) yoktur | Düşük | Hızlı kurulum, dar kapsam | Yalnızca ön uçta bir sohbet butonuna ihtiyacınız olduğunda |
| `whatsapp_cloud_api` contrib modülü | Yönetici odaklı denemeler | Sınırlı ve ekran odaklı | En iyi ihtimalle orta | Drupal.org'da görünür bir proje, ancak en çok atıfta bulunulan özel modül en son 2022'de güncellendi | Yeniden kullanılabilir bir servis katmanı tasarlamak yerine sadece fikirleri değerlendirirken |
| Brevo eylemleri | Başka bir platformdan kampanya veya iş akışı eylemleri | Mümkün, ancak Drupal'ın kendi servis konteynerinin dışında | Özel PHP kodları içinde düşük | Pazarlama otomasyonları için iyi, kod öncelikli Drupal sahipliği için zayıf | Drupal modül kodundan ziyade harici otomasyon istediğinizde |
| Özel Drupal modülü | Site mantığından giden mesajlar | Evet; servislerden, komutlardan, denetleyicilerden ve kuyruklardan | Yüksek | İlk gün daha fazla kurulum zahmeti, sonrasında çok daha iyi yeniden kullanım | Drupal'a ait olan tek bir gönderim yoluna ihtiyacınız olduğunda |
Bu uyumsuzluk mevcut arama sonuçlarında açıkça görülmektedir. Çoğu Drupal ve WhatsApp sayfası sohbet balonlarını, giriş akışlarını veya yönetici tarafından tetiklenen eylemleri kapsar. Bir sipariş olayı, bir potansiyel müşteri formu veya özel bir denetleyicinin Drupal kodundan gönderim yapması gerektiğinde ihtiyaç duyacağınız servis-konteyneri-öncelikli (service-container-first) yapıyı nadiren gösterirler.
Arayüz Modülleri
`whatsapp_button` ve `whatsapp_bubble` modülleri, okuyucunun tek amacı basit bir sohbet girişi sağlamak olduğunda gayet kullanışlıdır. Ancak, Drupal içindeki giden WhatsApp mantığı için enjekte edilebilir bir taşıma servisi, istek oluşturucu (request builder) veya hata yönetimi yolu sunmazlar.
Contrib API Modülleri
Drupal ekosistemindeki özel `whatsapp_cloud_api` modülü, esas olarak bir bakım ipucu olarak faydalıdır. Odak noktası yapılandırma formlarıdır ve en net güncel sinyal, son güncellemenin Eylül 2022'de yapılmış olmasıdır. İhtiyacınız yeniden kullanılabilir Drupal 10 servis kodu olduğunda, bu durum pek de güven verici değildir.
Özel Çözümün Doğru Tercih Olduğu Durumlar
Mesajın neden gönderilmesi gerektiğini Drupal zaten biliyorsa özel bir modül oluşturun. Drupal Commerce ekiplerinin bir bot platformu yerine doğrudan site mantığından gelen tek bir sipariş bildirimiyle işe başladığını sıkça görüyoruz. Gayrimenkul takip sistemleri ve sağlık hizmetleri kayıt akışları da genellikle aynı şekilde başlar: önce işe yarar tek bir giden mesaj, ardından daha büyük orkestrasyonlar.
WhatsApp API Altyapınızı Seçme
Üretim ortamı kısıtlamalarını gizlemeden sizi ilk gerçek gönderime ulaştıran arka ucu seçin. Bu makaledeki görev için Whapi.Cloud en kısa yoldur.
Whapi.Cloud, boş bir modülden ilk gerçek gönderime giden en kısa yolu sunar: QR kod tarama, token alma, POST isteği ve bitti. Meta Cloud API, bazı kuruluşlarda uzun vadeli uyumluluk için doğru yol olabilir; ancak başlangıç seviyesindeki bir Drupal geliştiricisinin siteden çıkan ilk başarılı mesajı görmesinden önce sürece çok fazla sisteme katılım (onboarding) yükü ekler.
| Arka Uç Yolu | İlk Test Gönderimine Kadar Geçen Süre | Üretim Ortamı Engelleri | MVP'yi Etkileyen Giden Gönderim Kuralları | Drupal 10 Entegrasyon Eforu |
|---|---|---|---|---|
| Meta Cloud API | Meta varlıklarınız zaten hazırsa aynı gün, aksi takdirde günler sürer | İşletme doğrulaması, telefon kurulumu, webhook abonelikleri ve onay adımları üst üste biriktiği için genellikle günler veya haftalar alır | Resmi akışlar, şablon kurallarını ve 24 saatlik müşteri hizmetleri penceresini üretim tasarımına dahil eder | Daha yüksek; çünkü kod yolu kararlı hale gelmeden önce sisteme katılım and politika kısıtlamalarıyla uğraşmanız gerekir |
| Whapi.Cloud | QR kod bağlantısından yaklaşık 2 dakika sonra | MVP gönderim yolu için Meta işletme doğrulaması gerekmez | İlk giden test mesajı için şablon engeli yoktur, böylece taşıma katmanını daha erken doğrulayabilirsiniz | Daha düşük; çünkü Drupal öncelikle tek bir HTTP entegrasyon modeline odaklanabilir |
Meta Cloud API Yolu
Resmi yol, test ve üretim aşamaları arasında adil bir ayrımı hak eder. Birçok ekibin tahmin ettiğinden daha erken test yapabilirsiniz, ancak işletme doğrulaması, numara kurulumu ve webhook yapılandırması entegrasyon rutin hale gelmeden önce projeye dahil olduğu için üretim ortamına geçiş yine de yavaş ilerler. Burada tam Meta İşletme Doğrulaması (Meta Business Verification) akışını ele almayacağız; çünkü bu ayrı bir katılım sürecidir ve giden bir Drupal modülünü test etmenin en hızlı yolu değildir.
Geçit (Gateway) API Yolu
Whapi.Cloud bu kılavuza tam olarak uymaktadır; çünkü MVP, bir uyumluluk programı değil, Drupal'dan giden tek bir kısa mesajdır. QR kod ile bağlantı kurulum yolu ve süresiz ücretsiz sandbox hesabı size ayda 5 aktif sohbet, günde 150 mesaj ve ayda 1.000 API isteği sunar. Bu, gönderim yolunu iş olaylarına bağlamadan önce servis tasarımını, token saklamayı, günlük kaydını (logging) ve Drush testlerini doğrulamak için fazlasıyla yeterlidir.
Seçim Kriterleri
İlk günden itibaren resmi platform gereksinimleri iş tanımının bir parçası olduğunda Meta'yı kullanın. Acil göreviniz deneme dostu ilk gönderime sahip çalışan bir Drupal 10 özel modülü oluşturmak olduğunda Whapi.Cloud'u kullanın. Bunun yerine kendi barındırdığınız (self-hosted) bir web istemcisi sarmalayıcısı kullanmaya yeltenirseniz, bunun size genellikle ne getireceğini unutmayın: üst protokol değişiklikleri, 500 hataları ve Drupal ile hiçbir ilgisi olmayan hata ayıklama (debugging) işleri.
Modül Yapısı: Servis, Yapılandırma ve Bağımlılık Enjeksiyonu
Modülünüz normal bir Drupal entegrasyonu gibi görünmelidir, çünkü zaten öyledir. Taşıma kodunu tek bir serviste tutun ve diğer her şeyin bu servisi çağırmasını sağlayın.
`@http_client` servisini bir kez enjekte edin, böylece her WhatsApp çağrısı yeniden kullanılabilir Drupal koduna dönüşür. Bu karar, aynı gönderim yönteminin taşıma mantığını yeniden yazmadan Drush, denetleyiciler (controllers), olay aboneleri (event subscribers), kuyruk çalışanları (queue workers) ve testlerden çalışmasını sağlar.
Dosya İskeleti (Scaffold)
Küçük başlayın. Bir modül tanımına, bir servis tanımına, bir yapılandırma şemasına (config schema), bir istemci sınıfına ve bir Drush komut sınıfına ihtiyacınız var. Bu, ilk mesaja temiz bir şekilde ulaşmak için yeterlidir.
name: Whapi Drupal
type: module
description: Drupal 10 custom module for outbound WhatsApp messaging.
core_version_requirement: ^10 || ^11
package: Custom
dependencies:
- key:key
services.yml ve WhatsappApiClient
Servis tanımı, Drupal yönteminin belirginleştiği yerdir. HTTP istemcisini, config factory'yi, Key deposunu (repository) ve logger kanalını, modül yapısını değiştirmeden Whapi.Cloud API belgelerine göre genişletilebilecek tek bir taşıma sınıfında birleştirir.
services:
logger.channel.whapi_drupal:
parent: logger.channel_base
arguments: ['whapi_drupal']
whapi_drupal.client:
class: Drupal\whapi_drupal\Service\WhatsappApiClient
arguments:
- '@http_client'
- '@config.factory'
- '@key.repository'
- '@logger.channel.whapi_drupal'
<?php
namespace Drupal\whapi_drupal\Service;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\key\KeyRepositoryInterface;
use GuzzleHttp\ClientInterface;
use Psr\Log\LoggerInterface;
final class WhatsappApiClient {
public function __construct(
private ClientInterface $httpClient,
private ConfigFactoryInterface $configFactory,
private KeyRepositoryInterface $keyRepository,
private LoggerInterface $logger,
) {}
}
http_client Enjekte Etmek vs Statik Çağrı
Drupal, Guzzle'ı servis konteynerinde zaten sarmalamaktadır. Ham cURL kod parçacıkları veya statik konteyner aramaları yerine bunu kullanın. Bu, istemciyi test edilebilir kılar, kod tekrarını önler og ve modülünüzün geri kalanının güveneceği çerçeve (framework) kurallarıyla eşleşir.
API Kimlik Bilgilerini Drupal'da Güvenli Bir Şekilde Saklama
Gizli değeri modül ayarlarının geri kalanından ayırın. Drupal yapılandırması (config) referanslar ve bayraklar (flags) içindir; Key ise doğrudan token'ın kendisi içindir.
Key ID'sini yapılandırmada, token değerini ise Key modülünde saklayın; token'ın kendisini asla modül kodunda veya dışa aktarılan yapılandırmada saklamayın. Bu, ekip devir tesliminden başarıyla geçen bir kılavuz ile kimlik bilgilerini git geçmişine sızdıran bir kılavuz arasındaki çizgidir.
Key Modülü Kurulumu
Drupal'da bir Key varlığı (entity) oluşturun ve bu Key ID'sini modül ayarlarınızda kullanın. Yaygın ve güvenli yöntem, Key modülünün değeri çevre değişkeni (environment-backed) tabanlı bir sağlayıcıdan çekmesine izin vermek, ardından özel modülünüzün çözümlenen değeri `key.repository` aracılığıyla istemesini sağlamaktır.
Config Schema (Yapılandırma Şeması)
Yapılandırma şemanız gizli olmayan ayarları net bir şekilde tanımlamalıdır: bağlı kanal veya gönderici kimliği, Key ID'si ve yeniden kullanmak istediğiniz isteğe bağlı varsayılan değerler. Token değerinin kendisi asla burada görünmemelidir.
whapi_drupal.settings:
type: config_object
label: 'Whapi Drupal settings'
mapping:
channel_id:
type: string
label: 'Connected WhatsApp channel ID'
token_key:
type: string
label: 'Key entity ID for the Whapi token'
default_country_code:
type: string
label: 'Default country code for test sends'
.module Dosyalarına Asla Konulmaması Gerekenler
Erişim token'ı `.module` dosyalarına, kopyalanan blog kod parçacıklarına veya sabit kodlanmış varsayılan değerlere ait değildir. Buradaki ilk hata nadiren API çağrısında yaşanır. Genellikle demo sonrasında git geçmişine sızan bir gizli anahtar (secret) hatasıdır.
İlk Giden Mesajınızı Gönderme
Modül yapısı ve token saklama alanı hazır olduğunda, çalışan gönderim yolu oldukça basittir. Bir veri yükü (payload) oluşturun, bunu doğrulanmış uç noktaya gönderin og ve yanıtı yapılandırılmış veri olarak okuyun.
`/messages/text` uç noktasına yapılacak tek bir başarılı POST isteği, mimariyi kanıtlamak için yeterlidir. Bu noktadan önce webhook'lara, kuyruklar veya tam bir yönetim arayüzüne ihtiyacınız yoktur. Drupal kodundan çalışan, tekrarlanabilir tek bir gönderim yöntemine ihtiyacınız vardır.
İstek Veri Yükünü (Payload) Oluşturma
Doğrulanmış Whapi.Cloud metin gönderim uç noktası `POST /messages/text` adresidir. Gerekli veri yükü alanları `to` ve `body` olup, bunlar minimal bir Drupal servis yöntemiyle düzgün bir şekilde eşleşir.
Enjekte Edilen HTTP İstemcisi ile POST İstemi
Bu, temel taşıma yöntemidir. Token'ı Key modülünden çeker, Drupal'ın enjekte edilen HTTP istemcisi aracılığıyla JSON gönderir, üst sunucu (upstream) hatalarını günlüğe kaydeder ve kodu çağıran tarafa kodu çözülmüş yanıt verilerini döndürür.
<?php
use GuzzleHttp\Exception\RequestException;
public function sendText(string $to, string $body): array {
$config = $this->configFactory->get('whapi_drupal.settings');
$keyId = $config->get('token_key');
$token = $this->keyRepository->getKey($keyId)?->getKeyValue();
if (!$token) {
throw new \RuntimeException('Missing Whapi token in Key module.');
}
try {
$response = $this->httpClient->request('POST', 'https://gate.whapi.cloud/messages/text', [
'headers' => [
// If you skip this Bearer header, Whapi.Cloud returns 401 and the send never leaves Drupal.
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json',
],
'json' => [
'to' => $to,
'body' => $body,
],
'timeout' => 15,
]);
return json_decode((string) $response->getBody(), TRUE, 512, JSON_THROW_ON_ERROR);
}
catch (RequestException $exception) {
$this->logger->error('Whapi send failed for {recipient}: {message}', [
'recipient' => $to,
'message' => $exception->getMessage(),
]);
throw $exception;
}
}
API Yanıtını Okuma
JSON yanıtını okuyun ve mesaj kimliğini (ID) veya durumunu çağıran tarafa iletin. Deneme modunda, `402` önemli bir sınır sinyalidir. `401` genellikle token'ın eksik veya yanlış olduğu anlamına gelir ve `403` genellikle hedef sohbetin veya alıcının mevcut kanal durumunda gönderimi alamayacağını gösterir.
Bu sınır önemlidir; çünkü sandbox sınırları modül tasarımını doğrulamak için yeterlidir. Bunlar bir üretim verimliliği kıstası değildir. Bu aşamada hacmi değil, mimariyi kanıtlıyorsunuz.
Entegrasyonu Drupal Üzerinden Test Etme
Taşıma işlemini hatanın görünür olduğu yerde test edin. Drush, bir yönetim sayfasından daha hızlı geri bildirim sağlar ve ilk doğrulama döngüsünü küçük tutar.
Bir yönetim ekranı oluşturmadan önce Drush ile test edin. İstisnayı (exception), veri yükü girdilerini ve döndürülen verileri daha hızlı görürsünüz; bu da ilk hata ayıklama döngünüzü daha kısa ve çok daha az gürültülü hale getirir.
Drush Komutu Yaklaşımı
Servisi tek bir komut aracılığıyla dışa açın. Bu, Drupal'ın istemciyi çözümleyebileceğinin, token'ı yükleyebileceğinin ve gerçek bir mesaj gönderebileceğinin en hızlı kanıtını sunar. Bunun Drupal Commerce kurulumlarında saatler kazandırdığını gördük; çünkü ilk yararlı kontrol yönetim arayüzü değil, taşıma katmanıdır.
<?php
namespace Drupal\whapi_drupal\Commands;
use Drupal\whapi_drupal\Service\WhatsappApiClient;
use Drush\Commands\DrushCommands;
final class WhapiDrupalCommands extends DrushCommands {
public function __construct(
private WhatsappApiClient $client,
) {}
/*
* Sends a test WhatsApp message through Whapi.Cloud.
*
* @command whapi:send-test
*/
public function sendTest(string $chatId, string $message): void {
$result = $this->client->sendText($chatId, $message);
$this->output()->writeln('Message sent. Remote id: ' . ($result['messages'][0]['id'] ?? 'n/a'));
}
}
Komutu bilinen bir hedef sohbet kimliği (chat ID) veya telefon numarasıyla çalıştırın, ardından bir şeyler ters giderse sonucu Whapi.Cloud Postman koleksiyonu ile karşılaştırın. Bu çapraz kontrol, hatanın Drupal'da mı, token'da mı yoksa veri yükünde mi olduğunu tahmin etmekten çok daha hızlıdır.
Minimal Yönetim Denetleyicisi (Admin Controller) Yaklaşımı
Drush çalıştıktan sonra, ekibinizin tarayıcı tabanlı bir duman testine (smoke test) ihtiyacı varsa küçük bir dahili rota veya yönetim denetleyicisi ekleyin. Bunu basit tutun: girdiyi alın, aynı servisi çağırın ve sonucu gösterin. Taşıma mantığını asla tekrarlamayın.
API Hatalarını Drupal Yöntemiyle Yönetme
Taşıma hataları normaldir. Önemli olan, Drupal'ın bunları ekibinizin harekete geçebileceği sinyallere dönüştürüp dönüştürmediğidir.
Drupal günlük kaydı (logging) ve Messenger, sessiz bir üst sunucu hatasını hata ayıklanabilir bir olaya dönüştürür. Taşıma istisnasını bir kez yakalayın, üst sunucu bağlamını bir kez günlüğe kaydedin ve boş bir sayfa veya yutulmuş bir hata yerine kullanıcıya yönelik kısa bir mesaj gösterin.
RequestException İstisnasını Yakalama
Tüm denetleyici veya komut sınıfı yerine, `RequestException` istisnasını doğrudan gerçek gönderim çağrısının etrafında yakalayın. Bu, hata sınırını dar tutar ve hedef alıcıyı, HTTP belirtisini ve gönderimi tetikleyen eylemi günlüğe kaydetmenizi sağlar.
Logger Factory ile Günlük Kaydı
Operasyonel olaylarınızın Son günlük mesajlarında kolayca filtrelenebilmesi için `whapi_drupal` gibi özel bir kanal kullanın. Bu, kuyruğa alınmış bir gönderim, bir olay abonesi ve manuel bir Drush çağrısının hepsinin aynı istemciyi kullandığı anda önem kazanır.
Kullanıcıya Yönelik Hata Mesajları
Denetleyiciler ve yönetim formları, istisnayı kısa bir `Messenger` hatasına dönüştürmelidir: gönderim başarısız oldu ve operatör günlükleri kontrol etmelidir. Arayüze ham üst sunucu JSON verilerini dökmeyin. Günlük kaydı geliştiriciler içindir; Messenger metni ise operatörler içindir.
Beklenmeyen bir davranışla karşılaşırsanız, whapi.cloud adresindeki sohbet widget'ı aracılığıyla Whapi.Cloud destek ekibine ulaşın. Doğrudan bir destek kontağı, başka birinin yığınını tanımlayan rastgele forum konularını taramaktan çok daha kullanışlıdır.
Sırada Ne Var: Webhook'lar, Kuyruklar ve ECA Eylemleri
Yalnızca ilk giden mesaj güvenilir bir şekilde çalıştıktan sonra kapsamı genişletin. Bir sonraki katman, artık temel entegrasyonu kanıtlamakla değil, dayanıklılık ve gelen durumlarla ilgilidir.
En iyi MVP, tüm müşteri yolculuklarını otomatikleştirmeden önce tek bir yararlı WhatsApp mesajı gönderir. Taşıma işlemi kanıtlandıktan sonra, temel istemciyi yeniden tasarlamadan gelen webhook'ları, yeniden denemeleri ve editör dostu eylemleri ekleyebilirsiniz.
Webhook Denetleyici Taslağı (Skeleton)
İlk webhook denetleyicisini dar tutun: isteği kabul edin, doğrulayın, olay türünü webhook veri yükü biçiminden çıkarın ve veri yükünü bir servise teslim edin. Doğrulama, iş mantığı ve yan etkiler tek bir denetleyicide yaşadığında webhook kurulumu karmaşıklaşır. İmza doğrulaması (signature validation), giden yol çalıştıktan sonraki bir sonraki sıkılaştırma adımıdır.
Queue API (Kuyruk API)
Gönderimin yeniden denemelerden, ani yoğunluklardan veya engelleyici olmayan iş akışlarından etkilenmemesi için Drupal Queue API'yi kullanın. Bu, özellikle site olayının istek iş parçacığında uzak çağrıyı beklemek yerine işi sıraya alması gereken e-ticaret bildirimleri, potansiyel müşteri takipleri ve planlanmış hatırlatıcılar için kullanışlıdır.
ECA WhatsApp Gönder Eylemi
Servis kararlı hale geldikten sonra, editör tarafından yönetilen otomasyon için onu bir ECA eylemiyle sarmalayabilirsiniz. İş kullanıcılarının token saklama veya taşıma karmaşıklığını devralmadan değer elde ettiği yer burasıdır. Servis öncelikli taşıma, yükü taşıyan kısım olmaya devam eder.
Burada derin webhook imza yönetimini, bot dallanmalarını veya tam bir Meta üretim onay kılavuzunu ele almayacağız. Bunlar, Drupal modülünüz gerçek bir kanal üzerinden doğrulanmış bir mesaj gönderebildikten sonraki takip konularıdır.
Sürdürülebilir bir Drupal 10 WhatsApp entegrasyonu bilerek küçük tutulur: tek bir servis, tek bir key referansı, tek bir giden POST isteği ve tek bir Drush test komutu. Bu, bir Whapi.Cloud deneme hesabı ile ilk gerçek gönderimi tamamlamak için yeterlidir ve daha sonra taşıma katmanını yeniden yazmadan büyümek için yeterli yapıyı sunar.
Bir sonraki en hızlı adım pratiktir. Bir sandbox numarası bağlayın, token'ı Key modülünde saklayın, Drush komutunu çalıştırın og ve bir mesajın Drupal'dan başarıyla çıktığını doğrulayın. Sandbox sınırları kasıtlıdır; ancak ayda 5 aktif sohbet, günde 150 mesaj ve 1.000 API çağrısı, olayları, kuyrukları veya gelen otomasyonu bağlamadan önce mimari kanıtı için fazlasıyla yeterlidir.









