English Version
1. Concept and Architecture
The Multi-Messaging System (MMS) is a modular, extensible subsystem designed to handle all outgoing notifications from the application. It was created to replace a monolithic utility class, promoting clean code, separation of concerns, and ease of maintenance. The architecture is based on the Strategy Design Pattern, where the core logic of sending a message is delegated to interchangeable “drivers”. Core Components:MmsManager(andMmsFacade): This is the central entry point for the entire system. It is responsible for reading the configuration, resolving the correct driver for a given channel, and providing helper methods like compiling messages from templates.- Contracts (Interfaces):
SenderInterface: Defines the fundamental rule that every driver must have asend()method.MessageInterface: Defines the structure for a standardized message object, ensuring data is passed consistently.- Drivers: These are the concrete classes that contain the logic for communicating with a specific third-party API (e.g., WAHA, Mailtrap, Firebase). Each driver implements the
SenderInterface. MmsMessageDTO: A simple Data Transfer Object that implementsMessageInterface. It acts as a standardized “package” carrying the recipient, body, and any other metadata to the driver.- Configuration (
config/mms.php): The “control panel” for the system. This file defines all available communication “channels” (likewhatsapp,email), which drivers are available for each channel, and the credentials/settings for each driver. - Logging (
NotificationDispatchLog): The system is tightly integrated with a unified logging model. Every message sent, regardless of the channel or driver, has its status tracked in thenotification_dispatch_logscollection.
- A Job (e.g.,
SendWhatsAppJob) is dispatched. - The Job uses the
Mmsfacade to compile a message and create anMmsMessageobject. - The Job calls
Mms::channel('whatsapp')->send($message). - The
MmsManagerreads theconfig/mms.phpfile to find the default driver for thewhatsappchannel (e.g.,WatZapDriver). - The
MmsManagerinstantiates theWatZapDriverwith its specific configuration. - The
send()method on theWatZapDriveris executed, which makes the API call to WatZap. - The driver then updates the
NotificationDispatchLogrecord with the final status (sentorfailed) and the response from the API.
2. How to Use the System
To send a message, you should always do so from within a queued Job. This ensures that API calls do not slow down your main application flow. Example: Sending a WhatsApp message fromSendWhatsAppJob
The process involves three simple steps within the job’s handle() method.
MmsMessage object contains any extra data the driver might need (like a subject for email or a title for FCM).
3. How to Extend the System
Adding a new provider (e.g., a new SMS gateway) is incredibly simple:- Create a New Driver: Create a new class in the appropriate
app/Services/Mms/Drivers/sub-directory (e.g.,Sms/NewGatewayDriver.php). It must implement theSenderInterface. - Update Configuration: Add your new driver to the
config/mms.phpfile under the appropriate channel.
- Update
.env: Add the new environment variables (NEW_GATEWAY_API_KEY, etc.).
4. How to Test the System
A dedicated Artisan command,test:mms, is provided for easy development and debugging.
Command Signature:
php artisan test:mms {channel?} {--options}
Arguments & Options:
channel: (Optional) The specific channel to test. Can bewhatsapp,telegram,fcm,internal,email. If omitted, it defaults toall.--template=<slug>or-T: The slug of the notification template to use. Defaults totest-template.--params='<json>'or-P: A JSON string of parameters to fill the template. Example:'{"name":"Budi"}'.--recipient=<value>or-R: The recipient’s identifier. This is required for single-channel tests.- For
internal, this can be a User ID, email, or name. - For other channels, it’s the phone number, chat ID, FCM token, or email address.
--director-D: A boolean flag. If present, the message will be sent synchronously without being pushed to the queue. This is extremely useful for immediate feedback during development.
notification_dispatch_logs collection in your database to see the final result.
Versi Bahasa Indonesia
1. Konsep dan Arsitektur
Multi-Messaging System (MMS) adalah sebuah subsistem yang modular dan dapat diperluas, yang dirancang untuk menangani semua notifikasi keluar dari aplikasi. Sistem ini dibuat untuk menggantikan kelas utilitas monolitik, mendukung penulisan kode yang bersih, pemisahan tanggung jawab (separation of concerns), dan kemudahan dalam pemeliharaan. Arsitekturnya didasarkan pada Strategy Design Pattern, di mana logika inti untuk mengirim pesan didelegasikan ke “driver” yang dapat diganti-ganti. Komponen Inti:MmsManager(danMmsFacade): Ini adalah titik masuk utama untuk keseluruhan sistem. Ia bertanggung jawab untuk membaca konfigurasi, memilih driver yang tepat untuk channel tertentu, dan menyediakan metode bantuan seperti mengompilasi pesan dari template.- Contracts (Interfaces):
SenderInterface: Mendefinisikan aturan dasar bahwa setiap driver wajib memiliki methodsend().MessageInterface: Mendefinisikan struktur untuk objek pesan standar, memastikan data diteruskan secara konsisten.- Drivers: Ini adalah kelas konkret yang berisi logika untuk berkomunikasi dengan API pihak ketiga tertentu (misalnya, WAHA, Mailtrap, Firebase). Setiap driver mengimplementasikan
SenderInterface. MmsMessageDTO: Sebuah Data Transfer Object sederhana yang mengimplementasikanMessageInterface. Ia berfungsi sebagai “paket” standar yang membawa informasi penerima, isi pesan, dan metadata lainnya ke driver.- Konfigurasi (
config/mms.php): “Panel kontrol” untuk sistem ini. File ini mendefinisikan semua “channel” komunikasi yang tersedia (sepertiwhatsapp,email), driver mana yang tersedia untuk setiap channel, beserta kredensial dan pengaturannya. - Logging (
NotificationDispatchLog): Sistem ini terintegrasi erat dengan model logging terpadu. Setiap pesan yang dikirim, terlepas dari channel atau drivernya, statusnya akan dilacak dalam koleksinotification_dispatch_logs.
- Sebuah Job (misalnya,
SendWhatsAppJob) dijalankan (di-dispatch). - Job tersebut menggunakan
Mmsfacade untuk mengompilasi pesan dan membuat objekMmsMessage. - Job memanggil
Mms::channel('whatsapp')->send($message). MmsManagermembaca fileconfig/mms.phpuntuk menemukan driver default untuk channelwhatsapp(misalnya,WatZapDriver).MmsManagermembuat instanceWatZapDriverbeserta konfigurasinya.- Method
send()padaWatZapDriverdieksekusi, yang kemudian melakukan panggilan API ke WatZap. - Driver kemudian memperbarui catatan
NotificationDispatchLogdengan status akhir (sentataufailed) dan respons dari API.
2. Cara Menggunakan Sistem
Untuk mengirim pesan, Anda sebaiknya selalu melakukannya dari dalam sebuah Job yang berjalan di antrean (queue). Hal ini memastikan bahwa panggilan API tidak memperlambat alur utama aplikasi Anda. Contoh: Mengirim pesan WhatsApp dariSendWhatsAppJob
Prosesnya melibatkan tiga langkah sederhana di dalam method handle() milik Job.
MmsMessage berisi data tambahan apa pun yang mungkin dibutuhkan driver (seperti subject untuk email atau title untuk FCM).
3. Cara Memperluas Sistem
Menambahkan provider baru (misalnya, gateway SMS baru) sangatlah mudah:- Buat Driver Baru: Buat kelas baru di sub-direktori yang sesuai di
app/Services/Mms/Drivers/(misalnya,Sms/NewGatewayDriver.php). Kelas ini harus mengimplementasikanSenderInterface. - Perbarui Konfigurasi: Tambahkan driver baru Anda ke file
config/mms.phpdi bawah channel yang sesuai.
- Perbarui
.env: Tambahkan variabel environment baru (NEW_GATEWAY_API_KEY, dll.).
4. Cara Menguji Sistem
Sebuah command Artisan khusus,test:mms, disediakan untuk kemudahan pengembangan dan debugging.
Struktur Command:
php artisan test:mms {channel?} {--options}
Argumen & Opsi:
channel: (Opsional) Channel spesifik yang akan diuji. Bisa berupawhatsapp,telegram,fcm,internal,email. Jika tidak diisi, default-nya adalahall.--template=<slug>atau-T: “Slug” dari template notifikasi yang akan digunakan. Default-nya adalahtest-template.--params='<json>'atau-P: String JSON berisi parameter untuk mengisi template. Contoh:'{"name":"Budi"}'.--recipient=<value>atau-R: Pengenal penerima. Wajib diisi jika menguji satu channel.- Untuk
internal, bisa berupa User ID, email, atau nama. - Untuk channel lain, bisa berupa nomor telepon, chat ID, token FCM, atau alamat email.
--directatau-D: Sebuah flag boolean. Jika ada, pesan akan dikirim secara langsung (synchronous) tanpa dimasukkan ke dalam antrean (queue). Ini sangat berguna untuk mendapatkan umpan balik instan saat pengembangan.
notification_dispatch_logs di database Anda untuk melihat hasil akhirnya.