WhatsApp memiliki lebih dari 2 miliar pengguna aktif dan menjadi channel komunikasi bisnis yang sangat penting di Indonesia. Membangun chatbot WhatsApp memungkinkan Anda mengotomatiskan CS, notifikasi order, reminder, hingga integrasi dengan sistem internal. Artikel ini membahas cara membangunnya dengan PHP menggunakan API resmi atau unofficial API.
Opsi API WhatsApp
1. WhatsApp Business API (Cloud API) — Resmi
Dari Meta sendiri. Gratis untuk volume tertentu, kemudian berbayar per-conversation. Cocok untuk bisnis skala menengah-besar yang butuh keandalan production-grade.
- Daftar di developers.facebook.com
- Verifikasi bisnis diperlukan
- Template message harus disetujui Meta dulu
2. Unofficial API (Baileys, wa-js, dll.)
Library third-party yang mensimulasikan WhatsApp Web. Mudah disetup, gratis, tapi risiko banned account dan tidak stabil untuk production serius.
3. API Aggregator Lokal (Fonnte, WaBlas, dll.)
Layanan Indonesia yang menyederhanakan integrasi WhatsApp. Bayar berdasarkan volume pesan. Cocok untuk use case sederhana dengan setup cepat.
Implementasi dengan WhatsApp Cloud API (Meta)
Setup Webhook di Laravel
// routes/web.php
Route::get('/webhook/whatsapp', [WhatsAppController::class, 'verify']);
Route::post('/webhook/whatsapp', [WhatsAppController::class, 'handle']);
// app/Http/Controllers/WhatsAppController.php
class WhatsAppController extends Controller
{
public function verify(Request $request): Response
{
$mode = $request->query('hub_mode');
$token = $request->query('hub_verify_token');
$challenge = $request->query('hub_challenge');
if ($mode === 'subscribe' && $token === config('services.whatsapp.verify_token')) {
return response($challenge, 200);
}
return response('Forbidden', 403);
}
public function handle(Request $request): JsonResponse
{
$payload = $request->json()->all();
// Proses setiap entry
foreach ($payload['entry'] ?? [] as $entry) {
foreach ($entry['changes'] ?? [] as $change) {
$value = $change['value'] ?? [];
// Pesan masuk
foreach ($value['messages'] ?? [] as $message) {
ProcessWhatsAppMessage::dispatch($message, $value['metadata']);
}
// Status update (delivered, read, dll.)
foreach ($value['statuses'] ?? [] as $status) {
$this->handleStatusUpdate($status);
}
}
}
return response()->json(['status' => 'ok']);
}
}
Job untuk Proses Pesan
// app/Jobs/ProcessWhatsAppMessage.php
class ProcessWhatsAppMessage implements ShouldQueue
{
use Dispatchable, Queueable;
public function __construct(
private readonly array $message,
private readonly array $metadata,
) {}
public function handle(WhatsAppService $whatsapp, ChatbotEngine $chatbot): void
{
$from = $this->message['from'];
$msgType = $this->message['type'];
// Hanya proses pesan teks untuk chatbot sederhana
if ($msgType !== 'text') {
$whatsapp->send($from, 'Maaf, saat ini saya hanya bisa memproses pesan teks.');
return;
}
$text = $this->message['text']['body'];
$response = $chatbot->process($from, $text);
$whatsapp->send($from, $response);
}
}
Service untuk Kirim Pesan
// app/Services/WhatsAppService.php
class WhatsAppService
{
private string $apiUrl;
private string $token;
public function __construct()
{
$this->apiUrl = 'https://graph.facebook.com/v18.0/' . config('services.whatsapp.phone_id');
$this->token = config('services.whatsapp.token');
}
public function send(string $to, string $message): bool
{
$response = Http::withToken($this->token)
->post("{$this->apiUrl}/messages", [
'messaging_product' => 'whatsapp',
'to' => $to,
'type' => 'text',
'text' => ['body' => $message],
]);
return $response->successful();
}
public function sendTemplate(string $to, string $template, array $params = []): bool
{
$response = Http::withToken($this->token)
->post("{$this->apiUrl}/messages", [
'messaging_product' => 'whatsapp',
'to' => $to,
'type' => 'template',
'template' => [
'name' => $template,
'language' => ['code' => 'id'],
'components' => [
['type' => 'body', 'parameters' => array_map(
fn ($p) => ['type' => 'text', 'text' => $p],
$params
)],
],
],
]);
return $response->successful();
}
}
Chatbot Engine Sederhana
// app/Services/ChatbotEngine.php
class ChatbotEngine
{
private array $states = [];
public function process(string $userId, string $message): string
{
$text = strtolower(trim($message));
$state = $this->getState($userId);
return match (true) {
$this->isGreeting($text) => $this->handleGreeting($userId),
$text === 'cek order' => $this->handleOrderCheck($userId),
$text === 'harga' => $this->handlePriceList(),
$state === 'awaiting_order_id' => $this->lookupOrder($userId, $message),
$text === 'bantuan' => $this->handleHelp(),
default => $this->handleUnknown(),
};
}
private function handleGreeting(string $userId): string
{
return "Halo! 👋 Selamat datang di layanan kami.\n\n"
. "Ketik salah satu:\n"
. "• *cek order* — Cek status pesanan\n"
. "• *harga* — Lihat daftar harga\n"
. "• *bantuan* — Hubungi CS";
}
private function handleOrderCheck(string $userId): string
{
$this->setState($userId, 'awaiting_order_id');
return "Silakan masukkan nomor order Anda (contoh: ORD-2025-001):";
}
private function lookupOrder(string $userId, string $orderId): string
{
$this->clearState($userId);
$order = Order::where('order_number', strtoupper(trim($orderId)))->first();
if (! $order) {
return "Nomor order *{$orderId}* tidak ditemukan. Pastikan penulisan sudah benar.";
}
return "📦 *Status Order {$order->order_number}*\n"
. "Status: {$order->status_label}\n"
. "Total: Rp " . number_format($order->total, 0, ',', '.') . "\n"
. "Tanggal: {$order->created_at->format('d M Y')}";
}
private function getState(string $userId): ?string
{
return Cache::get("chatbot_state_{$userId}");
}
private function setState(string $userId, string $state): void
{
Cache::put("chatbot_state_{$userId}", $state, now()->addMinutes(10));
}
}
Dengan arsitektur ini, chatbot WhatsApp Anda bisa menangani ribuan pesan per hari melalui queue worker. Untuk menjadikannya lebih cerdas, integrasikan dengan OpenAI API di handleUnknown() sebagai fallback — sehingga pertanyaan di luar menu tetap mendapat jawaban yang relevan.