Kirim dan terima WhatsApp dari PHP dan Laravel
Untuk menerima, buat rute Laravel yang menjawab GET verifikasi dari Meta dan menerima POST, dengan membaca parameter sebagai hub_mode, hub_verify_token, dan hub_challenge karena PHP mengubah titik menjadi garis bawah. Untuk mengirim, cukup satu POST Http::withToken() ke endpoint pesan Cloud API dengan ID nomor telepon dan token milik nomor itu. Tidak perlu SDK.
PHP mengubah titik pada nama variabel masuk menjadi garis bawah, sehingga hub.challenge terbaca sebagai hub_challenge.
Rute API Laravel yang stateless, dibuat oleh install:api, dilayani di bawah /api dan berada di luar perlindungan CSRF milik grup web.
Versi Graph API mengikuti contoh kirim pesan terbaru dari Meta, pada POST /{phone-number-id}/messages.
Bagaimana cara menerima pesan WhatsApp di Laravel?
Dengan satu GET dan satu POST pada path yang sama di routes/api.php. Jalankan php artisan install:api lebih dulu jika file itu belum ada. Rute API bersifat stateless dan berada di luar grup web, jadi POST dari Meta tidak ditolak karena token CSRF yang hilang, seperti yang terjadi pada rute di routes/web.php.
GET menjawab verifikasi dari Meta. Meta mengirim hub.mode, hub.verify_token, dan hub.challenge, tetapi PHP menulis ulang titik pada nama variabel masuk menjadi garis bawah, sehingga Laravel melihat hub_mode, hub_verify_token, dan hub_challenge. Kode yang membaca nama bertitik akan mendapat null dan tidak pernah lolos verifikasi. Kembalikan challenge sebagai teks biasa, bukan lewat response()->json().
POST menyerahkan payload ke job dalam antrean lalu langsung mengembalikan 200. Taruh kunci acak yang panjang di path dan periksa pada kedua rute: Meta menandatangani pengiriman dengan app secret milik Tech Provider, sehingga header tanda tangan tidak bisa divalidasi di sisi Anda.
use App\Jobs\HandleWhatsAppEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('/whatsapp/{key}', function (Request $request, string $key) {
abort_unless(hash_equals(config('services.whatsapp.url_key'), $key), 404);
// PHP turns hub.mode into hub_mode: read the underscored names
if ($request->query('hub_mode') === 'subscribe'
&& hash_equals(config('services.whatsapp.verify_token'),
(string) $request->query('hub_verify_token'))) {
return response((string) $request->query('hub_challenge'), 200)
->header('Content-Type', 'text/plain');
}
abort(403);
});
Route::post('/whatsapp/{key}', function (Request $request, string $key) {
abort_unless(hash_equals(config('services.whatsapp.url_key'), $key), 404);
HandleWhatsAppEvent::dispatch($request->json()->all());
return response('', 200);
});Bagaimana cara mengirim pesan WhatsApp dari Laravel?
Dengan HTTP client Laravel: satu POST ke endpoint pesan untuk ID nomor telepon, dengan access token sebagai bearer token. Kedua nilai ini berasal dari koneksi, tampil di dashboard dan dikembalikan oleh get_api_credentials, dan sebaiknya disimpan di config/services.php dengan dukungan variabel lingkungan, bukan di dalam kode.
Bentuk body bergantung pada waktu. Dalam 24 jam sejak pesan terakhir pelanggan, objek text bisa dipakai, seperti contoh di bawah. Di luar jendela itu Meta hanya menerima objek template yang menyebut template yang sudah disetujui beserta bahasanya, dan teks bebas gagal dengan kesalahan 131047. Respons adalah tempat untuk melihatnya: panggilan yang gagal mengembalikan objek kesalahan yang kodenya menjelaskan apa yang salah, jadi catat di log, jangan dibuang.
Tidak ada bagian dari permintaan ini yang khusus untuk EasyCoexistence. Ini adalah panggilan yang ada di dokumentasi Meta sendiri, sehingga HTTP client PHP apa pun, Guzzle atau cURL biasa, bekerja dengan cara yang sama.
use Illuminate\Support\Facades\Http;
$response = Http::withToken(config('services.whatsapp.token'))
->post('https://graph.facebook.com/v25.0/'
. config('services.whatsapp.phone_number_id') . '/messages', [
'messaging_product' => 'whatsapp',
'to' => '14155550188', // digits only, with country code
'type' => 'text',
'text' => ['body' => 'Thanks, we are on it.'],
]);
if ($response->failed()) {
// error.code 131047: outside the window, send a template instead
logger()->warning('WhatsApp send failed', $response->json('error', []));
}Apa lagi yang dibutuhkan handler Laravel di produksi?
Antrean yang sungguhan, deduplikasi, dan pemeriksaan jendela.
Antrean penting karena Meta mencoba kembali pengiriman jika respons lambat. HandleWhatsAppEvent::dispatch() hanya kembali dengan cepat bila koneksi antreannya sungguhan dan ada worker yang berjalan. Pada driver sync, job berjalan di dalam permintaan, dan pemanggilan model yang lambat atau penulisan database berubah menjadi pengiriman ganda.
Lakukan deduplikasi berdasarkan ID pesan, yaitu wamid pada setiap pesan, karena percobaan ulang itu hal biasa, bukan pengecualian. Unique index pada kolom itu, atau cache lock dengan kunci tersebut, sudah cukup.
Dan simpan kapan setiap kontak terakhir menulis. Dengan stempel waktu itu, jalur pengiriman memilih text atau template sendiri, tidak perlu mengetahuinya dari kesalahan 131047 setelah pelanggan terlanjur menunggu. Balasan yang diketik di ponsel pada aplikasi WhatsApp Business tiba sebagai event echo pada rute yang sama, sehingga handler juga bisa melihat kapan seseorang mengambil alih percakapan.
Kesalahan umum
- Membaca hub.challenge dengan titik. PHP sudah mengubahnya menjadi hub_challenge, sehingga handler mengembalikan body kosong dan Meta tidak pernah memverifikasi.
- Menaruh webhook di routes/web.php. POST dari Meta tidak membawa token CSRF dan ditolak dengan 419.
- Mengirim job ke antrean sync. Job berjalan sebelum 200 dikirim, penanganan yang lambat dicoba kembali, dan pesan diproses dua kali.
- Mengembalikan challenge dengan response()->json(). Tanda kutip di sekitar nilainya membuat pemeriksaan Meta gagal.
Hubungkan nomor di easycoexistence.com, arahkan tujuan webhook ke rute Laravel Anda dengan kuncinya di path, lalu baca ID nomor telepon dan token dari dashboard. Mulai US$ 9 per nomor per bulan, turun menjadi US$ 1 seiring bertambahnya nomor, dengan 3 hari pertama gratis.
Pertanyaan yang sering diajukan
Apakah ada SDK PHP?
Tidak dari kami, dan tidak diperlukan. API-nya milik Meta, didokumentasikan oleh Meta, dan HTTP client Laravel atau Guzzle langsung bisa menjangkaunya.
Apakah ini bisa dipakai tanpa Laravel?
Bisa. Di PHP biasa, baca $_GET['hub_challenge'], tampilkan sebagai text/plain, dan kirim dengan cURL. Aturan garis bawah berlaku untuk setiap framework PHP.
Mengapa URL perlu kunci di path?
Karena itulah autentikasi yang berfungsi. Tanda tangan Meta memakai app secret milik Tech Provider yang tidak pernah dibagikan, jadi rahasia di URL yang mencegah orang asing mengirim event palsu.
Apakah tim masih bisa memakai ponsel?
Bisa. Coexistence menjaga aplikasi WhatsApp Business tetap berfungsi pada nomor itu, dan pesan yang dikirim dari ponsel sampai ke rute Anda sebagai event echo.
Lanjut membaca
Siap memulai?
Konfigurasikan WhatsApp Coexistence dalam hitungan menit, bukan bulan. Aplikasi tetap berfungsi di ponsel.
Mulai uji coba gratisDiverifikasi pada